我在对话框中的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()可以选择将窗口HFONT选入HDC ......
所以,在获取DC之后在我的WM_MEASUREITEM中,我选择列表框的字体到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);
}
答案 0 :(得分:3)
GetDC()
或BeginPaint()
都不会使用默认系统字体以外的任何内容初始化它们返回的DC
。但是WM_DRAWITEM
是不同的 - 它会为您提供一个已经初始化的DC
来吸引。
你偶然发现的方法是正确的。 WM_MEASUREITEM
根本不提供DC
,因此如果您需要一个用于尺寸计算,则您需要负责获取并使用适当的字体进行设置。