LOGFONT文本旋转导致字体尺寸变化:如何保持旋转前后文本尺寸一致?
解决GDI文本旋转270度时字体尺寸变大的问题
这个问题的核心在于GDI对旋转字体的LOGFONT参数逻辑解释发生了变化——当你把lfEscapement和lfOrientation设为2700(对应270度)时,文本排版方向完全反转,此时你设置的lfHeight不再代表字符的垂直高度,而是被当成字符的水平宽度处理,最终导致渲染出的字体看起来比未旋转时大。
解决方案:匹配旋转前后的字体尺寸
最可靠的方式是先获取未旋转字体的实际尺寸,再用这个尺寸配置旋转后的字体,确保两者视觉大小一致。具体步骤如下:
创建临时未旋转字体,获取文本度量信息
先创建一个样式目标一致但未旋转的字体,通过GetTextMetrics拿到它的平均字符宽度——这个值就是旋转后字体需要的“高度”参数。用获取到的尺寸创建旋转字体
将旋转字体的lfHeight设置为负的平均字符宽度(负值告诉GDI使用字体的em高度计算,保证尺寸匹配更准确),同时保持其他样式参数和未旋转字体一致。
下面是修改后的完整代码示例:
HDC hdc = CreateCompatibleDC(NULL); // 第一步:创建未旋转字体,获取文本度量 LOGFONT lfNormal = {0}; lfNormal.lfHeight = 40; lfNormal.lfWidth = 0; lfNormal.lfEscapement = 0; lfNormal.lfOrientation = 0; lfNormal.lfWeight = FW_SEMIBOLD; lfNormal.lfItalic = 0; lfNormal.lfUnderline = 0; lfNormal.lfStrikeOut = 0; lfNormal.lfCharSet = DEFAULT_CHARSET; lfNormal.lfOutPrecision = OUT_DEFAULT_PRECIS; lfNormal.lfClipPrecision = CLIP_DEFAULT_PRECIS; lfNormal.lfQuality = DEFAULT_QUALITY; lfNormal.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; strcpy(lfNormal.lfFaceName, "Arial"); HFONT hFontNormal = CreateFontIndirect(&lfNormal); HFONT hOldFont = (HFONT)SelectObject(hdc, hFontNormal); TEXTMETRIC tm; GetTextMetrics(hdc, &tm); // 清理临时字体 SelectObject(hdc, hOldFont); DeleteObject(hFontNormal); // 第二步:创建270度旋转字体,匹配尺寸 LOGFONT lfRotated = {0}; lfRotated.lfHeight = -tm.tmAveCharWidth; // 用未旋转字体的平均宽度作为旋转后的高度(负值保证计算准确) lfRotated.lfWidth = 0; lfRotated.lfEscapement = 2700; lfRotated.lfOrientation = 2700; lfRotated.lfWeight = FW_SEMIBOLD; lfRotated.lfItalic = 0; lfRotated.lfUnderline = 0; lfRotated.lfStrikeOut = 0; lfRotated.lfCharSet = DEFAULT_CHARSET; lfRotated.lfOutPrecision = OUT_DEFAULT_PRECIS; lfRotated.lfClipPrecision = CLIP_DEFAULT_PRECIS; lfRotated.lfQuality = DEFAULT_QUALITY; lfRotated.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; strcpy(lfRotated.lfFaceName, "Arial"); HFONT hFontRotated = CreateFontIndirect(&lfRotated); hOldFont = (HFONT)SelectObject(hdc, hFontRotated); // 绘制旋转文本 TextOut(hdc, 120, 79, "hello", strlen("hello")); // 清理资源 SelectObject(hdc, hOldFont); DeleteObject(hFontRotated); DeleteDC(hdc);
额外注意点
- 不要把
lfOutPrecision、lfClipPrecision、lfQuality设为0,使用系统默认的宏(比如OUT_DEFAULT_PRECIS)可以提升不同字体和设备的兼容性。 - 如果你的HDC使用了非默认的映射模式(比如
MM_LOMETRIC),可能需要额外调整坐标或尺寸参数,但默认的MM_TEXT模式下上面的代码可以直接生效。
内容的提问来源于stack exchange,提问作者theBigCheese88
相关产品推荐
相关产品推荐

