77范文网 - 专业文章范例文档资料分享平台

Delphi报表制作技巧20篇 - 图文(4)

来源:网络收集 时间:2019-06-17 下载这篇文档 手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:或QQ: 处理(尽可能给您提供完整文档),感谢您的支持与谅解。点击这里给我发消息

end; 接下来你在Form1上对应的位置写上数据,运行后按Button1就会一五一十的打印下来了。 打印机的分辨率问题? Printer Resolution ? 问: I want to know, wich way I have to program, so every print is equal. No matter what resolution of the printer (300 or 600 dpi). Since now I program: TextOut(DC, 150, 150...) on a 300 dpi printer. But on 600 dpi, everything looks a bit strange, (small). What Objects can I use to print corectly?? 答: I get the printer resolution (and unprintable are if desired) and then specify coordinates using decimal inches * resulution e.g. x = trunc(1.5 * ResX) at 300 dpi will begin at 360 * 1.5 or 540 pixels. Get Resolution and unprintable ResX := GetDeviceCaps(ACanvas.Handle,LOGPIXELSX); ResY := GetDeviceCaps(ACanvas.Handle,LOGPIXELSY); pOffsetX := GetDeviceCaps(ACanvas.Handle,PHYSICALOFFSETX); pOffsetY := GetDeviceCaps(ACanvas.Handle,PHYSICALOFFSETY); print something Printer.Canvas.TextOut(trunc(1.5 * ResX)-pOffsetX, trunc(2.5 * ResY)-pOffsetY,'Hello'); This is nice when printing data on an existing paper form as you can just measure it up in decimal inches. 用Delphi编写打印程序的窍门 湖北 杨德军 如果你想自己用Delphi编写一个打印程序,那么,下面这些技巧或许对你有所帮助。 1.获娶显示当前打印机的分辨率 Windows下的打印分辨对打印程序有着至关重要的作用,如果你想知道打印机的分辨率,请在程序中加入一行:ShowMessage(′水平分辨率′+inttostr(GetDeviceCaps(printer?Handle,LOGPIXELSX))+chr(13)+′垂直分辨率:′+inttostr(GetDeviceCaps(printer?Handle,LOGPIXELSY)));结果就一目了然了。 2.将结果直接送到打印机 Delphi提供了两种打印方式:一是将结果输送到Form,再调用Form的print方法将结果输送到打印机,二是将结果直接输送到打印机。如果你采用第一种方式,则无论你怎样调整Form的PrintScal属性,打印出来的东西也不会让你满意。因此建议采用第二种方式。 3.尽量不要使用AssignPrn 尽管AssignPrn简化了文本打印操作,使输出到打印机像输出到文件一样简单。但简单带来的是一系列的不方便:你无法知道当前打印的行数,无法准确控制行距,无法灵活改变字体字形等等。还是用打印机的Canvas属性进行打印吧。 4.用打印机的点数做度量单位 如果想让打印程序在任何打印机上都能正常地打印,你就必须改变你的度量单位。如果采用固定的度量,不同分辨率的打印效果是不同的。举例来讲:printer?Canvas?rectangle(0,0,360,720)在360×360的佳能4200SP上能打出一个1英寸宽、2英寸高的矩形,但在600×600的惠普6L上只能打出0?6英寸宽、1?2英寸高的矩形。使用打印机的点数做为度量单位是一个明智的选择。具体做法如下:VarPointX,PointY:integer;PointX:=GetDeviceCaps(printer?Handle,LOGPIXELSX);PointY:=GetDeviceCaps(printer?Handle,LOGPIXELSX);printer?Canvas?rectangle(0,0,PointX*1,PointY*2)这样,无论你使用什么样的打印机,都能得到一个1英寸宽、2英寸高的矩形。 5.添加打印程序单元 尽管Delphi在生成窗体时会自动在USES部分加入许多程序单元,但打印程序单元(Printers)却不在之列,要想使打印机正常工作和程序不出错,你还是老老实实手工给它加上吧。 Delphi编写一个打印程序 如果你想自己用Delphi编写一个打印程序,那么,下面这些技巧或许对你有所帮助。

16

1.获娶显示当前打印机的分辨率 Windows下的打印分辨对打印程序有着至关重要的作用,如果你想知道打印机的分辨率,请在程序中加入一行:ShowMessage(′水平分辨率′+inttostr(GetDeviceCaps(printer?Handle,LOGPIXELSX))+chr(13)+′垂直分辨率:′+inttostr(GetDeviceCaps(printer?Handle,LOGPIXELSY)));结果就一目了然了。 2.将结果直接送到打印机 Delphi提供了两种打印方式:一是将结果输送到Form,再调用Form的print方法将结果输送到打印机,二是将结果直接输送到打印机。如果你采用第一种方式,则无论你怎样调整Form的PrintScal属性,打印出来的东西也不会让你满意。因此建议采用第二种方式。 3.尽量不要使用AssignPrn 尽管AssignPrn简化了文本打印操作,使输出到打印机像输出到文件一样简单。但简单带来的是一系列的不方便:你无法知道当前打印的行数,无法准确控制行距,无法灵活改变字体字形等等。还是用打印机的Canvas属性进行打印吧。 4.用打印机的点数做度量单位 如果想让打印程序在任何打印机上都能正常地打印,你就必须改变你的度量单位。如果采用固定的度量,不同分辨率的打印效果是不同的。举例来讲:printer?Canvas?rectangle(0,0,360,720)在360×360的佳能4200SP上能打出一个1英寸宽、2英寸高的矩形,但在600×600的惠普6L上只能打出0?6英寸宽、1?2英寸高的矩形。使用打印机的点数做为度量单位是一个明智的选择。具体做法如下:VarPointX,PointY:integer;PointX:=GetDeviceCaps(printer?Handle,LOGPIXELSX);PointY:=GetDeviceCaps(printer?Handle,LOGPIXELSX);printer?Canvas?rectangle(0,0,PointX*1,PointY*2)这样,无论你使用什么样的打印机,都能得到一个1英寸宽、2英寸高的矩形。 5.添加打印程序单元 尽管Delphi在生成窗体时会自动在USES部分加入许多程序单元,但打印程序单元(Printers)却不在之列,要想使打印机正常工作和程序不出错,你还是老老实实手工给它加上吧。 打印功能的实现 对于每一个Windows应用程序开发者来说,打印功能的实现都是极为棘手的,因为要涉及到相当多的代码,而且常常是相当复杂,但是在Delphi中实现文本和图像的打印功能却是非常容易的。 文本的打印功能 Delphi中文本的打印功能就如同在DOS中一样容易,需要做的只是取得打印参数,打开打印机,然后发送文本的每一行内容。在Delphi中提供了一个printers程序单元,它说明了一个tprinter对象,封装了Windows打印工作和输出打印机之间的接口,并提供常用的属性和方法。其中画布canvas是一个非常有用的属性,它代表了当前打印文件的表面,是以图形方式来工作的,整个打印输出工作仅仅是将打印的内容输出到tprinter的属性canvas上,当全部输出工作完成以后,打印对象(tprinter)把canvas的属性值送到打印机上去。 下面举例来说明如何通过Delphi实现文本内容的打印。在Delphi中提供了printdialog 、printersetupdialog两个控件允许我们进行打印机以及其他影响打印输出的选择,此外最重要的一点是要想实现打印功能必须在编译程序以前将printers加入到interface或者impl ementation的UESE语句当中,因为printer单元包括assignprn和其他控制打印机的过程。 首先在From当中加入memo、printdialog、printersetupdialog和两个BUTTON控件,两个 BUTTON的CAPTION分别为\打印设置\和\打印\。然后编写BUTTON的事件驱动程序。本例比较简单,只要单击\打印\按钮时便可以在打印机上输出文件0S2.TXT。代码如下: implementation uses printers; {$R *.DFM} procedure TForm1.BitBtn1Click(Sender: TObject); begin printersetupdialog1.execute; //选择输出的打印机以及其他打印控制选项 end; procedure TForm1.BitBtn2Click(Sender: TObject); var lines:integer; prntext:system.text; //将PRNTEXT声明为一个在SYSTEM程序单元当中定义的文本文件 begin if printdialog1.execute then assignprn(prntext); //将PRNTEST分配给打印机 rewrite(prntext); //调用REWRITE函数,为输出打开已分配的文件 printer.canvas.font:=memo1.font; //把当前MEMO1的字体指定给打印对象的CANVAS的字体属性 for lines:=0 to memo1.lines.count-1 do

17

writeln(prntext,memo1.lines[lines]); //把MEMO的内容写到打印机对象 system.close(prntext); //关闭打印文件 end; procedure TForm1.FormCreate(Sender: TObject); begin memo1.lines.loadfromfile(‘c:\\dos\\os2.txt’); //在FORM建立时读入C:\\DOS\\S2.TXT文件 end; end. 图形的打印功能 简单的图形打印功能也如打印文本一样容易,只是告诉打印机对象(tprinter)开始打印 ,把图形复制到打印机上去,最后告诉打印机结束打印工作。 举例说明:将上面的例子中的memo控件换成image控件,再经过一些简单修改,图形打印的代码如下: procedure TForm1.BitBtn1Click(Sender: TObject); begin if printdialog1.execute then begin printer.begindoc; printer.canvas.draw(0,0,image1.picture.graphic); printer.enddoc; end; end; 在这种情况下,使用的是打印机的分辨率,图形在页面的左上角开始打印输出,打出的图形很小,通常不能符合要求。但是利用打印机画布canvas的stretchdraw方法,我们可以对图形进行灵活处理,canvas的stretchdraw方法声明为: procedure StretchDraw(const Rect: TRect; Graphic: TGraphic); 其中的Rect参数代表图形输出区域的大小,Trect的类型声明为: TRect = record case Integer of 0: (Left, Top, Right, Bottom: Integer); 1: (TopLeft, BottomRight: TPoint);end; 因此我们只要调整RECT的大小及其在打印页面上的位置,进而达到满意的效果,下面不断放大图形,充满我们定义的矩形区域,并将其定位在打印机画布(canvas)的中央然后输出。代码如下: procedure TForm1.Button1Click(Sender: TObject); VAR strect:Trect; //定义打印输出矩形框的大小 temhi,temwd:integer; begin if printdialog1.execute then begin temhi:=image1.picture.height; temwd:=image1.picture.width; while (temhi<printer.pageheight div 2)and //将图形放大到打印页面的1/2 (temwd<printer.pagewidth div 2) do begin temhi:=temhi+temhi; temwd:=temwd+temwd; end; with strect do //定义图形在页面上的中心位置输出 begin left:=(printer.pagewidth -temwd) div 2; top:=(printer.pageheight-temhi) div 2; right:=left+temwd; bottom:=top+temhi; end; with Printer do begin begindoc; //将放大的图形向打印机输出 canvas.stretchdraw(strect,image1.picture.graphic);

18

enddoc; end; end; end; 动态制作报表 在Delphi中,编程人员利用Quick Report控件可以方便地设计和实现静态报表,但对动态报表的制作仍有不便之处。如制作一个列表式报表时,如何动态调节每一列的宽度?由于报表在预览情况下不能修改,只能在预览前将宽度设定好,因此,如何比较方便地预先设定宽度,就成了一个需要解决的问题。 分析问题 首先可想到一种笨办法,就是在确定报表中需要显示的字段后,对每一个字段的宽度赋予一个初始值(比如80),对于需要调整的字段再通过编辑框进行输入修改。这样的确可以达到预期目的,但由于不直观,可能需要多次调整,影响了效率和方便性。 笔者通过实践,利用DBGRID解决了这个问题。由于是制作与数据库相关的报表,其报表记录肯定需要通过一个SQL语句来产生,那么这些记录就可以先显示在一个DBGRID中。由于DBGRID的各列宽度可以动态调节,那么将适当的DBGRID的各列宽度赋给报表中的各列,就一次性达到了我们预期的目的,而且操作非常方便。 设置窗体 建立两个窗体mainform和repform。在mainform上放置edit1、datasource1、query1、dbgrid1、button1(caption为“提取数据”)和button2(caption为“预览报表”),将datasource1.dataset设定为query1,将dbgrid1的datasource设定为datasource1。在repform上放置Quickrep1,并至少将Quickrep1.bands.hascolumnband和Quickrep1.bands.hasdetailband设为true。 编程实现 运行时,在edit1中输入正确的 SQL语句。点击“提取数据”按钮,将相应记录显示在 dbgrid1中。具体的程序代码如下: procedure Tmainform.button1click(sender:TObject); var s:string; begin s:=edit1.text; with query1 do begin close; sql.clear; sql.add(s); open; end; end; 点击“预览报表”按钮,可以看到形成的报表,如果对宽度摆放还有些不满意,可以关闭预览窗口后重新调整。具体的程序代码如下: procedure Tmainform.button2click(sender:TObject); var leftv,i:integer; //leftv为报表起始位置 cheader:Tqrlabel; detailtext:Tqrdbtext; ?? begin leftv:=0; for i:=0 to dbgrid1.columns.Count-1 do begin cheader:=TQrlabel.Create(repform); with repform.cheader do begin parent:=repform.columnheaderband1; caption:=dbgrid1.columns[i].fieldname; width:=dbgrid1.columns[i].width; height:=repform.columnheaderband1.height; left:=leftv+2; top:=5; end; ??//在leftv 处画表格竖线 leftv:=dbgrid1.columns[i].width+leftv; end; ??//画表头栏边框。起始位为0,总宽度为leftv,也就是dbgrid1的各列宽度之和

19

leftv:=0; //显示记录内容 for i:=0 to dbgrid1.columns.Count-1 do begin detailtext:=TQrdbtext.create(repform); with repform.detailtext do begin parent:=repform.detailband1; dataset:=query1; datafield:=dbgrid1.columns[i].fieldname; width:=dbgrid1.columns[i].width; height:=repform.detailband1.height; left:=leftv+2; top:=5; end; ??//在leftv 处画表格竖线 leftv:=dbgrid1.columns[i].width+leftv; end; ??// 画明晰栏边框。 repform.quickrep1.preview();//报表预览 end; 多栏打印 在所有有关Delphi的书籍中,都没有讲解如何实现一个打印项的多栏打印,而实现生活中往往有许多报表要求同一项目多栏打印,QuickReport提供了报表打印一整套完整的解决方案,完全可以实现同一项目的多栏打印,技术关键是如何控制表中记录提取个数,如果在Treport的DataSet属性中选定一个Table,那么QuickReport每次打印详细列表(BandType=rbDetail)属性的TQRBand时,系统会自动取出一个记录供打印,并将表中的记录指针移到下一位,这样程序无法控制表中记录指针的移动,就无法实现多栏打印,只要程序不在Treport的DataSet属性选定任何表, QuickReport便不会控制表记录的提取,QuickReport特为其它类型数据打印提供了一个OnNeedData事件,QuickReport每次打印详细列表(BandType=rbDetail)属性的TQRBand时,会触发这个事件,要求提供打印数据,如果程序在OnNeedData事件中编写运用表中数据提供打印资料,便能实现多栏打印,现举例说明: ---- 现在要实现一个Table1中Name项两栏打印,在窗口上放TquickReport组件 quickReport1,并在上面放Tband组件band1,将其BandType属性改为Detail,在Tband 组件上并排放两个QRLabel组件QRLabel1和QRLabel2,在quickReport1的OnNeedData事件中写如下代码: procedure TForm1.QuickRep1NeedData(Sender: TObject; var MoreData: Boolean); var I: integer; begin MoreData := True; for I:= 1 to 2 do begin if Table1.Eof then Break; case I of 1: QRLabel1.Caption := Table1.FieldByName('Name').AsString; 2: QRLabel2.Caption := Table1.FieldByName('Name').AsString; end; Table1.Next; end; if Table1.Eof then MoreData := False; end; 为了保证打印或者打印预览开始时Table1指针在第一条记录,在quickReport1的BeforePrint事件中写如下代码: procedure TForm1.QuickRep1BeforePrint(Sender: TCustomQuickRep; var PrintReport: Boolean); begin Table1.First; end; 这样程序调用QuickRep1.Preview或者QuickRep1.Print便能预览或者打印到一个关于Name的从左至右,从上到下的多栏报表。 检测存在打印机 Printers是专门用来控制打印机的,可是在没有安装打印机时,却会提示I/O错误,所以必须有一个检测是否存在打印

20

百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库Delphi报表制作技巧20篇 - 图文(4)在线全文阅读。

Delphi报表制作技巧20篇 - 图文(4).doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印 下载失败或者文档不完整,请联系客服人员解决!
本文链接:https://www.77cn.com.cn/wenku/zonghe/662082.html(转载请注明文章来源)
Copyright © 2008-2022 免费范文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ: 邮箱:tiandhx2@hotmail.com
苏ICP备16052595号-18
× 注册会员免费下载(下载后可以自由复制和排版)
注册会员下载
全站内容免费自由复制
注册会员下载
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: