-1

编辑在不同的程序中(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 相同。他们都返回宽度为32GetCaretPos{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

你能解释一下吗?

4

2 回答 2

1

文档GetCaretPos说_ _

此 API 不参与 DPI 虚拟化。

另一方面,您提到的其他两个功能确实参与了 DPI 虚拟化。

于 2019-07-17T12:23:50.867 回答
0

'WM_GETFONT' 返回值是控件使用的字体的句柄,如果控件使用系统字体,则返回 NULL。你可以试一试:

HFONT hFont =(HFONT)SendMessage(edit,WM_GETFONT,0,0); 
if(NULL == hFont)
hFont =(HFONT)GetStockObject(SYSTEM_FONT);
于 2019-07-18T10:02:35.207 回答