如何在win32 c ++打印预览? [英] how do I do print preview in win32 c++?

查看:233
本文介绍了如何在win32 c ++打印预览?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个绘图功能,只需要一个HDC。
但我需要显示一个EXACT缩放版本的打印内容。

I have a drawing function that just takes an HDC. But I need to show an EXACT scaled version of what will print.

现在,我使用
CreateCompatibleDC()与打印机HDC和
CreateCompatibleBitmap()与打印机的HDC。

So currently, I use CreateCompatibleDC() with a printer HDC and CreateCompatibleBitmap() with the printer's HDC.

我认为这种方式DC将有打印机的确切的宽度和高度。
当我在这个HDC中选择字体时,文本将按照打印机的尺寸进行缩放。

I figure this way the DC will have the printer's exact width and height. And when I select fonts into this HDC, the text will be scaled exactly as the printer would.

不幸的是,我不能使用StretchBlt将HDC的像素复制到控件的HDC,因为它们是不同的HDC类型。

Unfortunately, I can't to a StretchBlt() to copy this HDC's pixels to the control's HDC since they're of different HDC types I guess.

如果我从一个窗口HDC创建内存画布 ,h作为打印机的页面,
的字体出来WAY少年,因为他们缩放为屏幕,而不是页...

If I create the "memory canvas" from a window HDC with same w,h as the printer's page, the fonts come out WAY teeny since they're scaled for the screen, not page...

我应该创建CompatibleDC )从窗口的DC和
CreateCompatibleBitmap()从打印机的DC或什么??

Should I CreateCompatibleDC() from the window's DC and CreateCompatibleBitmap() from the printer's DC or something??

如果有人可以解释正确的方式做到这一点。
(还有一些看起来不错的东西,就像在打印机上一样)...

If somebody could explain the RIGHT way to do this. (And still have something that looks EXACTLY as it would on printer)...

好吧,我很感激它!

... Steve

...Steve

推荐答案

根据你想要的准确度,困难。

Depending on how accurate you want to be, this can get difficult.

有很多方法。听起来你试图画一个打印机大小的位图,然后收缩下来。这样做的步骤是:

There are many approaches. It sounds like you're trying to draw to a printer-sized bitmap and then shrink it down. The steps to do that are:


  1. 为打印机创建DC(或更好的IC - 信息上下文) li>
  2. 查询打印机DC以了解分辨率,页面大小,物理偏移等。

  3. 为窗口/屏幕创建DC。 >
  4. 创建兼容的DC(内存DC)。

  5. 为窗口/屏幕创建兼容的位图,但大小应为打印机的像素大小页。 (

  6. 在内存DC中选择兼容的位图。

  7. 绘制到内存DC,使用相同的坐标,如果绘图到实际打印机将使用。 (当您选择字体时,请确保将其缩放到打印机的逻辑英寸,而不是屏幕的逻辑英寸。)

  8. StretchBlt 内存DC到窗口,这将缩小整个图像。

  9. 释放所有资源。

  10. 。您可能想尝试拉伸模式,看看哪种效果最适合您要显示的图片类型。
  1. Create a DC (or better yet, an IC--Information Context) for the printer.
  2. Query the printer DC to find out the resolution, page size, physical offsets, etc.
  3. Create a DC for the window/screen.
  4. Create a compatible DC (the memory DC).
  5. Create a compatible bitmap for the window/screen, but the size should be the pixel size of the printer page. (The problem with this approach is that this is a HUGE bitmap and it can fail.)
  6. Select the compatible bitmap into the memory DC.
  7. Draw to the memory DC, using the same coordinates you would use if drawing to the actual printer. (When you select fonts, make sure you scale them to the printer's logical inch, not the screen's logical inch.)
  8. StretchBlt the memory DC to the window, which will scale down the entire image. You might want to experiment with the stretch mode to see what works best for the kind of image you're going to display.
  9. Release all the resources.

但在你朝这个方向前进的时候,考虑替代品。这种方法涉及分配一个巨大的离屏位图。这可能在资源贫乏的计算机上失败。即使没有,您可能会挨饿其他应用程序。

But before you head in that direction, consider the alternatives. This approach involves allocating a HUGE off-screen bitmap. This can fail on resource-poor computers. Even if it doesn't, you might be starving other apps.

在另一个答案给出的元文件方法是很多应用程序的一个不错的选择。我会从这开始。

The metafile approach given in another answer is a good choice for many applications. I'd start with this.

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

Another approach is to figure out all the sizes in some fictional high-resolution unit. For example, assume everything is in 1000ths of an inch. Then your drawing routines would scale this imaginary unit to the actual dpi used by the target device.

最后一种方法(可能是元文件)的问题是GDI字体不能完美线性缩放。根据目标分辨率调整各个字符的宽度。在高分辨率设备(如300+ dpi激光打印机)上,这种调整是最小的。但在96 dpi的屏幕上,这些调整可以加起来在一条线的长度上的显着误差。因此,预览窗口中的文字可能与打印页面上的文字不成比例(通常更宽)。

The problem with this last approach (and possibly the metafile one) is that GDI fonts don't scale perfectly linearly. The widths of individual characters are tweaked depending on the target resolution. On a high-resolution device (like a 300+ dpi laser printer), this tweaking is minimal. But on a 96-dpi screen, the tweaks can add up to a significant error over the length of a line. So text in your preview window might appear out-of-proportion (typically wider) than it does on the printed page.

因此,核心方法是测量打印机上下文,并在屏幕上下文中再次测量,并调整差异。例如(使用化妆数字),您可以测量打印机上下文中某些文本的宽度,并得出900个打印机像素。假设打印机像素与屏幕像素的比率为3:1。你会期望屏幕上的相同文本的宽度为300个屏幕像素。但是你在屏幕上下文中测量,你得到像325屏幕像素的值。当你画到屏幕上,你将不得不使文本25像素更窄。您可以将字符靠近在一起,或选择一个稍小的字体,然后伸展出来。

Thus the hardcore approach is to measure text in the printer context, and measure again in the screen context, and adjust for the discrepancy. For example (using made-up numbers), you might measure the width of some text in the printer context, and it comes out to 900 printer pixels. Suppose the ratio of printer pixels to screen pixels is 3:1. You'd expect the same text on the screen to be 300 screen pixels wide. But you measure in the screen context and you get a value like 325 screen pixels. When you draw to the screen, you'll have to somehow make the text 25 pixels narrower. You can ram the characters closer together, or choose a slightly smaller font and then stretch them out.

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

The hardcore approach involves more complexity. You might, for example, try to detect font substitutions made by the printer driver and match them as closely as you can with the available screen fonts.

我已经很好运气与大位图和硬核方法的混合。而不是为整个页面做一个巨大的位图,我做一个足够大的一行文本。然后我绘制打印机大小到屏幕外的位图和 StretchBlt 它下降到屏幕尺寸。这消除了在字体质量的轻微降低时处理尺寸差异。它适合实际的打印预览,但你不想要构建一个所见即所得的编辑器。单线位图足够小,可以使这个实用。

I've had good luck with a hybrid of the big-bitmap and the hardcore approaches. Instead of making a giant bitmap for the whole page, I make one large enough for a line of text. Then I draw at printer size to the offscreen bitmap and StretchBlt it down to screen size. This eliminates dealing with the size discrepancy at a slight degradation of font quality. It's suitable for actual print preview, but you wouldn't want to build a WYSIWYG editor like that. The one-line bitmap is small enough to make this practical.

好消息是文本很难。所有其他绘图是一个简单的缩放坐标和大小。

The good news is only text is hard. All other drawing is a simple scaling of coordinates and sizes.

我没有使用GDI +很多,但我认为它取消了非线性字体缩放。所以如果你使用GDI +,你应该只是缩放你的坐标。缺点是我不认为GDI +的字体质量是好的。

I've not used GDI+ much, but I think it did away with non-linear font scaling. So if you're using GDI+, you should just have to scale your coordinates. The drawback is that I don't think the font quality on GDI+ is as good.

最后,如果你是Vista或更高版本的本机应用程序,确保您已将进程标记为可识别DPI 。否则,如果用户在高DPI屏幕上,Windows会对你说谎,并声称分辨率只有96 dpi,然后做一个模糊的缩放你绘制的任何东西。这降低了视觉质量,并可以使调试打印预览更复杂。由于这么多的程序不能很好地适应更高的DPI屏幕,微软默认从Vista开始添加高DPI缩放。

And finally, if you're a native app on Vista or later, make sure you've marked your process as "DPI-aware" . Otherwise, if the user is on a high-DPI screen, Windows will lie to you and claim that the resolution is only 96 dpi and then do a fuzzy up-scaling of whatever you draw. This degrades the visual quality and can make debugging your print preview even more complicated. Since so many programs don't adapt well to higher DPI screens, Microsoft added "high DPI scaling" by default starting in Vista.

编辑添加

Edited to Add

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

Another caveat: If you select an HFONT into the memory DC with the printer-sized bitmap, it's possible that you get a different font than what would get when selecting that same HFONT into the actual printer DC. That's because some printer drivers will substitute common fonts with in memory ones. For example, some PostScript printers will substitute an internal PostScript font for certain common TrueType fonts.

您可以首先在打印机IC中选择HFONT,然后使用GDI函数, code> GetTextFace , GetTextMetrics ,也许 GetOutlineTextMetrics 实际字体选择。然后,您可以创建一个新的LOGFONT尝试更紧密地匹配打印机将使用,将其转换为HFONT,并选择它到您的内存DC。这是一个真正好的实施的标志。

You can first select the HFONT into the printer IC, then use GDI functions like GetTextFace, GetTextMetrics, and maybe GetOutlineTextMetrics to find out about the actual font selected. Then you can create a new LOGFONT to try to more closely match what the printer would use, turn that into an HFONT, and select that into your memory DC. This is the mark of a really good implementation.

这篇关于如何在win32 c ++打印预览?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆