如何获取Win32接口DrawText()将为其添加下划线的对应字符
你观察到的DrawText()给字符加下划线的逻辑,是对字符串中&前缀的助记符处理结果:单个&后的第一个字符会被标记为助记符并加下划线,连续&&会被渲染为单个&且不生成助记符。
你不需要自己实现解析逻辑,直接用Win32原生API就可以拿到结果,天然支持日文等多语言字符,实现方案如下:
解决方案
使用DrawTextW(宽字符版本,支持所有Unicode字符包括日文)配合专属标志位即可直接获取结果,完全和实际渲染逻辑一致,不会出现自行解析的偏差:
核心原理
调用DrawTextW时传入DT_CALCRECT + DT_PREFIXONLY标志组合:
DT_CALCRECT让API只计算参数不实际绘制内容,不会产生UI副作用DT_PREFIXONLY让API仅处理助记符逻辑,返回值直接是助记符在原字符串中的下标
代码示例
#include <windows.h> #include <string> /** * 获取DrawText会加下划线的助记符 * @param str 传入的原始字符串,宽字符版本支持日文等Unicode内容 * @param drawTextFlags 你实际调用DrawText时用的其他标志位,保证和渲染逻辑一致 * @return 会被加下划线的助记符,无有效助记符时返回0 */ WCHAR GetUnderlineCharForDrawText(const std::wstring& str, UINT drawTextFlags = 0) { // 叠加核心标志位 UINT calculateFlags = DT_CALCRECT | DT_PREFIXONLY | DT_SINGLELINE | drawTextFlags; RECT dummyRect = {0}; HDC hdc = GetDC(NULL); int mnemonicIndex = DrawTextW(hdc, str.c_str(), static_cast<int>(str.size()), &dummyRect, calculateFlags); ReleaseDC(NULL, hdc); // 校验下标合法性 if (mnemonicIndex < 0 || mnemonicIndex >= static_cast<int>(str.size())) { return 0; } return str[mnemonicIndex]; }
测试验证
传入你示例的字符串 L"my rando&m string" 调用该函数,返回结果就是 L'm',和你观察到的DrawText()渲染结果完全一致。
注意事项
如果你实际绘制时传入了DT_NOPREFIX标志,DrawText()会跳过助记符处理,不会有下划线字符,此时调用上述函数也会返回0,和实际表现对齐。
内容的提问来源于stack exchange,提问作者MAG
相关产品推荐
相关产品推荐

