U8开发之打印控件.docx
- 文档编号:3326815
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:68
- 大小:660.91KB
U8开发之打印控件.docx
《U8开发之打印控件.docx》由会员分享,可在线阅读,更多相关《U8开发之打印控件.docx(68页珍藏版)》请在冰豆网上搜索。
U8开发之打印控件
U8打印控件
摘要
打印控件是面向单据,列表,报表等多种业务场景的提供预览,打印,输出功能的公共控件。
什么是打印控件?
打印控件PrintControl是一个独立的,但同时又具有一定针对性的报表打印控件,它根据指定的XML格式文件(或字符串)对指定的XML数据文件(或字符串)进行格式化输出,本身基本不做任何数据的处理,不涉及任何业务逻辑,也不与任何数据库进行交互。
也就是说,一旦你对控件指定了源格式XML和数据XML,那么通过控件得到的打印预览输出和打印输出也就唯一确定了。
从这一点来看,本控件类似于IE、Mozilla等浏览器对纯HTML文本进行的解释。
PrintControl的格式化输出依赖与上述的两个XML文件(或字符串,下同,以后不再注明),任何报表或者其他类似文件,如果希望使用本控件来打印的话,都必须先将格式和数据分别组织成满足本控件预定义格式的XML文件。
PrintControl以ocx的形式封装,是一个进程内的COMServer,并支持嵌入到WEB中使用。
目标
本文的目标是介绍使用打印控件进行开发的基本流程已经各个接口,属性,事件的使用方法。
目标人群是使用打印控件的二开人员。
打印控件可以做什么?
如何使用打印控件?
1.环境准备
打印控件的编译和调适,需要安装VC6和2个sdk
1个是MicrosoftSDK(WindowsSDKNovember2001)
1个是FRAMEWORK2.0SDK
安装完后在VC6进行如下设置:
ToolsàOptionsàDirectoriesà选中Includefilesà加入2个sdk的路径:
再在此界面中选中LibraryFilesà加入2个sdk的lib路径:
然后就可以在VC6中打开PrintControl的工程,进行编译了。
打印控件的调试工程一般如下:
在一个文件夹中搁入U8PrintDataXML.log,U8PrintStyleXML.log,logPrintCtlTestor.exe
然后ProjectàSettingsàDebug,指向那个文件夹即可:
然后在工程中找到此函数CPrintControlCtrl:
:
SetDataStyleXML(此为打印控件入口函数)
和longCPrintControlCtrl:
:
PrintPreview()
下断点,然后F5运行。
先点Binddata,再点preview即可看到打印控件运行到断点处。
到时就可以调适了。
2.打印控件的程序流程
打印控件程序流程:
1,CPrintControlCtrl:
:
SetDataStyleXML绑定数据(在CPrintTask:
:
SetDataStyleXML中进行),数据由data和style2个xml串传进来。
组织成一个一个的Cgrid(在CPrintTask:
:
Compose中进行)。
2,CPrintControlCtrl:
:
PrintPreview()是弹出预览窗口的,它主要做2个操作,对数据进行分页运算;在弹出窗口中显示数据。
下面分别讲解这2个操作。
3,分页运算主要在CPrintTask:
:
DoPaginate()中进行。
主要是把Cgrid放在新构建CgridSlice中,然后根据Cgrid中取得的页面大小信息,把CgridSlice放到Cpage中。
这个的意义就是看一页纸(Cpage)中能放多少个表格(CgridSlice)。
然后通过此函数算出需要多少页纸。
并且每页纸上有多少表格的行和列(在此分页运算中找SetBeginRow,SetEndRow,SetHorzPageIndex,然后跟踪此函数即可慢慢体会到怎么算出来的)。
4,显示操作主要在voidCGridSlice:
:
Draw()中进行。
在此下断点可以很清晰地看到每页的各个部分是如何画出来的。
DrawTitle是画标题
DrawFormHeader是画表头
DrawFormBody是画表格
DrawFormBodyHeader画表格里面的表体头
DrawFormDataLine画表格里面的表体行
DrawFormBodyFooter画表格里面的表体尾
DrawFormFooter画表尾
5,分析下CGridSlice:
:
DrawFormHeader是怎样画表头的。
voidCGridSlice:
:
DrawFormHeader(CDC*pDC,constIAdapter&adapter)
{
//先得到表头的格式信息
CCommStyle*pHeaderStyle=&m_pGrid->GetPrintParam()->m_FormHeaderStyle;
//在格式信息中有此表头在此页是否打印的信息。
如果是不打印,则函数退出。
if(IsPrintableSlice(pHeaderStyle)==false)
{
return;
}
//得到表头的数据集合,具体数据是些什么,看SEGSTYLEARRAY的定义
LPSEGSTYLEARRAYpSegStyleArray=&m_pGrid->GetPrintParam()->m_HeaderSegStyleArray;
//创建字体
CFontbaseFont;
pHeaderStyle->CreateRatioFont(baseFont,adapter.GetDispRatio());
CFont*pOldFont;
CFontsegFont;
//枚举表头数据集合
for(inti=0;i
{
//得到其中一个表头数据
CSegStyle*pSegStyle=pSegStyleArray->GetAt(i);
//通过CsegStyle找到对应的表头字符串CSegment。
CSegment*pSegData;
if(pSegStyle->IsUnnamedSegment())
{
pSegData=m_pGrid->GetHeaderUnnamedSegment(i);
}
else
{
pSegData=m_pGrid->GetHeaderSegmentFormKey(pSegStyle->m_sKey);
}
if(pSegData==NULL)continue;
//创建字体
if(!
(pSegStyle->m_sFontName.IsEmpty()))
{
pSegStyle->CreateRatioFont(segFont,adapter.GetDispRatio());
pDC->SetTextColor(pSegStyle->m_color);
pOldFont=pDC->SelectObject(&segFont);
}
else
{
pDC->SetTextColor(pHeaderStyle->m_color);
pOldFont=pDC->SelectObject(&baseFont);
}
//得到表头数据的框的大小
CRectsegRect=pSegStyle->GetSegRect();
if(pSegStyle->m_bPageRightAlign==false&&pHeaderStyle->m_emAlignment==centeralign)
{
segRect.OffsetRect(m_pGrid->GetHeaderCenterOffsetX(),0);
}
//算出表头数据框的对应屏幕框
segRect=adapter.CalcScreenRect(segRect);
//有框,有字符串,则在对应的框中画出那个字符串
DrawSegment(pDC,pSegStyle,pSegData->m_sValue,segRect,adapter);
pDC->SelectObject(pOldFont);
}
}
6,分析下DrawFormDataLine画表格里面的表体行
在CGridSlice:
:
DrawDataLineCell下断点即可得到以下堆栈
CGridSlice:
:
DrawFormDataLine
CGridSlice:
:
DrawWithPolicy
CDataDrawerPolicy:
:
DrawCell
CGridSlice:
:
DrawDataLineCell
画表体行主要是通过上面的函数执行到此的。
此函数讲点重点的骨架即可:
//得到表体行的格式信息
CTableLineStyle*pStyle=&m_pGrid->GetPrintParam()->m_FormBodyStyle.m_DataLineStyle;
//得到表体行的数据信息(主要就是此单元格内的字符串是啥)
CDataCell*pData=m_pGrid->GetData(row,col);
//得到表体行的框位置(主要是通过Cgrid先前的计算分页信息所存贮信息运算得到)
CRectrect=m_pGrid->GetDataLineRect(row,col);
//有框,有字符串,就开始画这个单元格里面的字符串了
DrawCellWithStyle(pStyle,pDC,sCellData,rect,alignment);
7,画自定义表体
此运算主要是在CGridSlice:
:
Draw()函数中判断style这个xml串中是否有如下属性
<自定义表体是否启用="是">
if(pUDBodyStyle->m_bIsUsing==TRUE)
DrawFormUserDefineBody(pDC,*pAdapter);
else
DrawFormBody(pDC,*pAdapter);
如果有,则进行DrawFormUserDefineBody函数,它就是画自定义表体的。
此函数跟DrawFormBody类似,看懂前面1个,再看这个即可。
它最大的不同就是常规表体取框是通过m_pGrid->GetDataLineRect(row,col)的方式,而自定义表体的框的大小是在style这个xml串中自己指定的。
例如,如下一个
<自定义表体是否启用="是"行宽="1000"行高="325"打印表头="是">
<字段关键字="0"名字="业务类型"打印="是"字体名="Tahoma"字体大小="11"粗体="否"下划线="否"斜体="否"左顶点="0,0"宽="339"高="45"颜色="#000000"边框="15"/>
自定义表体>
所以取框的大小是由这个函数搞定的:
CRectrect=m_pGrid->GetUDFormBodyHeaderRect(row,col,iUDLineindex);
看懂这里其它的就一起自然了。
无外乎取了框,再取了字符串,就可以画框,画字符串了。
8,关于那些style对应的数据结构。
在PrnParam.h中有很多对应表体头,表体行的数据结构。
有的是一层包一层。
不过其本质都是对style那个xml中的数据属性进行封装,这样那些属性就可以拿到控件里面用了。
可以先阅读PrnParam.h,里面注释很多,至少能告诉你那些数据结构的组成。
然后这些数据结构,大部分在SetDataStyleXML绑定数据时生成。
在ContentHandler.cpp随便找个解析xml的函数下断点,(比如CXMLStyleHandler:
:
parseFormBodyStyle)即可看到这个过程。
3.在VB中引用打印控件
VB中点击主菜单中的“工程->部件”或者直接按Ctrl+T热键,随后出现的“部件”对话框中选中“PrintControlActiveXControlmodule”,然后点击“确定”,左侧的工具条中将出现该控件的图标,如下图所示:
如下图:
需要注意的是,基于特定的理由,本控件取消了“运行时不显示”的特性,因此,为了防止运行时显示出控件本身的窗口,应该在控件的属性窗口中设定Visible为FALSE,如图:
OCX文件的方法函数图例如下
(vs2005的对象浏览器添加PrintControl.ocx即可)
4.打印控件接口介绍
1)SetDataStyleXML
为控件绑定格式和数据XML文件(或字符串)。
本方法是使用其他方法的先决条件(AboutBox方法除外)。
语法:
longSetDataStyleXML(constVARIANTFAR&varDataXML,
BOOLbDataIsFile,
constVARIANTFAR&varStyleXML,
BOOLbStyleIsFile,
constVARIANTFAR&varModuleID)
参数:
varDataXML
字符串
指明数据XML,含义由bDataIsFile决定。
bDataIsFile
布尔值
如果为True,表示varDataXML为数据XML文件的绝对路径或者相对路径;
如果为False,表示varDataXML为数据XML字符串本身。
varStyleXML
字符串指明格式XML,含义由bStyleIsFile决定。
bStyleIsFile
布尔值
如果为True,表示varStyleXML为格式XML文件的绝对路径或者相对路径;
如果为False,表示varStyleXML为格式XML字符串本身。
varModuleID
字符串
模版ID。
本参数可由调用者自由定义,用做开始打印时的打印任务名,可以为空,但
建议使用有意义的字符串标识打印任务。
返回值:
长整形,0表示成功,非0表示错误
调用控件的SetDataStyleXML方法的示例代码如下:
OptionExplicit
PrivateSubbtnBind_Click()
DimlRetAsLong
DimsDataAsString
DimsStyleAsString
DimsModuleIdAsString
sData=txtData.Text
sStyle=txtStyle.Text
sModuleId=txtModuleID.Text
lRet=printer.SetDataStyleXML(sData,True,sStyle,True,sModuleId)
MsgBoxlRet
EndSub
如果使用XML文件作为输入(上例中),那么sData和sStyle为文件的路径(绝对路径和相对路径均可),如果以XML字符串作为输入,那么sData和sStyle为XML字符串本身,同时第2和第四个参数应为False。
sModuleId为单据的模版名(注:
本控件使用该字符串作为打印任务名,并为使用者提供一个区别各类格式XML的标志)。
2)ExportToFileEx
将XML的内容输出到其他格式的文件(一般指文件型数据库),支持输出到rep文件(需要PrnExtension.DLL)。
语法:
longExportToFileEx(longlJobId,
constVARIANTFAR&varColType,
constVARIANTFAR&varColSize,
constVARIANTFAR&varColName,
constVARIANTFAR&varTempDBPath)
参数:
lJobId
长整形
指定需要输出的任务ID,即XML数据文件包含多个任务时的第几个任务,第一个任务ID为0。
varColType
字符串
该参数指定输出时各个字段的类型,各个字段类型之间用英文逗号“,”隔开,组成字段类型字符串,并且中间不能有空格。
例如:
”10,10,5,5”表示总共有4个字段,各字段类型分别为:
字符串(dbText)、字符串、货币(dbCurrency)和货币。
字段类型见“备注”部分。
该参数不能为空。
如果指定的字段类型个数不足,那么余下未指定类型的字段类型被认为是字符串类型(即10)。
注意:
该参数不能写成:
”dbText,dbText,dbCurrency,dbCurrency”。
varColSize
字符串
该参数指定各个字段的大小,同样,各个字段大小之间用英文逗号“,”隔开(中间不允许有空格),组成字段大小字符串,并与字段类型字符串相对应。
对应于前例,字段大小字符串为:
”50,50,8,8”,表示第一个文本型字段的大小为50字节,第二个文本型字段大小也为50字节,后两个货币金额型字段大小均为8个字节。
各字段类型对应的字段大小参见“备注”部分。
该参数不能为空。
如果指定的字段大小个数不足,那么余下未指定大小的字段被认为是254。
注意:
无论本参数或者上一个参数(varColType)是否指定了足够长的字段,两个参数指定的个数应该保持一致,例如都只指定了3项,否则将可能导致不可预知的错误。
varColName
字符串
该参数指定各个字段的字段名用于输出。
各个字段名之间用英文逗号“,”隔开(中间不能有空格,否则空格将被认为是字段名的一部分),组成字段名字符串。
注意各字段名不需要额外的引号。
例如:
”摘要,会计科目,贷方金额,借方金额”。
本参数可以为空字符串。
如果为空,那么控件将使用表体的表格头(即上部固定行)的最后一行个列的列名作为字段名用于输出。
如果本参数为非空字符串,并且指定的列数不足,那么未指定的列使用诸如“NO_NAME1”类似字段名进行输出。
VarTempDBPath
字符串
指定临时数据库(Access文件)的路径。
如果为空串,那么使用缺省数据库:
%System%\UFCOMSQL\UFFormat.mdb。
如果本参数非空,但指定的Access文件不存在,那么函数将创建该数据库(程序退出后并不会删除该库)。
指定的Access文件必须是Access97格式的,否则函数将产生错误。
返回值:
成功返回0,用户取消操作返回3999,其他为错误,参见“错误码”参考。
备注:
使用本方法之前必须先绑定格式和数据XML。
当控件属性ExportTableOnly被设置成FALSE时,调用本方法不仅输出表体的内容,还将输出表头和表尾的各个字段的内容。
无论是否仅输出表体,本方法的三个参数:
sColTypeList、sColSizeList、sColNameList都仅用于指定表体部分输出的字段类型,大小和字段名,而对于表头和表体的各个字段,输出格式均为字符串类型,255个字节大小,字段名为字段的关键字。
如果没有提供关键字,则自动生成字段名。
所有表头表尾字段输出时,其相应字段名都会增加“(表头)”或者“(表尾)”的后缀,以避免和表体部分的字段名名称冲突。
需要指出的是,输出时指定的数据库类型可能影响到输出是否成功。
这是因为各种类型的数据库对字段名长度,各种数据类型的支持程度和大小限制,单个表所允许的记录条数都有各自的限制。
字段类型定义如下:
♦dbBoolean=1,
♦dbByte=2,
♦dbInteger=3,
♦dbLong=4,
♦dbCurrency=5,
♦dbSingle=6,
♦dbDouble=7,
♦dbDate=8,
♦dbText=10,
♦dbLongBinary=11,(不支持)
♦dbMemo=12,
♦dbGUID=15,(不支持)
对应于以上各字段类型,有如下字段大小列表:
字段类型
字段大小
说明
dbBoolean
1(byte,下同)
Yes/No,同True/False
dbByte
1
Byte
dbInteger
2
Integer
dbLong
4
Long
dbCurrency
8
Currency
dbSingle
4
Single
dbDouble
8
Double
dbDate
8
Date/Time
dbText
1-255
Text(String)
dbLongBinary
0
LongBinary
dbMemo
0
Memo(String)
dbGUID
16
GUID
以上说明可以参看MSDN:
CDaoFieldInfo。
绑定了格式和数据之后,可以使用ExportToFile方法将数据中表体的内容导出到系统中已安装有ISAM驱动的文件型数据库中,例如dBase,Foxpro,Excel,HTML文件,Text文件,Lotus,Paradox,Access等,如以下示例代码:
PrivateSubbtnExport_Click()
DimsTypeListAsString
DimsSizeListAsString
DimiAsLong
DimeAsLong
i=0
sTypeList="10,10,5,5"
sSizeList="50,50,8,8"
e=printer.ExportToFileEx(i,sTypeList,sSizeList,"","")
MsgBoxe
EndSub
该方法将XML数据文件中表体的内容根据指定的字段类型,字段大小和字段名(如果没有提供字段名,将使用表格头固定行最后一行的各列名作为字段名)导出到用户指定的其他格式文件。
该方法将弹出一个文件保存对话框,在这个对话框中,用户可以选择导出文件类型并填写文件名,如下图所示:
3)PageSetup
显示页面设置对话框,允许用户在打印或预览前,以及预览过程中对打印机设置,纸张设置,以及页面各个元素的格式进行调整。
语法:
LongPageSetup()
参数:
无
返回值:
长整形,0表示成功,-1表示用户点击“取消”按钮返回,非0表示错误,具体请参“错误码”参考。
备注:
使用本方法之前必须先绑定格式和数据XML。
绑定完数据和格式之后可以使用PageSetup方法进行页面设置,如以下示例代码:
PrivateSubbtnPageSetup_Click()
printer.PageSetup
EndSub
以上方法将显示如下所示的对话框:
在本对话框中可以设置各种打印格式。
4)PrintPreview
显示打印预览窗口。
语法:
longPrintPreview();
参数:
无
返回值:
长整形,0表示成功,非0表示错误,参见“错误码”参考。
备注:
使用本方法之前必须先绑定格式和数据XML。
绑定了格式和数据以后,可以使用PrintPreview方法查看打印预览,如以下示例代码:
PrivateSubbtnPr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- U8 开发 打印 控件