编辑在不同的程序中(DPI 不知道)。我的程序正在尝试获取文本宽度。
std::wstring text = L"1234";
HWND edit = 0x04AC1BF0;
// AttachThreadInput
// ...
auto ret1 = ::GetCaretPos(&pt1); // pt1 => {x=1 y=1}
// Set text to "1234" here
// ...
::Sleep(3000);
auto ret2 = ::GetCaretPos(&pt2); // pt2 => {x=25 y=1}
HDC hdc = GetDC(edit);
auto hFont = (HFONT)SendMessage(edit, WM_GETFONT, 0, 0);
auto oldObj = SelectObject(hdc, hFont);
CSize size1;
auto ret3 = GetTextExtentPoint32(hdc, text.c_str(), text.size(), &size1); // size1 => {cx=32 cy=16}
CRect rect1;
DrawText(hdc, text.c_str(), text.size(), &rect1, DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE); // {LT(0, 0) RB(32, 16) [32 x 16]}
SelectObject(hdc, oldObj);
ReleaseDC(edit, hdc);
所以GetTextExtentPoint32
行为与 DrawText 相同。他们都返回宽度为32
。GetCaretPos
从{1, 1}
变为的结果{25, 1}
,表示宽度为24
。
我的电脑上的 DPI 是 150%。如果我将 DPI 设置为 100%,这些 API 返回值不会改变。所以我认为这不是因为 DPI 影响。
这两个API有什么关系?
使用 API 监控工具,我可以看到程序本身调用 GetTextExtentPoint32A 并返回[24, 12]
. 其行为类似于 GetCaretPos。
我怎样才能得到与目标进程本身相同的结果?
现在事情变得更有趣了!如果我创建字体并再次选择它,则GetTextExtentPoint32
返回[24, 12]
!
LOGFONT font = { 0 };
::GetObject(hFont, sizeof(LOGFONT), &font);
hFont = ::CreateFontIndirect(&font);
auto oldObj = ::SelectObject(hdc, hFont);
如果我在重新创建之前使用 DrawText 进行编辑,我可以看到字体是Bold
,但是在重新创建和重新绘制字体之后,它看起来是Normal
。
你能解释一下吗?