GetDC()和BeginPaint()之间的区别?

时间:2016-03-16 19:18:21

标签: winapi mfc

我在对话框中的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);
}

1 个答案:

答案 0 :(得分:3)

GetDC()BeginPaint()都不会使用默认系统字体以外的任何内容初始化它们返回的DC。但是WM_DRAWITEM是不同的 - 它会为您提供一个已经初始化的DC来吸引。

你偶然发现的方法是正确的。 WM_MEASUREITEM根本不提供DC,因此如果您需要一个用于尺寸计算,则您需要负责获取并使用适当的字体进行设置。

相关问题