问题描述
我正在尝试使用 GetTextExtentPoint32 获取文本字符串的大小。我多次阅读文档并做了一些研究,据我所知,下面的代码应该给我正确的 width
和 height
文本。
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,// normal orientation
FW_norMAL,// normal weight--e.g.,bold would be FW_BOLD
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
之前设置了正确的字体系列和字体大小,它就应该为我提供文本的确切宽度和高度。你怎么看?
解决方法
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"),&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?