U8开发之打印控件Word格式.docx
《U8开发之打印控件Word格式.docx》由会员分享,可在线阅读,更多相关《U8开发之打印控件Word格式.docx(68页珍藏版)》请在冰豆网上搜索。
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_HeaderSegStyleArray;
//创建字体
CFontbaseFont;
pHeaderStyle->
CreateRatioFont(baseFont,adapter.GetDispRatio());
CFont*pOldFont;
CFontsegFont;
//枚举表头数据集合
for(inti=0;
i<
pSegStyleArray->
GetSize();
i++)
//得到其中一个表头数据
CSegStyle*pSegStyle=pSegStyleArray->
GetAt(i);
//通过CsegStyle找到对应的表头字符串CSegment。
CSegment*pSegData;
if(pSegStyle->
IsUnnamedSegment())
{
pSegData=m_pGrid->
GetHeaderUnnamedSegment(i);
}
else
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);
SetTextColor(pHeaderStyle->
baseFont);
//得到表头数据的框的大小
CRectsegRect=pSegStyle->
GetSegRect();
m_bPageRightAlign==false&
&
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
DrawWithPolicy
CDataDrawerPolicy:
DrawCell
DrawDataLineCell
画表体行主要是通过上面的函数执行到此的。
此函数讲点重点的骨架即可:
//得到表体行的格式信息
CTableLineStyle*pStyle=&
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"
/>
/自定义表体>
所以取框的大小是由这个函数搞定的:
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,
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,
varColName,
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
Single
dbDouble
Double
dbDate
Date/Time
dbText
1-255
Text(String)
dbLongBinary
LongBinary
dbMemo
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表示错误,具体请参“错误码”参考。
绑定完数据和格式之后可以使用PageSetup方法进行页面设置,如以下示例代码:
PrivateSubbtnPageSetup_Click()
printer.PageSetup
以上方法将显示如下所示的对话框:
在本对话框中可以设置各种打印格式。
4)PrintPreview
显示打印预览窗口。
longPrintPreview();
长整形,0表示成功,非0表示错误,参见“错误码”参考。
绑定了格式和数据以后,可以使用PrintPreview方法查看打印预览,如以下示例代码:
PrivateSubbtnPr