随笔-2  评论-17  文章-0 

Win32下的打印作业输出

        前些天我发布了一篇关于Web打印的文章,不少朋友对其很感兴趣,不过都觉得没有简单且容易上手的Demo,同时也没有对打印控制原理做说明。那么今天我就对打印控制谈一下自己的看法。

        第一章 Windows GDI简介
        说到Windows下的打印控制就不得不说到Windows GDIGraphics Device Interface),它给我们的程序能够在显示器或是打印机上输出图形以及格式文本。(注:这个概念很重要,向屏幕的输出和向打印机的输出在一定程度上是完全一样的)基于Windows的应用程序不需要直接和硬件打交道,这也就是GDI存在的理由吧。查阅Microsoft关于Windows GDI的手册,上面很清楚的说明了其使用条件:
        1.适用于所有的基于Windows的应用程序
        2.GDIAPIs是为C/C++程序员设计的
        3.在应用程序的编写过程中需要一些图形接口和消息驱动的相关知识
        这样的使用条件对于绝大多数的程序员来说都是比较苛刻的,所以各个类库基本上都对GDI进行了不同程度的封装,从而形成了各式各样的Canvas对象。通过使用GDI函数,你可以画线(曲线),封闭图形,文本和位图。这些元素的颜色和样式都取决于你所创建的绘图对象,包括PensBrushesFonts对象。使用Pens对象去绘(曲)线;使用Brush去填充封闭图形的内部区域;使用Fonts对象去输出文本。
        应用程序通过创建一个Device Context(设备环境,简称DC)直接向一个指定的设备进行输出。这个设备环境就是在GDI管理之下的包含着该设备信息的一个数据结构,这些设备信息包括它的工作方式和当前的设置等,而它的创建是在应用程序中通过调用设备环境函数创建的。在创建成功后,GDI返回一个设备环境句柄,它用来在稍后的调用中标识该设备。比如,使用这个句柄,应用程序能够从灾难中恢复设备的相关信息,包括它的类型(显示器,打印机或者其他设备)、显示面的解析维度等。
        应用程序能够直接向一个物理设备进行输出(这也是我们最简单和最常用的方式),这样的物理设备当然包括打印机,除此之外也包括显示器、逻辑设备或者源文件。逻辑设备提供应用程序一个区域去以某种格式对输出内容进行存储,这样的区域能够非常容易的将内容在稍后向物理设备输出,而在应用程序将数据记录在输出到源文件后,它将能够把源文件显示多次或是向多个物理设备进行输出。
        应用程序使用属性函数来设置操作当前设备所在的操作模式和相关信息。操作模式包含文本和背景颜色;混合方法(通常也叫做二进制光栅方法)描述了画笔(或是画笔刷)如何在已有的显示表面上对颜色进行混合;匹配方法描述了GDI是如何通过设备的坐标系统进行坐标的测绘;当前对象则标识了在输出内容时所使用的绘图对象。

        第二章 Windows GDI坐标系统
        在打印的时候经常遇见坐标系的转换和映射,所以有必要在这里解释一些基本概念和知识。我们都知道大部分GDI都需要指定坐标集,用来确定绘图的位置,Windows GDI也一样是这样的,它也是以垂直和水平两个方向上的轴来定位,也就是说通过增减XY的数值来确定绘图位置。
        Win32依赖两个因素来执行绘图函数:坐标系统和映射模式。
        1. 坐标系统
        Windows支持两种坐标系:设备坐标系和逻辑坐标系
        (1)设备坐标系:指WIN32运行于的设备。它是以像素作为度量单位,定位方向是水平轴从左到右,垂直轴从上到下增加。例如在800*600的显示器上运行Windows 2000,设备左上角坐标为(00),而右下角为(799599)。
                1)逻辑坐标系:在WIN32中,有设备环境(DC)的区域通常使用逻辑坐标系,逻辑坐标通过在不同能够的区域使用时分为两种:
                2)屏幕坐标系:是指显示设备,因此它是以像素作为度量单位的坐标系,在800*600的显示器上,Screen.WidthScreen.Height分别为800600像素。
        (2)窗体坐标系:也叫做窗口坐标系,指整个窗体或者窗口,包括标题栏和边框。
        下列代码片段是由Pascal书写,通过使用WIN32 API中的函数来获得DC,将设备环境句柄传递非绘图对象TCanvas

 1Procedure Print()
 2var
 3      c:TCanvas;
 4begin
 5      c:=TCanvas.Create;
 6      try
 7            c.Handle:=GetDC(0);
 8            c.TextOut(10,10,’Hellod World’);
 9      finally
10            c.free;
11      end;
12end;

        2. 
映射模式
        在了解了两种坐标系之后就不难说明为什么要根据不同的打印需求设置不同的映射模式,WIN32给设备环境定义了8种映射模式,这里就不列举了,可以参考相关手册获得。 

        第三章 打印作业输出控制
        说了这么多关于GDI的东西,也许许多概念都已经混淆了,但是一般来说对打印作业的过程控制只需要用到下列3个步骤:
        1.向打印机发送一个打印作业(此时还没有在打印机上进行打印)
        2.通过上面所说的绘图对象,建立打印输出内容(线条或者文本)
        3.结束当前的打印作业,此时该作业才开始在打印机上开始打印

        向屏幕输出与向打印机输出的不同之处,下面是需要特别注意的问题:
        1.在屏幕上绘图是动态的——可以擦去在屏幕上绘图的内容。而向打印机做的输出就没有那么灵活了,凡是通过绘图对象向打印机输出的内容都将被打印出来。
        2.在屏幕上显示文本和图是很快的,而想打印机输出,即使是高性能的激光打印机,也是较慢的,因此必须提供用户能够终止打印作业或采用其他方法来放弃打印作业。
        3.打印机和显示器具有非常不相同的分辨率,300*300的位图在860*480的显示器中很漂亮,但是在300DPI的激光打印机上只是一个1*1英寸的小方块,所以一定要用打印机的点数作为度量单位,而不能使用像素这样的单位,同时注意打印机的分辨率。
        4.注意处理打印纸张不够这样的问题。

         第四章 具体打印类库说明
        GDI在不同具体的类库中的反映可以参考下面的内容:
        1.VS.NET2003(包括VS.Studio 2005也同样包括该部分)请参看MSDN中的命名空间System.Drawing.Printing
        2. Delphi中请参看Printers单元中的TPrinter,Delphi自带的Help中的说明很详细。

 

posted on 2005-11-11 15:15 Yoko 阅读(...) 评论(...) 编辑 收藏