该编辑位于其他程序中(不了解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
。
您能解释一下吗?
答案 0 :(得分:1)
GetCaretPos
的{{3}}说
此API不参与DPI虚拟化。
另一方面,您提到的其他两个功能确实参与了DPI虚拟化。
答案 1 :(得分:0)
'WM_GETFONT'返回值是控件使用的字体的句柄,如果控件使用的是系统字体,则返回NULL。 您可以尝试一下:
HFONT hFont =(HFONT)SendMessage(edit,WM_GETFONT,0,0);
if(NULL == hFont)
hFont =(HFONT)GetStockObject(SYSTEM_FONT);