bestlong 怕失憶論壇

 

 

搜索
bestlong 怕失憶論壇 論壇 Delphi QuickReport 報表元件 QucikReport 原始碼剖析
查看: 7568|回復: 1
go

QucikReport 原始碼剖析 [複製鏈接]

Rank: 9Rank: 9Rank: 9

1#
發表於 2006-6-26 15:23 |只看該作者 |倒序瀏覽 |打印
QucikReport 源代码剖析

按设计期与外部运行 Exe 单元分类:


外部运行 Exe:

qrdatasu 报表数据源设置 Dialog
qrdatawz 从报表数据源中选择字段 Dialog
qreditor 报表设计器 Dialog,用于外部使用,和 qrdatasu, qrdatawz 都有关
qrexpred 表达式显示格式 Dialog
QRLABLWZ - MAILING LABEL SETUP DIALOG
qrmdsu 主从表设置 Dialog
qrwizard 新报表的 Wizard Dialog


设计期与独立 Exe 公用单元:

qrcomped 设计期报表属性设置Dialog
qrabout about Dialog
qrenved 用户自定义函数 Dialog
qrexpbld 表达式设置 Wizard Dialog
qrprev 打印预览 Dialog
qrprgres 打印进度条 Dialog
qrprnsu 打印机设置 Dialog
qrLablEd 增强型 qrlabel 的属性编辑器 Dialog


比较重要的类:

qrexpr 表达式计算
qr3const 定义了一些提示常量,打印纸张列表常量。
qrexport 把报表输出到各种文件,如ascii,csv,xls,html,rtf,text,wmf
qrctrls 设计期控件


重要的类:

qrprntr 打印预览基础类,是一个重要的单元 打印控制时重要.
quickrpt Quickrpt 组件源码 设计期重要


未知:

qrextra 附加类,作用未明

TQrPrinterSettings 设置打印属性
TQrStandardPreViewInterface 建立预览窗口
TQrPreviewImage 打印和预览的图象
TQrPreView 控制预览


这是三个很重要的类:

TQrStream  存图象的流
TQrPagelist 图象内存页的列表
TQrPrinter 控制打印


QuickRept 在预览时做了些什么?给你段源码你就明白了。
  1. procedure TCustomQuickRep.Preview;
  2. begin
  3.   Application.ProcessMessages;
  4.   if PrepareQRPrinter and not QRPrinter.ShowingPreview then
  5.   begin
  6.     QRPrinter.Destination := qrdMetafile;
  7.     QRPrinter.Master := Self;
  8.     QRPrinter.OnPrintSetup := PrinterSetup;
  9.     QRPrinter.OnExportToFilter := ExportToFilter;
  10.     QRPrinter.Title := ReportTitle;
  11.     if assigned(FOnPreviewEvent) then
  12.       QRPrinter.OnPreview := FOnPreviewEvent;
  13.     QRPrinter.Preview;
  14.     CreateReport(false);
  15.     if Cancelled then
  16.     begin
  17.       QRPrinter.Free;
  18.       Exit;
  19.     end;
  20.     repeat
  21.       Application.HandleMessage
  22.     until (QRPrinter = nil) or (not QRPrinter.ShowingPreview) or Application.Terminated;
  23.   end;
  24. end;
複製代碼

有人说程序压栈了,NO,是 REPEAT 了,你的退出方式符合 QuickRep 的条件吗?呵呵。


打印原理:

在内存中建立一个内存流,再每一个BAND做处理[其中细节还没有探明],把 Band 信息存到内存流中[writebuffer]。在预览或打印时,建立一个 TMetaFile 文件,先写入 EMFHEADER。把内存流的信息 LoadFromStream 到 MetaFile 文件中,在打印或预览时就进行文件的定位,读取 [seek, read, write],然后就在打印机的纸上输出。输出时用 Canvas.StreahDraw(Rect, MetaFile); 走纸控制是按打印机设置走纸的。如果设置当前打印机不支持,则按默认首选项打印,可以动态用 API 改变默认打印首选项来控制走纸。


关于 metaFile 文件类型:

是一种可无级缩放的矢量图。在WINDOWS中有一种WMF文件就是此格式。矢量图可由WINDOWS控制缩放,打印。QUIEKREPORT就是利用了元文件的这个好处,不需自己管走纸,预览打印了。而国人王寒松写的EREPORT用的是DOS下常用的找位置用程序生画线textout的手法。metafile文件一旦建立,得到文件句柄,你就象面对一张白纸一样,往上用函数画你的东西吧。画完用打印机的CANVAS打印即可。ArcoBat Reader得PDF文件也是这个原理。


metafile文件可缩放的工作原理:

在文件中存放的其实是图象的相对位置,在具体的设备上显示时,才通过坐标映射关系转换为具体的坐标。

关于Delphi对MetaFile的编程,Graphics.pas就有TMetaFile的源码,我就不多费口舌了。


主要处理点:

如何把各BAND信息存到流里去。想改变Qr的打印速度和打印方式,需要从此下手。

对MetaFile文件格式的处理。在王寒松做的eReport中是纯粹用线画,用Textout,没有用MetaFile,用MetaFile速度会慢,但处理缩放很好,用线画,对打印速度会有提高,但无级缩放,达不到矢量图的效果。


打印是用Qrprinter打印的。但quickrep.print与quickrep.qrPrinter.print打印在源代码上不一样,还没有深研究。


qrprinter只在预览和打印中才产生,没有预览和打印,没有qrprinter.


quickrep几个最主要的事件:

afterpreview 只在关闭预览窗口才触发
afterprint 只在打印完最后一页才触发
beforeprint 在打印第一页时触发
OnEndPage 在一页末下一页开始前的间隔触发
OnNeedData
OnPreview 在预览前触发
OnStartPage 在每一页开始触发


bandtype

rbtitle 在第一页的头部
rbpageheader 在每一页的头部
rbDetail 记录区
rbPageFooter 在每页纸的尾部
rbsummary 在 Detail 区和 Group Footer 区的下
rbcolumnheader 在每页纸的头部。


如何多张互不关联报表连打[节约纸张]?

答:用复合报表制作。在 OnAddReports 中把报表 Reports.add(报表)

缺点:每一个报表的 CloumnHeader, PageHeader 只能在每张纸的头出现。

如果两张报表在一张纸上,第二个报表的 CloumnHeander,PageHeader 不出现。如改为 Title,就可出现,但在后续的纸的头部就不出现了。或许在 TQuickRep.OnNeedData 中可以办到,但没仔细想。


用报表生成器做连续打印的思想:

1 建立一个不定长数组,存放 quickRep,ClientDataSet 把一个报表取下,把值添好,把它用流的技术复制一份[单纯赋值只是引用指针,因为我们是用一个QuickRep恢复,所以下一张报表会把我们当前的报表冲掉,而流技术可以复制一份],从流里边恢复控件必须把流里控件所涉及到的类都用 RegisterClass 注册一遍,否则从流中恢复时 Owner 有可能不认识这个类 [Form 类和 Components 类会系统自动识别] ,无法利用 RTTI 信息建立控件和保存控件的运行期信息。然后就把数组中的报表增加到复合报表中连打,因为就一个 cdsReportDataSet, 而报表连的都是 cdsReportDataSet,现在新建了一个 cdsReportDataSet 的副本,所以只能把报表上的控件的 DataSet都换掉}


不要在其他地方给复合报表.Reports 赋值,因为在复合报表内部处理时,它只认在 OnAddReport 中增加的报表,具体的内部细节是它有一个内部方法:CreateComposite,第一句就是 Reports.Clear; 在第5句就有一句:

if Assigned(OnAddReports) then OnAddReports(Sender);
CreateComposite 在 Print, Preview, Prepare 都有。
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 1

2#
發表於 2010-10-26 17:01 |只看該作者
果然也是一个很强的人。
‹ 上一主題|下一主題

Archiver|怕失憶論壇

GMT+8, 2024-4-26 06:56 , Processed in 0.013156 second(s), 11 queries .

Powered by Discuz! X1.5

© 2001-2010 Comsenz Inc.