The edit is in a different program (DPI unaware). My program is trying to get the text width.
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);
So GetTextExtentPoint32 behaves the same as DrawText. They both returns width as 32. Result of GetCaretPos changes from {1, 1} to {25, 1}, means the width is 24.
DPI is 150% on my computer. Those APIs return values don't change if I set DPI it to 100%. So I think it is not because of DPI impact.
What's the relationship of those 2 APIs?
With API monitor tool, I can see the program itself calls GetTextExtentPoint32A and returns [24, 12]. That behaves similar to GetCaretPos.
How could I get the same result as the target process itself?
Things become more interesting now! If I create the font and select it again, then GetTextExtentPoint32 returns [24, 12]!
LOGFONT font = { 0 };
::GetObject(hFont, sizeof(LOGFONT), &font);
hFont = ::CreateFontIndirect(&font);
auto oldObj = ::SelectObject(hdc, hFont);
If I DrawText to the edit before recreation, I can see the font is Bold, but after font recreation and redrawn, it looks Normal.
Could you explain this?
The documentation for
GetCaretPossaysOn the other hand, the other two functions that you mention do participate in DPI virtualization.