Win GDI DrawText 渲染错误

Posted

技术标签:

【中文标题】Win GDI DrawText 渲染错误【英文标题】:Win GDI DrawText bad rendering 【发布时间】:2021-09-06 22:57:18 【问题描述】:

直到今天,在使用 DrawText 渲染之前,我一直使用 GetTextExtentPoint32 来测量要渲染的文本。

由于我现在需要渲染多行文本,我必须使用 DrawTextDT_CALCRECT(因为 GetTextExtentPoint32 忽略换行符)。

但是,这会导致文本呈现不同,主要是通过减少字符间距。例如:

底部渲染是更改后的。 我已经隔离了问题,只需在使用GetTextExtentPoint32 的原始输出时调用第一个DrawText - 问题仍然存在。

以下是调用顺序的缩减:

::GetTextExtentPoint32(...); // Result is used
::DrawText(... DT_CALCRECT); // Result is unused
BITMAPINFOHEADER bih =  size values from GetTextExtentPoint32 ;
hBitMap = ::CreateDIBSection(... (BITMAPINFO*)&bih, ...); 
::SelectObject (hdc, hBitMap);
::DrawText(...); // Render the text

注意,我是否删除第二行中的DT_CALCRECT 并不重要。对DrawText 之前 CreateDIBSection 的调用似乎是罪魁祸首。

我还应该尝试什么?

【问题讨论】:

如果这是我认为的错误,那么这是一个错误,其中某些内部浮点定位状态保留在 GDI 中的某处。在某些情况下(尤其是工具提示),同样的错误也会导致带有 .NET 框架的 GDI+ 中出现错误的字符间距。几年前我找到了确切的问题,并在一些文章中找到了提示,但不幸的是我不记得细节了。 试图筛选一些旧程序;不确定,但您可以通过在 DC 中选择不同的 HFONT 来解决此问题,然后选择回您实际想要绘制的字体,可能就在“真实”DrawText 调用之前。 【参考方案1】:

在字体创建过程中,LOGFONT 中的字体质量和精度标志如何?您是否尝试过看看是否有所作为?

最后一句我也没看懂。您是说如果您删除 DrawText (... DT_CALC) 或 CreateDIBSection 之后将其移动,结果会有所不同,而字符间距不会出错?

【讨论】:

我的意思是两件事:(1) 如果我将 DrawText 保留在适当的位置(第 2 行)但在没有 DT_CALCRECT 的情况下使用它,问题仍然存在。 (2) 如果我将第二行移到 CreateDIBSection 之后,问题就消失了 这确实很奇怪。但老实说,如果我要将文本渲染成位图,我通常会先有一个位图设置代码,然后是所有绘图。因此,根据您的发现,这种流程不会产生奇怪的结果。 我希望我能做到。但是位图设置代码需要传递渲染大小,因此文本测量...

以上是关于Win GDI DrawText 渲染错误的主要内容,如果未能解决你的问题,请参考以下文章

System.Drawing.Bitmap.GetHicon() 上的 GDI 对象泄漏

System.Runtime.InteropServices.ExternalException: GDI+ 中发生一般性错误。

如何解决 winforms 错误“GDI+ 中发生一般错误。”?

GDI+ DrawImage 在 C++ (Win32) 中比在 C# (WinForms) 中慢得多

无预览打印本地报告 - 超出流大小或GDI + C#中发生一般错误

H265播放器EasyPlayer-RTSP WIN版播放器D3D和GDI两种渲染模式效果比较