通过EM_FORMATRANGE缩放富编辑控件的渲染输出时的舍入错误

Jam*_*ton 5 c c++ windows winapi richtextbox

我正在使用该EM_FORMATRANGE消息将富文本控件的输出呈现给任意设备上下文.但是,当渲染到位图时,位图的设备上下文的每英寸点数与显示设备的DPI相同,即每英寸96点.这比我想呈现的要低得多.我宁愿渲染更高的DPI,以便用户可以放大,也许以后可以在高DPI打印机上打印.

我怀疑会发生什么情况是,RTF控件调用GetDeviceCapsLOGPIXELSXLOGPIXELSY获取装置的每英寸的像素数.然后,它使用此DPI值以100%缩放级别呈现文档.除非在系统上使用大字体(在控制面板中设置)并且应用程序支持DPI,否则Windows显示设备始终返回96 DPI的值.

互联网上的许多例子都建议扩大产量EM_FORMATRANGE.这样可以实现任何任意的DPI分辨率.大多数示例通常涉及使用SetMapMode,, SetWindowExtExSetViewportExtEx(例如,请参阅http://social.msdn.microsoft.com/Forums/en-us/netfxbcl/thread/37fd1bfb-f07b-421d-9b5e-5f4492ffbbc3).这些函数可用于缩放富文本控件的渲染输出:例如,如果我指定400%缩放,那么如果富文本控件呈现5像素宽的内容,则实际上将变为20像素宽.

不幸的是,旧的GDI函数使用整数而不是浮点数.例如,假设RTF控件决定应在(12.7,15.3)像素处绘制元素.这将四舍五入到(13,15)的位置.这些圆角坐标传递给GDI,GDI然后使用以下指定的缩放比例放大图像SetMapMode:对于400%的示例,它将是(13*4,15*4)或(52,60).但这不准确:元素最好放在(12.7*4,15.3*4)或(51,61).最糟糕的是,在某些情况下,错误会累积起来.

我相信这是缩放一些简单文本时这个非常明显的错误的根本原因:

使用EM_FORMATRANGE <code>EM_FORMATRANGE</code>和<code>SetMapMode</code>在96 DPI显示设备上下文缩放到400%.文本现在变成了32磅大小,但每个角色之间的空间太高,看起来不自然.</p>

<p><img rel=

上面的示例是在写字板中创建的,输入文本为8点Segoe UI,然后使用缩放控件设置为400%缩放级别.每个角色之间的空间看起来很正常.使用32磅字体和100%缩放级别可获得完全相同的结果.

要解决此问题,我尝试了以下方法.对于尝试的每一件事,当缩放到400%时,结果同样不令人满意.

  • 使用缩放变换使用设置SetWorldTransform,而不是与完成缩放SetMapModeSetWindowExtEx等.
  • 将元文件的设备上下文传递给EM_FORMATRANGE,然后稍后缩放元文件.
  • 使用SetMapMode结合比例与呈现为图元文件,再后来表示无调整图元文件.

我相信结果总是不能令人满意,因为问题归结为这样一个事实:富编辑控件正在四舍五入到最接近的整数并呈现它认为是96 DPI设备 - 忽略转换到位.我查看了元文件格式,我发现的是单个字符位置实际上以像素级分辨率存储在元文件中 - 这就是为什么缩放元文件显然不起作用,因为该点已经发生舍入.

我可以想到两个可以解决这个问题的真正解决方案:

  • 使用具有更高用户指定的每英寸点数的设备上下文,以GetDeviceCaps返回不同的值.(注意:一些示例建议使用打印机设备,因为它们通常具有更高的DPI,但我希望我的代码可以在没有打印机并且能够渲染到屏幕外缓冲区的系统上工作).
  • 某种方式告诉富编辑控件假设设备上下文的每英寸点数与报告的不同GetDeviceCaps.

其他任何东西似乎仍然会受到这些舍入误差的影响.

有没有人(1)知道如何实现我提出的任何解决方案,或者(2)如何实现我的目标,即将准确的高DPI输出放入缓冲区?

Roe*_*oey 0

我遇到了完全相同的问题。

一个快速的解决方案是将文本绘制为 100% 比例的位图,然后仅缩放位图。这不是最好的解决方案,但它可能对您有用。

您找到更好的解决方案了吗?如果有,请在这里分享。

另请注意,当您将文本绘制到 100% 元文件,然后将元文件缩放到屏幕时,也会出现此问题 - 我相信这与 GDI 文本绘制函数不能很好地工作有关缩放。

罗伊