【发布时间】:2016-07-02 21:15:27
【问题描述】:
我的一些所有者在 Windows 10 的高 DPI 监视器上在对话框中绘制的列表框时遇到问题。文字在底部被截断。我们在 Windows 7 上看到了这个问题并且能够修复它。它不一定是高 DPI,而是当用户设置不同的文本缩放时。我解决了这个问题,所以我想(!),通过使用 CClientDC(围绕 GetDC() 的包装器)并调用 GetTextMetrics() 来确定文本高度。以前,我们的图标总是比我们的文本高,所以这不是问题。对于更大的 DPI 监视器,我们看到一些客户在缩放文本时报告了问题。
现在我们在 Windows 10 下获得了新的报告。前一个问题在 Windows 7 下很好,但 Windows 7 只能扩展到 100%、125% 和 150%。 Windows 10(可能还有 8?-- 但没有客户报告)允许用户定义扩展。
所以,我在某种程度上找到了问题...当我在 WM_MEASUREITEM 期间调用 GetTextMetrics() 时,我知道字体高度是多少。我去放了一些代码来调试在我的 WM_DRAWITEM 期间 GetTextMetrics() 是什么。嗯,它们是不同的——在 WM_MEASUREITEM 期间高 20 像素,在 WM_DRAWITEM 期间高 25 像素。显然,这是一个问题。我希望 GetTextMetrics() 在两个地方都有相同的结果。
我的想法是,我能想到的唯一真正区别是,在 WM_MEASUREITEM 期间,我通过 CClientDC 构造函数调用 GetDC(),而在 WM_DRAWITEM 期间,我使用的是已经构建的 HDC(可能来自 GetPaint( ) 在 GDI32.dll 或其他系统 DLL 中)。
我认为 BeginPaint() 可能会执行一些操作,例如将 Windows HFONT 选择到 HDC 中...
所以,在我的 WM_MEASUREITEM 中,获得 DC 后,我将列表框的字体选择到 HDC 中,然后调用 GetTextMetrics()。瞧,现在 WM_MEASUREITEM 和 WM_DRAWITEM 中的数字匹配了。
但是,我不知道我是不是走运了。目前这一切都只是猜测。
BeginPaint() 是否将窗口字体选择到 DC 而 GetDC() 没有?所有者绘制的 LISTBOX 或 COMBOBOX 的 WM_PAINT 的默认处理程序是否执行诸如将窗口字体选择到绘图 DC 中的操作?
BOOL DpiAwareMeasureGraphItem(LPMEASUREITEMSTRUCT lpM, CWnd* pWnd)
{
int iItemHeight = INTERG_BITMAP_HEIGHT + 4;
if (pWnd)
{
CClientDC dc(pWnd);
if (dc.GetSafeHdc())
{
CFont* pOldFont = dc.SelectObject(pWnd->GetFont()); // seems to fix it on Windows 10, but is it luck?
TEXTMETRIC tm;
memset(&tm, 0, sizeof(tm));
dc.GetTextMetrics(&tm);
LONG tmHeight = tm.tmHeight + 4; //pad
iItemHeight = max(iItemHeight, tmHeight);
dc.SelectObject(pOldFont);
}
}
lpM->itemHeight = iItemHeight;
return (TRUE);
}
【问题讨论】:
-
Windows 7,甚至是 Vista,允许用户自定义字体缩放
-
谢谢。我去设置“证明你错了”,因为我从未见过它。然后我查看了左侧窗格,看到了我以前从未“见过”的设置。