【问题标题】:C++ GetTextExtentPoint32 doesn't give the correct size [duplicate]C ++ GetTextExtentPoint32没有给出正确的大小[重复]
【发布时间】:2021-03-25 08:50:12
【问题描述】:

我正在尝试使用GetTextExtentPoint32 获取文本字符串的大小。我多次阅读文档并进行了一些研究,据我所知,下面的代码应该给我正确的 widthheight 文本。

vFontFamily = "Segoe UI"; //font family
vFontSize = 26; //font size

HDC hdc = GetDC(hwnd);
HFONT hFont = CreateFont(
     -MulDiv(vFontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72), //calculate the actual cHeight.
      0, 0, 0, // normal orientation
      FW_NORMAL,   // normal weight--e.g., bold would be FW_BOLD
      false, false, false, // not italic, underlined or strike out
      DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, // select only outline (not bitmap) fonts
      CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH | FF_SWISS, vFontFamily);

SIZE size;
HFONT oldfont = (HFONT)SelectObject(hdc, hFont);
GetTextExtentPoint32(hdc, L"This is Text", wcslen(L"This is Text"), &size);

width = size.cx; //get width
height = size.cy; //get height

SelectObject(hdc, oldfont); //don't forget to select the old.
DeleteObject(hFont); //always delete the object after creating it.
ReleaseDC(hwnd, hdc); //alway reelase dc after using.

很遗憾,它没有给我正确的尺寸。宽度太大至少 10%,高度太大至少 5%。确切地说,This is Text 文本中宽度的结果是228,高度是62,而我认为更准确的结果是接近190 x 55

文字是使用GDI+绘制的。

case WM_PAINT: {
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    Graphics g(hdc);
    
    FontFamily  theFontFamily(vFontFamily);
    Font        font(&theFontFamily, vFontSize, FontStyleRegular, UnitPixel);
    SolidBrush  brush(Color(255, R, G, B));
    PointF      pointF(0.0f, 0.0f);

    TextRenderingHint hint = g.GetTextRenderingHint(); // Get the text rendering hint.
    g.SetTextRenderingHint(TextRenderingHintAntiAlias); // Set the text rendering hint to TextRenderingHintAntiAlias. 
    g.DrawString(L"This is Text", strlen("This is Text"), &font, pointF, &brush);

    EndPaint(hwnd, &ps);
    return TRUE;
}

我在想这可能与我绘制文本的方式有关,因为在绘制消息中,我使用了Font 而不是HFONT。但这没有任何意义,对吧?只要我在GetTextExtentPoint32 之前设置了正确的字体系列和字体大小,它就会给我准确的文本宽度和高度。你怎么看?

【问题讨论】:

  • 大概以与绘制文本相同的方式测量文本会产生更好的结果?例如docs.microsoft.com/en-us/windows/win32/api/gdiplusgraphics/…
  • GetTextExtentPoint32、DrawText、GDI+和DriectWrite函数之间存在细微差别。较大的差异 (>2%) 通常是由使用不同的字体引起的。在您的情况下,经典 GDI 字体的负尺寸(不包括内部前导)和正尺寸(包括内部前导)之间可能存在差异。尝试在 MulDiv 之前删除 -

标签: c++ winapi visual-studio-2019 gdi+


【解决方案1】:

您使用GDI 测量文本,而使用GDI+ 绘制文本。

GDI+ 是对 GDI 的改进,当您使用它来渲染文本等时,两者之间存在差异。另一件事是DPI Awareness,在测量文本时,您也需要确保处理缩放.与使用 GDI+ 绘制的实际宽度和高度相比,如果您在测量时未正确处理 DPI,则您的方法将获得更大的结果。

尝试使用Graphics::MeasureString,看看你是否得到了预期的宽度和高度。就像AlanBirtles 在评论中所说的那样,按照您绘制字符串的方式进行操作。

例如,

HDC hdc = GetDC(hwnd);                                                      //get dc of your handle.
Graphics graphics(hdc);                                                     //setup graphics.
FontFamily  theFontFamily(vFontFamily);                                     //setup your font family.
Font        font(&theFontFamily, vFontSize, FontStyleRegular, UnitPixel);   //create the font the same way how you do it on your paint message.
PointF      pointF(0.0f, 0.0f);                                             //use PointF instead of RectF since thats how you paint it.

RectF boundRect;                                                            //setup boundRect to get the width and height.
graphics.MeasureString(text, -1, &font, pointF, &boundRect);                //Measure the text of the string
//or
//graphics.MeasureString(L"This is Text", strlen("This is Text"), pointF, &boundRect);

width = boundRect.Width;                                                    //get the width of text from boundRect.
height = boundRect.Height;                                                  //get the height of text from boundRect.

DeleteObject(&font);                                                        //delete the font.
ReleaseDC(LabelHandle, hdc);                                                //always reelase dc after using.

如果您需要更多解释,以下内容可能会对您有所帮助。

How to automatically set the width and height of static control base on its content?

GDI+ font size difference under different processes on same machine

DPI-awareness is really needed?

How to draw a GDI + text independent of DPI

https://stackoverflow.com/questions/4551224/what-is-the-difference-between-gdi-and-gdi#:~:text=GDI%2B%20is%20object%20oriented%2C%20and,in%20some%20ways%20GDI%20usage.&text=GDI%2B%20is%20an%20improvement%20on,and%20more%20image%20format%20support.

【讨论】:

  • 哇,这个真的有效。无论如何,如果可能的话,我想了解为什么我的方法不起作用?
  • @Papilion 我添加了更多解释。
猜你喜欢
  • 2020-05-06
  • 1970-01-01
  • 2021-04-03
  • 2016-05-02
  • 2021-10-07
  • 1970-01-01
  • 2020-10-26
  • 1970-01-01
  • 2023-03-30
相关资源
最近更新 更多