如何在win32 c ++中打印预览?

Ste*_*zel 9 c++ windows winapi gdi print-preview

我有一个绘图功能,只需要一个HDC.但是我需要展示一个精确版本的打印版本.

所以目前,我使用带有打印机HDC的CreateCompatibleDC()和带有打印机HDC的CreateCompatibleBitmap().

我这样想DC会有打印机的确切宽度和高度.当我在这个HDC中选择字体时,文本将与打印机完全一样.

不幸的是,我不能让StretchBlt()将这个HDC的像素复制到控件的HDC,因为我猜它们是不同的HDC类型.

如果我从具有与打印机页面相同的w,h的HDC窗口创建"内存画布",那么这些字体会因为缩放屏幕而不是页面而显示出来.

我应该从窗口的DC和CreateCompatibleBitmap()从打印机的DC或其他东西创建CompatibleDC()吗?

如果有人可以解释这样做的正确方法.(并且仍然有像打印机那样看起来很完美的东西)......

好吧,我很感激!!

...史蒂夫

Adr*_*thy 10

根据您想要的准确程度,这可能会变得困难.

有很多方法.听起来你正试图绘制一个打印机大小的位图,然后缩小它.这样做的步骤是:

  1. 为打印机创建DC(或更好的IC,信息上下文).
  2. 查询打印机DC以查找分辨率,页面大小,物理偏移等.
  3. 为窗口/屏幕创建DC.
  4. 创建兼容的DC(内存DC).
  5. 为窗口/屏幕创建兼容的位图,但大小应该是打印机页面的像素大小.(这种方法的问题是这是一个巨大的位图,它可能会失败.)
  6. 在存储器DC中选择兼容的位图.
  7. 绘制到内存DC,使用与绘制到实际打印机时相同的坐标.(当您选择字体时,请确保将它们缩放到打印机的逻辑英寸,而不是屏幕的逻辑英寸.)
  8. StretchBlt内存DC到窗口,将缩小整个图像.您可能希望尝试拉伸模式,以查看哪种图像最适合您要显示的图像.
  9. 释放所有资源.

但在你走向这个方向之前,请考虑其他选择.这种方法涉及分配一个巨大的屏幕外位图.这可能会在资源匮乏的计算机上失败.即使它没有,你可能会饿死其他应用程序.

另一个答案中给出的元文件方法对于许多应用程序来说是一个很好的选择 我从这开始.

另一种方法是在一些虚构的高分辨率单元中找出所有尺寸.例如,假设一切都在千分之一英寸.然后,您的绘图例程会将此虚构单位缩放到目标设备使用的实际dpi.

最后一种方法(可能还有元文件)的问题在于GDI字体不能完全线性扩展.根据目标分辨率调整各个字符的宽度.在高分辨率设备(如300+ dpi激光打印机)上,这种调整很少.但是在96-dpi的屏幕上,调整可能会在一条线的长度上产生明显的误差.因此,预览窗口中的文本可能与打印页面上的文本不成比例(通常更宽).

因此,硬核方法是在打印机上下文中测量文本,并在屏幕上下文中再次测量,并调整差异.例如(使用虚拟数字),您可以测量打印机上下文中某些文本的宽度,它可以达到900个打印机像素.假设打印机像素与屏幕像素的比率为3:1.您希望屏幕上的相同文本宽度为300像素.但是你在屏幕上下文中测量,你得到一个像325屏幕像素的值.当您绘制到屏幕时,您必须以某种方式使文本缩小25像素.您可以将字符拉得更近,或者选择稍小的字体,然后将它们拉出来.

硬核方法涉及更多复杂性.例如,您可能会尝试检测打印机驱动程序所做的字体替换,并尽可能与可用的屏幕字体进行匹配.

我很喜欢大位图和硬核方法的混合体.我没有为整个页面创建一个巨大的位图,而是为一行文本创建了一个足够大的位图.然后我将打印机尺寸绘制到屏幕外位图,StretchBlt然后缩小到屏幕尺寸.这消除了在略微降低字体质量时处理尺寸差异.它适用于实际的打印预览,但您不希望像这样构建WYSIWYG编辑器.单行位图足够小,可以实现这一点.

好消息是文字很难.所有其他绘图都是坐标和大小的简单缩放.

我没有太多使用GDI +,但我认为它取消了非线性字体缩放.因此,如果您使用的是GDI +,则只需缩放坐标即可.缺点是我不认为GDI +上的字体质量一样好.

最后,如果您是Vista或更高版本的本机应用程序,请确保您已将您的流程标记为"支持DPI ".否则,如果用户处于高DPI屏幕上,Windows将对您撒谎并声称分辨率仅为96 dpi,然后对您绘制的任何内容进行模糊放大.这会降低视觉质量,并使调试打印预览变得更加复杂.由于许多程序无法很好地适应更高的DPI屏幕,因此微软默认在Vista中添加了"高DPI缩放".

编辑添加

另一个警告:如果您使用打印机大小的位图选择HFONT到内存DC中,则可能会获得与在实际打印机DC中选择相同的HFONT时所获得的字体不同的字体.这是因为某些打印机驱动程序会将常用字体替换为内存字体.例如,某些PostScript打印机会将内部PostScript字体替换为某些常见的TrueType字体.

您可以先将HFONT选择到打印机IC中,然后使用像GetTextFace,等GDI函数GetTextMetrics,也GetOutlineTextMetrics可以找出所选的实际字体.然后,您可以创建一个新的LOGFONT,以尝试更紧密地匹配打印机将使用的内容,将其转换为HFONT,并将其选择到您的内存DC中.这是一个非常好的实现的标志.