在DELPHI中如何实现打印功能
- 格式:doc
- 大小:25.50 KB
- 文档页数:6
delphi printerdialog 用法Delphi是一种集成开发环境(IDE),用于创建Windows应用程序。
其中一个常见的用途是与打印机进行交互,以实现打印功能。
PrinterDialog是Delphi中用于显示打印对话框的函数。
在Delphi中,可以使用PrinterDialog函数来显示打印对话框,让用户选择打印机、打印范围、打印份数等打印参数,然后进行打印操作。
要在Delphi中使用PrinterDialog函数,首先需要包含Printers单元。
Printers单元提供了用于处理打印机和打印操作的类和函数。
然后可以在需要的地方调用PrinterDialog函数来显示打印对话框。
下面是一个简单的示例:```delphiuses Printers;procedure TForm1.Button1Click(Sender: TObject);beginif PrinterSetupDialog1.Execute thenbeginPrinter.BeginDoc;tryPrinter.Canvas.TextOut(100, 100, 'Hello, World!');finallyPrinter.EndDoc;end;end;end;```在这个示例中,当用户点击Button1时,会调用PrinterSetupDialog1.Execute方法显示打印对话框。
用户可以在打印对话框中选择打印机、打印范围等参数,然后点击“打印”按钮进行打印。
在Printer.BeginDoc和Printer.EndDoc之间的代码将在打印操作开始前和结束后执行,可以在其中进行打印操作。
除了显示打印对话框,PrinterDialog函数还可以用于获取用户在打印对话框中选择的打印参数,以便在程序中进行进一步处理。
通过Printer.PrinterIndex属性可以获取用户选择的打印机索引,通过Printer.Copies属性可以获取用户选择的打印份数,通过Printer.PageWidth和Printer.PageHeight属性可以获取打印纸张的宽度和高度等。
图1:单据管理示意图摘要:本文用Delphi+Fastreport 为例介绍了用数据库后台存储单据文件前台进行调用很好的解决了后台存储与用户本地自定义设置之间的矛 盾,还介绍了通过编写通用式主从结构的单据打印程序快速解决各种单据的打印输出以及用cross-tab 技术解决交叉表样式报表的输出。
这些方法的 实现很好的解决了ER P 系统中单据输出和报表打印问题,同时较方便的实现了用户对单据和报表样式自定义的需求。
关键词:ER P 系统;后台;套打;交叉表;单据 中图分类号:T P302.1 文献标识码:A 文章编号:1003-9767(2011)05-0054-03下载:将存于后台表中的单据字段通过流文件方式保存至本地相 1. 单据文件的存储与用户自定义FastReport 中报表默认是以文件形式存储于各客户端本地系统 中,以其调用速度快而获得程序的首选,但这种方式更新时必须在各 客户端站点之间进行手动同步操作,给后期的报表维护带来了极大的不便,因此往往适用于站点数量较少的系统应用场合,在ER P 系统应用中,一般采用将FastReport 报表文件以image 字段的形式存储于后台数据库中,再通过相应的下载和上传操作实现对数据库内image 字段(即相应报表文件)的修改。
应的报表文件。
try SetStream := TFileStream.Create(ReportFileName, fmC reate orfmShareExclusive);// 保存相应字段内容到文件流中 TBlobField(ADOQueryBill.FieldByName('xt_bill_attach')). SaveToStream(SetStream);MessageDlg('报表文件下载成功!', mtInformation, [mbOk], 0);exceptMessageDlg('报表文件下载过程中遇到了错误!', mtError,[mbOk], 0);end; 上传至服务器:将重新设置的本地报表文件上传至后台表xt_bill 相应记录。
开发IE控件ActiveX(Delphi打印控件)关键字:activex ie控件fastreport一直以来都觉得开发IE控件是一件非常难的事情,都是一些比较资深的程序员开发的,对于开发IE控件真的是觉得无从下手。
经过这几天的,查资料,问别人,瞎摸索终于做出了我的第一个IE控件--汽车电子客票打印控件。
下面按照自己的步骤,记录一下,以免以后自己都忘了,我这里是用Delphi7开发的(学校的课程设计时学过,后来一直都没用过,手生得很),使用了FastReport报表打印控件(/en/),以及Delphi7WebDeploy发布工具(/article.asp?articleid=4381):1、安装Delphi及插件,由于不会在Delphi上安装插件,还是费了不少功夫,问别人。
2、新建一个ActiveX工程,我这里选的是“ActiveX Form”,至于其它的选项,我还真不知道是用来开发什么的。
3、开发Delphi程序,接下来的事情,就是拖控件,写代码了。
其中很多时候需要调试,不知道有没有什么好的办法,自己觉得开发ActiveX控件,调试还是比较麻烦的,所以,我基本上是先在普通的Application Form上先把一些比较难弄、需要多次的程序写好,再拷到“ActiveX Form”工程中(详细的delphi+fastReport的开发过程下面再说)。
4、用WebDeploy发布,之前需要先在“Web deployment options”里,选择发布路径,发布后,会自动生成一个html文件了一个ocx控件,其中html 里的代码还需要自己去调一下,大小啊,位置啊,还有就是object标签的ocx 路径,最好改成相对路径,否则好像会报access拒绝的错误。
5、用IE打开这个html,选择警告中的“允许阻止的内容”,这样就会安装控件了,它安装在了“C:\WINDOWS\Downloaded Program Files”这个路径下,如果需要再次改代码、调试,你需要从这里把它右键删除掉(需要关掉这个html 页面,否则删不掉)6、接下来你会觉得,安装的这个控件的图标有点丑(delphi的默认图标),在project->options->application发现这个东西,还不让改,怎么办,查资料,“/t/20041021/14/3477746.html”我好像两种办法都试了一次,但总是改不了,后来重启一次,发现这个是已经改掉了。
报表打印在数据库开发应用时,一般都离不开报表打印功能,Delphi 6.0提供了一种完善易用的打印组件---QReport,利用它可是非常方便的实现报表打印功能,这里不准备详细讨论实现报表的一切方法,具体问题已经有不少资料,不过一般的资料都是介绍的应用英美模式构造报表,这种报表格式和国内一般的习惯并不相同,下面,我们将通过一个实际的例子,说明如何构造一个符合我们习惯的报表。
有了这样的基础,实现其它样式的报表并不是太困难的事情。
一、QReport面板组件介绍QReport面板提供的组件可以分类以下几种类型:1,模板类:这类组件是作为快速构建报表的模板或容器,它实际上是QReport面板左边的前六个组件,包括QuickRep、QrsubDetall、QRStringBand、QRBand、QRChildBand、QRGroup。
其中,QuickRep是必用组件,它必须加入到一个空白的表单中,作为建立报表的基础,其它所有的组件都要放在这个组件之上。
QRBand也是一个必用组件,它用于显示具体内容,内容的类型由BandType 属性来决定。
其它几个组件的使用频率低一些,主要是构建特殊类型的报表。
2,显示一般内容的组件:这类组件主要是为了显示非数据库类型的内容,或者提供一些特定的功能,包括:QRLabel、QRExpr、QRSysData、QRMemo、QRExprMemo、QRRichText、QRShape、QRChart 等。
其中,QRExpr既可以显示一般数据,也可以显示数据库数据。
3,显示数据库内容的组件:该组件主要用于显示数据库中的数据,这些组件包括QRDBText、QRExpro、QRDBRichText、QRDBImage等。
4,其它组件:这些组件包括QRCompositeReport用于合并多个报表, QRPreview用于预览报表,至于 QRTextFilter、QRCSVFFilter、QRHTMLFilter等组件则用于输出报表内容,这些组件用的较少。
Delphi下使用并口控制打印机使用Delphi编程的人员如果需要在Windows下使用并口打印机逐行打印,而又不想使用Windows的驱动程序。
我们这里提供一种不需要任何外来的元件的方法。
Var F:TextFile; Str:string; Begin try Str:=’ 欢迎使用票据打印机!’+Chr(10; AssignFile(F, 'LPT1'; Rewrite(F; Write(F, Str; CloseFile(F; Except Messagedlg('数据发送失败!',mterror,[mbok],0; End; end; 如果需要控制并口打印机开钱箱,也只需要重新给Str如下赋值: Str:=Chr(27+'p'+Chr(0+Chr(25+Chr(255;Delphi下使用串口控制打印机使用Delphi编程的人员如果需要在Windows下使用串口控制顾客显示屏或串口打印机,就需要使用外来方式。
我们这里提供了API_COM.DLL这个链接库供调用。
首先把API_COM.DLL文件复制到编写的源程序目录下,接着在程序的开头声明调用的三个函数来源: var Form1: TForm1; {加入下面三行声明} functioncom_init(com:Integer; baud:Dword:Boolean;stdcall;external 'api_com.dll'; functioncom_rest:Boolean;stdcall;external 'api_com.dll'; function com_send(buf:PChar;len:Integer:Boolean;stdcall;external 'api_com.dll';implementation{$R*.DFM}Com_init(1,9600是打开串口进行通讯,1是打开COM1,波特率为9600。
delphi打印实现(节选)................{$R *.dfm}procedure SetPaperHeight(V alue:integer); //设置纸张高度-单位:mmvarDevice : array[0..255] of char;Driver : array[0..255] of char;Port : array[0..255] of char;hDMode : THandle;PDMode : PDEVMODE;beginif Value < 127 then Value := 127; //自定义纸张最小高度127mmif Value > 432 then Value := 432; //自定义纸张最大高度432mmPrinter.PrinterIndex := Printer.PrinterIndex;Printer.GetPrinter(Device, Driver, Port, hDMode);if hDMode <> 0 thenbeginpDMode := GlobalLock(hDMode);if pDMode <> nil thenbeginpDMode^.dmFields := pDMode^.dmFields or DM_PAPERSIZE orDM_PAPERLENGTH;pDMode^.dmPaperSize := DMPAPER_USER;pDMode^.dmPaperLength := Value * 10;pDMode^.dmFields := pDMode^.dmFields or DMBIN_MANUAL;pDMode^.dmDefaultSource := DMBIN_MANUAL;GlobalUnlock(hDMode);end;end;Printer.PrinterIndex := Printer.PrinterIndex;end;procedure SetPaperWidth(V alue:integer); //设置纸张宽度:单位--mmvarDevice : array[0..255] of char;Driver : array[0..255] of char;Port : array[0..255] of char;hDMode : THandle;PDMode : PDEVMODE;beginif Value < 76 then Value := 76; //自定义纸张最小宽度76mmif Value > 216 then Value := 216; //自定义纸张最大宽度216mmPrinter.PrinterIndex := Printer.PrinterIndex;Printer.GetPrinter(Device, Driver, Port, hDMode);if hDMode <> 0 thenbeginpDMode := GlobalLock(hDMode);if pDMode <> nil thenbeginpDMode^.dmFields := pDMode^.dmFields or DM_PAPERSIZE orDM_PAPERWIDTH;pDMode^.dmPaperSize := DMPAPER_USER;pDMode^.dmPaperWidth := Value * 10; //将毫米单位转换为0.1mm单位pDMode^.dmFields := pDMode^.dmFields or DMBIN_MANUAL;pDMode^.dmDefaultSource := DMBIN_MANUAL;GlobalUnlock(hDMode);end;end;Printer.PrinterIndex := Printer.PrinterIndex;end;//======================================绘基础几何图型函数======================//--------------------圆--------------------------------------------------------procedure _Circle(x,y,r,N:real);varIntLineWidth:Integer;beginx:=x*mm_H;y:=y*mm_V;r:=r*mm_H;IntLineWidth:=Round(N*mm_H);MyCanvas.Pen.Width:=IntLineWidth;MyCanvas.Ellipse(round(x-r),round(y-r),round(x+r),round(y+r));end;function _outTxt(x,y:Real;Txt:String;FontSize:Real;FontName:String):Boolean;varLogRec: TLOGFONT;OldFont, NewFont: HFONT;i: LongInt;begin// case PrnMode of{ 1: beginwith printer dobeginGetObject(Canvas.Font.Handle, SizeOf(LogRec), @LogRec);LogRec.lfOutPrecision := OUT_TT_ONL Y_PRECIS;LogRec.lfFaceName :='宋体';LogRec.lfHeight:=round(FontSize*mm_V);LogRec.lfWeight:=0;NewFont := CreateFontIndirect(LogRec);OldFont := SelectObject(Canvas.Handle,NewFont);end;x:=Round((x+PageLeft)*mm_H);y:=Round((y+PageTop)*mm_V);MyCanvas.TextOut(round(x),round(y),txt);end; }// 2:beginx:=Round((x+PageLeft)*mm_H);y:=Round((y+PageTop)*mm_V);MyCanvas.Font.Height:=round(FontSize*mm_V);:=FontName;MyCanvas.TextOut(round(x),round(y),txt);end;// end;end;//移动坐标点procedure _Move(x,y:Real);beginPoint1.X:=point1.X+round(x*mm_H);point1.Y:=Point1.Y+round(y*mm_V);MyCanvas.MoveTo(point1.X,point1.Y);end;procedure _line(x1,y1,x2,y2,LineWidth:Real);varpoint2:TPoint;IntLineWidth:Integer;begin// if x1+y1<>0 then_move(x1,y1); //移动到起点坐标point2.X:=Point1.X+round(x2*mm_H);point2.Y:=Point1.Y+round(y2*mm_V);IntLineWidth:=Round(LineWidth*mm_H); //输出线宽MyCanvas.Pen.Width:=IntLineWidth; //设置线宽MyCanvas.LineTo(point2.X,point2.Y);point1:=point2;end;procedure TForm1.FormCreate(Sender: TObject);varTmpQry : TADOQuery;beginMyCanvas:=Image1.Canvas;ADOCOnnection1.Connected := false;ADOConnection1.ConnectionString :='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+GetCurrentDir()+'\data.mdb;Persist Security Info=False';ADOCOn:=ADOConnection1;ADOTable1.Active := true;TmpQry := OpenDB('select * from report order by ID',ADOCon);ComboBox1.Items.Clear;SetLength(TabIds,TmpQry.RecordCount);while not TmpQry.Eof dobeginComboBox1.Items.Add(VarToStr(TmpQry.FieldValues['Title']));TabIds[TmpQry.RecNo-1]:=TmpQry.FieldValues['id'];TmpQry.Next;end;if ComboBox1.Items.Count>0 then ComboBox1.ItemIndex :=0;TmpQry.Freeend;procedure recover;beginpoint1.X := round(PageLeft*mm_H);point1.Y := round(PageTop*mm_V);end;procedure _Grid(Id:Integer;Sql:String;Grid,Data:Boolean);varTmpQry,TmpQry1 : TADOQuery;x1,y1,x2,y2,r,w,FontSize:real;txt : String;classId : Integer;FontName : TFontName ; //显示使用的字体TmpColor:TColor;beginif Sql<>'' then TmpQry1 := OpenDB(sql,ADOCon);Sql := 'select * from TableLib where hidden=0 and tabId='+IntToStr(Id);if (not Grid) and (data) then sql:=sql+' and classId=4';if (grid) and (not data) then sql:=sql+' and classId<>4';TmpQry := OpenDB(Sql,ADOCon);while not TmpQry.Eof dobeginx1 := TmpQry.FieldValues['x1'];y1 := TmpQry.FieldValues['y1'];w := TmpQry.FieldValues['width'];if not TmpQry.FieldValues['relatively'] then recover; //若非相对坐村,恢复原点ClassId := TmpQry.FieldValues['ClassId'];case ClassId of1 : begin //标签txt := VarToStr(TmpQry.FieldValues['text']);if not TmpQry.FieldByName('FontSize').IsNull thenFontSize := TmpQry.FieldValues['FontSize']else FontSize := 2.5;if not TmpQry.FieldByName('FontName').IsNull thenFontName:=TmpQry.FieldValues['FontName']else FontName:='宋体';MyCanvas.Font.Style:=[];if TmpQry.FieldValues['FontBold'] thenMyCanvas.Font.Style:=[fsBold];_outTxt(x1,y1,txt,FontSize,FontName);end;2 : begin //直线x2 := TmpQry.FieldValues['x2'];y2 := TmpQry.FieldValues['y2'];_line(x1,y1,x2,y2,w);end;3 : begin //圆r := TmpQry.FieldValues['r'];_circle(x1,y1,r,w);end;4 : begin //字段if not TmpQry.FieldByName('text').IsNull thenbeginif not TmpQry1.FieldByName(TmpQry.FieldValues['text']).IsNull thenbegintxt := VarToStr(TmpQry1.FieldValues[TmpQry.FieldValues['text']]);if not TmpQry.FieldByName('FontSize').IsNull thenFontSize := TmpQry.FieldValues['FontSize']else FontSize := 2.5;if not TmpQry.FieldByName('FontName').IsNull thenFontName:=TmpQry.FieldValues['FontName']else FontName:='宋体';MyCanvas.Font.Style:=[];if TmpQry.FieldValues['FontBold'] thenMyCanvas.Font.Style:=[fsBold];TmpColor := MyCanvas.Font.Color;MyCanvas.Font.Color := clBlack;_outTxt(x1,y1,txt,FontSize,FontName);MyCanvas.Font.Color := TmpColor;end;end;end;end;TmpQry.Next;end;TmpQry.Free;end;procedure _init(PageSize:TPoint);begincase PrnMode of1: beginPhysicalWidth:=PageSize.x; //物理页宽PhysicalHeight:=PageSize.Y; //物理页高PageWidth:=printer.PageWidth; //逻辑页宽PageHeight:=printer.PageHeight; //逻辑页高end;2: beginPageWidth:=PhysicalHeight; //逻辑页宽PageHeight:=PhysicalHeight; //逻辑页高end;end;end;//---------------------------------------------------------------------------------procedure TForm1.OutPut(PrnMode:Integer;Grid,data:Boolean);varPaperW,PaperH:integer;PrintDialog1:TPrintDialog;LogRec: TLOGFONT;OldFont, NewFont: HFONT;PageSize:Tpoint;pw,ph,PointX,PointY:Integer; //纸张设置TabId : Integer;TmpQry :TADOQuery;Sql:String;beginTabId := ComboBox1.ItemIndex+1; //报表号Sql := 'select * from report where id='+IntToStr(TabId);TmpQry := OpenDb(Sql,ADOCon);if not TmpQry.Eof thenbeginPaperW := TmpQry.FieldValues['PaperWidth'];paperH := TmpQry.FieldValues['PaperHeight'];Sql := VarToStr(TmpQry.FieldValues['Sql']);if not ADOTable1.Eof thensql := _replace(sql,'@id@',VarToStr(ADOTable1.FieldValues['id']))else sql :='';PrintDialog1:=TPrintDialog.Create(nil);PageLeft := TmpQry.FieldValues['Left'];PageTop := TmpQry.FieldValues['Top'];case PrnMode of1: beginif PrintDialog1.Execute thenbeginSetPaperHeight(paperH);SetPaperWidth(PaperW);Escape(Printer.Handle, GETPHYSPAGESIZE, 0,nil,@PageSize); //取得物理页尺寸PointX:=GetDeviceCaps(Printer.Handle,LOGPIXELSX);PointY:=GetDeviceCaps(Printer.Handle,LOGPIXELSY);mm_H:=PointX/25.4;mm_V:=PointY/25.4;_Init(PageSize);Printer.Title:=VarToStr(TmpQry.FieldValues['title']);MyCanvas := Printer.Canvas;Printer.BeginDoc;MyCanvas.Brush.Color:=clBlue;MyCanvas.Brush.Style := bsclear;MyCanvas.Pen.Color:=clGreen;MyCanvas.Font.Color := clGreen;Zoom:=TmpQry.FieldValues['Zoom'];mm_H := mm_H*zoom;mm_V := mm_V*zoom;_Grid(TabId,Sql,Grid,data);Printer.EndDoc;end;end;2: beginmm_H:=2;mm_V:=2;Zoom := ComboBox2.ItemIndex+2 ; //全局缩放比例mm_H := mm_H*zoom;mm_V := mm_V*zoom;Image1.Picture.Graphic.Width := 1;Image1.Picture.Graphic.Height := 1;Image1.Width := Image1.Picture.Graphic.Width;Image1.Height := Image1.Picture.Graphic.Height;Image1.Picture.Graphic.Width := round(PaperW*mm_H);Image1.Picture.Graphic.Height := round(PaperH*mm_V);Image1.Width := Image1.Picture.Graphic.Width;Image1.Height := Image1.Picture.Graphic.Height;Image1.Top:=10-ScrollBox1.VertScrollBar.Position;if Image1.Width+10>ScrollBox1.Width thenImage1.Left:=0-ScrollBox1.HorzScrollBar.Position+2elseImage1.Left:=((ScrollBox1.Width-Image1.Width) div 2)-8-ScrollBox1.HorzScrollBar.Position;Image1.Canvas.Brush.Style := bsSolid;// ---------清除预览画布上的残像Image1.Canvas.Brush.Color:=clWhite;Image1.Canvas.Pen.Color:=clWhite;Image1.Canvas.Rectangle(0,0,PageWidth,PageHeight);Shape1.Top:=Image1.Top+10;Shape1.Left:=Image1.Left+10;Shape1.Width:=Image1.Width;Shape1.Height:=Image1.Height;Shape1.Visible:=True;Image1.Visible := true;MyCanvas.Brush.Color :=clWhite;MyCanvas.FillRect(MyCanvas.ClipRect); //清除残留影像MyCanvas:=Image1.Canvas;MyCanvas.Brush.Color:=clBlue;MyCanvas.Brush.Style := bsclear;MyCanvas.Pen.Color:=clGreen;MyCanvas.Font.Color := clGreen;Zoom:=TmpQry.FieldValues['Zoom'];mm_H := mm_H*zoom;mm_V := mm_V*zoom;_Grid(TabId,Sql,Grid,data);end;end;end;TmpQry.free;end;//-----------------------------------------------------------------------------------procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);beginStart_Point.X:=x;Start_Point.Y:=y;end;procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);beginScrollBox1.HorzScrollBar.Position:= ScrollBox1.HorzScrollBar.Position+(Start_Point.X-x); ScrollBox1.VertScrollBar.Position:= ScrollBox1.VertScrollBar.Position+(Start_Point.Y-y); end;procedure TForm1.ToolButton1Click(Sender: TObject);beginOutPut(1,checkBox1.Checked,checkBox2.Checked);end;procedure TForm1.ToolButton2Click(Sender: TObject);beginOutPut(2,checkBox1.Checked,checkBox2.Checked);end;procedure TForm1.DBEdit10Change(Sender: TObject);beginDBText1.caption := NumToChnStr(StrToFloat(DBEdit10.Text),false);end;procedure TForm1.DBEdit12Change(Sender: TObject);beginDBText2.caption := NumToChnStr(StrToFloat(DBEdit12.Text),false);end;procedure TForm1.ADOTable1BeforePost(DataSet: TDataSet);beginADOTable1.FieldValues['cn_price'] := NumToChnStr(StrToFloat(DBEdit12.Text),false); ADOTable1.FieldValues['cn_rate'] := NumToChnStr(StrToFloat(DBEdit12.Text),false); end;procedure TForm1.PageControl1Change(Sender: TObject);beginif ADOTable1.State = dsEdit then ADOTable1.Post;ToolButton2.Click;end;procedure TForm1.Shape1ContextPopup(Sender: TObject; MousePos: TPoint;var Handled: Boolean);beginend;procedure TForm1.TabSheet2ContextPopup(Sender: TObject; MousePos: TPoint;var Handled: Boolean);beginend;end.procedure PrintDbGrid(DataSet:TDataSet;DbGrid:TDbGrid;Title:String);varPointX,PointY:integer;ScreenX:integer;i,lx,ly:integer;px1,py1,px2,py2:integer;RowPerPage,RowPrinted:integer;ScaleX:Real;THeight:integer;TitleWidth:integer;SumWidth:integer;PageCount:integer;SpaceX,SpaceY:integer;RowCount:integer;beginPointX:=Round(GetDeviceCaps(printer.Handle,LOGPIXELSX)/2.54);PointY:=Round(GetDeviceCaps(printer.Handle,LOGPIXELSY)/2.54);ScreenX:=Round(Screen.PixelsPerInch/2.54);ScaleX:=PointX/ScreenX;RowPrinted:=0;SumWidth:=0;printer.BeginDoc;With Printer.Canvas dobeginDataSet.DisableControls;DataSet.First;THeight:=Round(TextHeight('我')*2.5);//设定每行高度为字符高的1.5倍SpaceY:= Round(TextHeight('我')/4);SpaceX:=Round(TextWidth('我')/4);RowPerpage:=Round((printer.PageHeight-5*PointY)/THeight); //上下边缘各2厘米ly:=2*PointY;PageCount:=0;while not DataSet.Eof dobeginif (RowPrinted=RowPerPage) or (RowPrinted=0) thenbeginif RowPrinted<>0 thenPrinter.NewPage;RowPrinted:=0;PageCount:=PageCount+1;:='宋体';Font.size:=16;Font.Style:=Font.Style+[fsBold];lx:=Round((Printer.PageWidth-TextWidth(Title))/2);ly:=2*PointY;TextOut(lx,ly,Title);Font.Size:=11;Font.Style:=Font.Style-[fsBold];lx:=Printer.PageWidth-5*PointX;ly:=Round(2*PointY+0.2*PointY);if RowPerPage*PageCount>DataSet.RecordCount thenRowCount:=DataSet.RecordCountelseRowCount:=RowPerPage*PageCount;TextOut(lx,ly,'第'+IntToStr(RowPerPage*(PageCount-1)+1)+'-'+IntToStr(RowCount)+'条,共'+IntToStr (DataSet.RecordCount)+'条');lx:=2*PointX;ly:=ly+THeight*2;py1:=ly-SpaceY;if RowCount=DataSet.RecordCount thenpy2:=py1+THeight*(RowCount-RowPerPage*(PageCount。
第六讲程序重要功能及打印功能的实现《上》在本讲及下一讲中,我们来完成本程序最重要的一个功能:劳保发放。
此功能从原理上来讲不是太复杂,但实现起来需要动脑筋,稍有不慎就会导致发放错误。
下面我们来讲如何实现此功能。
劳保用品发放。
在前面的讲座中,心铃给大家讲了数据维护等一些功能,在劳保用品发放前必须对各种需要维护的数据做好维护工作,比如工种、岗位是否有调整,劳保用品的发放周期是否改变,部门是否有新进员工,是否有员工退休等等,这些工作的目的都是为了保证上次发放记录(对某些员工是初始发放记录)的完整性。
因为心铃在程序中采用的方式是发放记录中保存着发放周期、上次发放时间、工种等几个关键信息,所以上次发放记录的准确性是非常重要的。
下面我们来看看程序实现思路。
劳保用品发放要得到的结果是:本次发放劳保用品的员工姓名(编号)、劳保用品名称、发放数量,这是直接结果,同时我们还需要在发放的同时把发放记录中的劳保用品的上次发放时间更新为本次发放时间。
根据需要,我们要统计单个部门所有劳保用品名称、规格、发放数量,还要统计所有需要发放的劳保用品名称、规格、发放数量。
由于我们的发放记录数据表中是不保存这些信息的,所以我们需要建立一个数据表来保存本次发放的基本数据,便于随时查询、统计本次发放的各种信息。
心铃将此数据表命名为fftmp(发放临时表),此数据表字段如下:注意:上面的表格有点冗余,其实部门名称、员工姓名都是可以根据部门编号和员工编号查到的,这里主要是为了方便起见才这样处理的。
之所以称此表为发放临时表,主要是其数据寿命周期为到下次发放为止,在下次发放(我们公司是半年为一周期)时要清空此数据表。
下面我们就来看看如何用代码实现。
首先看发放界面图,见图(12-1)。
界面图上右下角有一个“初始化发放数据表”,此按钮的代码如下:procedure TForm3.BitBtn23Click(Sender: TObject);beginif MessageDlg('本功能每次发放前使用一次,且只能使用一次,请确认!', mtConfirmation, [mbYes, mbNo], 0) = mrYes thenbegintable11.EmptyTable;MessageDlg('初始化完毕,本次发放过程中不要再使用此功能!', mtInformation, [mbOk], 0);end;end;上面这段代码用了Emptytable这个数据表的方法来清空数据表,并在清空数据表前让用户确认、在清空后给出用户提示信息。
delphi printerdialog 用法全文共四篇示例,供读者参考第一篇示例:Delphi是一种功能强大的编程语言,被广泛用于Windows平台的应用程序开发。
在Delphi中,有一个名为PrinterDialog的组件,可以帮助开发者轻松应用打印功能到他们的应用程序中。
本文将介绍如何使用Delphi的PrinterDialog组件来实现打印功能,并提供一些示例代码和技巧。
我们来了解一下PrinterDialog组件的基本用法。
PrinterDialog组件可以让用户选择打印机、纸张大小、打印范围等打印参数,并通过简单的调用函数来执行打印操作。
通过PrinterDialog组件,开发者可以在应用程序中实现用户友好的打印功能,提升用户体验。
在Delphi中,使用PrinterDialog组件的基本步骤如下:1. 创建PrinterDialog对象:在应用程序中创建一个PrinterDialog对象,用于实现打印操作。
2. 设置打印参数:通过PrinterDialog对象的属性设置打印参数,如选择打印机、设置纸张大小、设置打印范围等。
3. 调用打印函数:调用PrinterDialog对象的Print函数来执行打印操作,打印完成后可以进行相应的处理,如提示用户打印完成、保存打印结果等。
```delphiprocedure TForm1.Button1Click(Sender: TObject);beginPrinterDialog1.Title := '选择打印机';PrinterDialog1.Execute;if PrinterDialog1.Printer = '' thenShowMessage('未选择打印机')elsebeginPrinter.BeginDoc;Printer.Canvas.TextOut(100, 100, 'Hello, World!');Printer.EndDoc;end;end;```在上面的示例代码中,我们通过一个按钮的点击事件来触发打印操作。
用Delphi 扩展WinCC 的数据查询打印功能(1.大庆石油学院;2. 大庆第四采油厂) 于显利1张宏杰2王文达2高宏宇1Yu,Xianli Zhang,hongjie Wang,wenda Gao,hongyu摘要:本文主要讨论了使用Delphi 编程语言,将西门子组态软件WinCC 的过程归档数据,通过Sybase 数据库的ODBC 连接,进行数据查询后输入到EXCEL表格里,实现了对WinCC 归档数据的灵活查询和复杂报表打印功能。
关键词:WinCC;Delphi;ODBC;Excel 报表中图分类号:TP311 文献标识码:AUsing Delphi Program to Expand WinCC Data Inquiry and Report PrintingAbstract: This paper mainly discusses how to import the WinCC process data to Excel sheet from Sybasedatabase via ODBC, and it solves commendably the problems of flexible data inquiry and complicated datareport based on Excel using Delphi program.Key words: WinCC; Delphi; ODBC; Excel report1.引言视窗控制中心WinCC(Windows Control Center)是一款优秀的工控组态软件,由德国西门子公司与微软公司共同开发研制, 它结合了西门子在过程自动化领域中的先进技术和微软软件开发的高级技术,并广泛应用于各种工业控制系统的数据采集及监控[1]。
WinCC本身也具有报表和过程数据归档功能,但在WinCC v6.0 以前的版本没有加入VBS 脚本语言,所以其归档数据不能直接在WinCC内进行数据库查询、过滤操作[2]。
TQ_Printrer 控件,是一个为方便需要控制打印命令而设计的跨平台专用控件,已包含标准ESC/POS 打印控制的基本指令在内(这些基本指令已能很好的满足多数项目使用)。
TQ_Printrer 控件让开发人员在开发跨平台项目相关打印控制时更加方便快捷。
控件支持Android 、iOS 以及WIN32/64的开发,可控制兼容ESC/POS 的小票打印机。
目前控件已在多个Android 、iOS 项目中配合蓝牙小票打印机使用。
控件下载:在csdn 上搜索“Delphi 10 Seattle 小票打印控件”一、控件安装1、在Delphi 10 Seattle 开发环境打开控件目录下print.dpk 文件(XE8下请使用print_XE8.dpk 文件)。
在项目管理器中选择WIN32。
2、右键单击项目,在弹出菜单中选择“install ”,安装控件。
严禁复制弹出下图说明安装成功(路径会不同)。
3、在项目中配置控件引用路径:打开或新建项目,打开菜单project ,找到Option ,在目标平台中选择“All CConfiguations - All platforms ”,将路径添加到Delphi Compiler->SearchPath 中。
如下两图:严禁复制制复禁严使用你控件放置的路径,绝对目录\TQ_Printer\DCU\FMX\D10\$(Platform)\Release ,这点很重要。
(XE8安装时请把D10改为XE8)二、了解控件新建一个项目,在Tool Palette 中选择 TQ_Printer 控件,并将其放置到窗体设计器。
切换到 Object Inspector ,点击ReadMe 属性后面的[…]按钮,可以查看控件说明。
如下图: 严禁复制制复禁严说明后半部分给出了使用的代码样例。
以下是控件使用说明: Pinit 初始化打印设置。
CR 换行控制FontSize(X,Y:Integer) 设置字体大小,x,y 分别为字体高宽放大倍数; 取值1时为正常大小,最大取值为8。
Delphi程序实现打印功能Delphi程序实现打印功能预备内容:一、新建一个窗体(Form1)二、在窗体上加memo1、Button1、Printdialog1这三个组件(都自带了的)。
思路过程:一、在程序代码页,最上边部分,有个粗体字Users,你在它下面加一个printers(这个不是粗体的)。
二、双击button按钮,咱要在这里写代码了。
三、先定义一个line变量,类型是integer,用来控制打印的行数。
再定义一个files为system.text,告诉程序这个东西是要它打印的文件。
四、将文件变量(files)通过assignprn函数来提交到打印机。
//可以这么理解:咱拿了个文件,命令打印机说:“呆会儿你把这个文件给我打印出来。
”五、通过rewrite函数,打开要输出的文件(files)。
//这个就理解为:打印机很无奈的拿了文件过去,翻看着。
六、设置文件(files)在打印机上的字体。
七、通过writeln函数,打印文(files)件的每行内容八、打印完了后,关闭要打印的文件。
简化过程(其实就是思路):一、在Users下写个printers二、定义两个变量。
三、通过assignprn函数把文件传到打印机上。
四、通过rewrite函数,让打印机打开文件。
五、设置字体。
六、打印每行内容七、关闭文件。
具体代码:{在Users下面加个printers}varline:integer; //定义一个line变量,用于下面控制打印各行内容files:system.text; //告诉系统说files是文本文件,是要打印机打印的文件beginif printdialog1.execute then //当printdialog1执行后beginassignprn(files); //通过assignprn函数将要打印的文件交给打印机rewrite(files); //让打印机打开文件准备打印printer.canvas.font.size:=12; //canvas是打印机的画板,用来打印文件的,直接设置字体for line:=0 to memo1.lines.count-1 do //以下是循环memo1的每个行beginwriteln(files,memo1.lines[line]); //打印每行内容 writeln(文件名,文本的某个行);end;system.close(files); //打印完了就关闭要打印的文件end;end;end;。
Delphi调用BarTender打印机1.使用Delphi调用BarTender来完成打印条码标签功能:a) 使用BarTender格式打印b) 格式中有需要变动的部分2. 设计标签a) 新建一个空白标签b) 在画面上加入一个条形码控件,一个文本控件c) 选中条形码控件,双击(或右键,属性),打开属性窗口;点击“高级”,选择“共享/名称”页,在共享名称中输入条形码控件的名字“BarCode1”;点击确定完成修改。
这个步骤来定义在Delphi中(或其它语言VB等)访问的对象名。
d) 同样的步骤,给文本控件设置名称为“Text1”e) 保存为“c:\test.btw”3. 导入ActiveX组件a) 打开Delphi(版本5.0及以上,其它没有测试)b) 选择菜单“项目”-->“导入类型库”(ProjectàImport Type Library)c) 在弹出的窗口中,列出可导入的类型库;找到“BarTender 7.75”,选中d) 将要导入的类名称会列在class names中,由于这里的类名称会与系统已存在类名称有重复,将这个全部复制出来,将类型名称前面都加上Bt。
如:TFormat修改为TBtFormat.e) 类名称修改完成后,点击”安装”(Install)f) 系统会安装组件到ActiveX控件页上4. 调用BarTender打印a) 新建应用程序b) 在窗体上拖一个TBtApplication控件(ActiveX页上),命名为btApp1c) 在窗体上放一个TButton控件,命名为btn1,双击btn1产生事件d) 填写事件代码如下:procedure TForm1.btn1Click(Sender: TObject);beginwith btApp1.Formats.Open('c:\test.btw', True, '') do//打开标签文件beginSetNamedSubStringValue('BarCode1', '1234567890'); //设置值SetNamedSubStringValue('Text1', 'Hello BarTender!');PrintOut(False, False); //打印Close(btDoNotSaveChanges); //关闭不保存end;btApp1.Quit(btDoNotSaveChanges); //退出end;。
在DELPHI中提供了一个PRINTERS程序单元,它说明了一个TPRINTER对象,封装了WINDOWS打印工作和输出打印机之间的接口,并提供常用的属性和方法,其中画布CANVAS是一个非常有用的属性,它代表了当前打印文件的表面,是以图形方式来工作的,整个的打印输出工作仅仅是将你打印的内容输出到TPRINTER的属性CANVAS上,当全部的输出工作完成以后,打印对象(TPRINTER)把CANVAS的属性值送到打印机上去。
下面举例来说明如何通过DELPHI实现文本内容的打印。
在DELPHI 中提供了PRINTDIALOG、PRINTERSETUPDIALOG两个控件允许我们进行打印机以及其他影响打印输出的选择,此外最重要的一点是要想实现打印功能必须在编译程序以前将PRINTERS加入到INTERFACE或者IMPLEMENTATION的UESE语句当中,因为PRINTER单元包括ASSIGNPRN和其他控制打印机的过程。
首先在FORM当中加入MEMO、PRINTDIALOG、PRINTERSETUPDIALOG和两个BUTTON控件,两个BUTTON的CAPTION分别为“打印设置”和“打印”。
然后编写BUTTON的事件驱动程序(代码在下面),这个简单的例子中只要单击“打印”按钮时便可以在打印机上输出文件0S2.TXT,打印事件的清单如下:implementationusesprinters;{$R*.DFM}procedureTForm1.BitBtn1Click(Sender:TObject);beginprintersetupdialog1.execute;//选择输出的打印机以及其他打印控制选项end;procedureTForm1.BitBtn2Click(Sender:TObject);varlines:integer;prntext:system.text;//将PRNTEXT声名为一个在SYSTEM程序单元当中定义的文本文件beginifprintdialog1.executethenassignprn(prntext);//将PRNTEST分配给打印机rewrite(prntext);//调用REWRITE函数,为输出打开已分配的文件printer.canvas.font:=memo1.font;//把当前MEMO1的字体指定给打印对象的CANVAS的字体属性forlines:=0tomemo1.lines.count-1dowriteln(prntext,memo1.lines[lines]);//把MEMO的内容写到打印机对象system.close(prntext);//关闭打印文件end;procedureTForm1.FormCreate(Sender:TObject);beginmemo1.lines.loadfromfile('c:\dos\os2.txt');//在FORM建立时读入C:\DOS\OS2.TXT文件end;end.2、图形的打印功能,简单的图形打印功能也如打印文本一样的容易,只是告诉打印机对象(TPRINTER)开始打印,把图形简单的复制到打印机上去,最后告诉打印机结束打印工作。
用Delphi+FastReport解决ERP系统开发中单据打印的实例探索5700字摘要:本文用Delphi+Fastreport为例介绍了用数据库后台存储单据文件前台进行调用很好的解决了后台存储与用户本地自定义设置之间的矛盾,还介绍了通过编写通用式主从结构的单据打印程序快速解决各种单据的打印输出以及用cross-tab技术解决交叉表样式报表的输出。
这些方法的实现很好的解决了ERP系统中单据输出和报表打印问题,同时较方便的实现了用户对单据和报表样式自定义的需求。
zuoe(‘xt_bill_attach’)).LoadFromStream(SetStream); try Post; MessageDlg(‘报表文件上传成功!’, mtInformation, [mbOk], 0); Requery; GotoBookmark(OldBookMark); except MessageDlg(‘报表文件上传过程中遇到了错误,上传失败!’, mtError, [mbOk], 0); end; end; 2、通用的主从式单据打印解决方案:在ERP系统应用中,单据种类复杂,有采购计划、采购订单、采购收货通知单、销售订单、销售出库通知单、库存调拨单、库存领用单等等,但仔细分析后我们发现其结构均为主从式的数据模型,为了找到通用的解决方案,我们在Delphi项目的DM模块下,增加ADOQueryParent作为主表的数据源,增加ADOQueryChild作为子表的数据源,增加frDBDataSetOrder作为FastReport数据源,增加frReportOrder作为FastReport作为报表控件,前端通过后台数据库的视图实现用户对数据源的控制,减少了对前台应用程序的维护频度,实现了报表文件、访问方式和数据源三者既相互独立,又兼顾统一。
2.1调用报表的过程描述如下:procedure PrintCheck(ReportName, --报表名称MasterViee, --主项数据视图名称MasterKeyFieldName, --主项数据关键字段名称DetailViee, --明细项数据视图名称DetailKeyFieldName, --明细数据关联字段名称SortByField --数据源排序字段名称: string; KeyFieldV alue: variant); 2.2过程代码如下:procedure PrintCheck(ReportName, MasterViee, MasterKeyFieldName, DetailViee, DetailKeyFieldName, SortByField: string; KeyFieldV alue: variant); Begin // 指定主项数据源‘ + MasterViee + ‘ e + ‘=:’ + MasterKeyFieldName); Parameters.Items[0].V alue := KeyFieldValue; Open; end; // 指定明细项数据源‘ + DetailViee + ‘ DetailKeyFieldName + ‘=:’ + DetailKeyFieldName); SQL.Add(‘ order by ‘ + SortByField); Parameters.Items[0].V alue := KeyFieldV alue; Open; end; // 装载相应单据 e from xt_bill eters.Items[0].V alue := ReportName; Open; if (DM.frDBDataSetOrder.DataSet DM.ADOQueryChild)then DM.frDBDataSetOrder.DataSet := DM.ADOQueryChild; BlobField(FieldByName(‘xt_bill_attach’)); // 从相应字段进行装载Title := FieldByName(‘xt_bill_name’).V alue; Sho示方式外经常会遇到交叉表式的数据输出要求,依靠传统的报表设计工具和方式显得特别麻烦,FastReport提供了一个Cross-tab的对象可以解决这个问题,但笔者经过多次反复测试后发现只有数据源提供正确且设置合理才会得到我们想要的输出格式。
Delphi打印纸张选项设置参数{ paper selections }{$EXTERNALSYM DMPAPER_LETTER}DMPAPER_LETTER = 1; { Letter 8 12 x 11 in }{$EXTERNALSYM DMPAPER_FIRST}DMPAPER_FIRST = DMPAPER_LETTER;{$EXTERNALSYM DMPAPER_LETTERSMALL}DMPAPER_LETTERSMALL = 2; { Letter Small 8 12 x 11 in } {$EXTERNALSYM DMPAPER_TABLOID}DMPAPER_TABLOID = 3; { Tabloid 11 x 17 in }{$EXTERNALSYM DMPAPER_LEDGER}DMPAPER_LEDGER = 4; { Ledger 17 x 11 in }{$EXTERNALSYM DMPAPER_LEGAL}DMPAPER_LEGAL = 5; { Legal 8 12 x 14 in }{$EXTERNALSYM DMPAPER_STATEMENT}DMPAPER_STATEMENT = 6; { Statement 5 12 x 8 12 in }{$EXTERNALSYM DMPAPER_EXECUTIVE}DMPAPER_EXECUTIVE = 7; { Executive 7 14 x 10 12 in }{$EXTERNALSYM DMPAPER_A3}DMPAPER_A3 = 8; { A3 297 x 420 mm }{$EXTERNALSYM DMPAPER_A4}DMPAPER_A4 = 9; { A4 210 x 297 mm }{$EXTERNALSYM DMPAPER_A4SMALL}DMPAPER_A4SMALL = 10; { A4 Small 210 x 297 mm }{$EXTERNALSYM DMPAPER_A5}DMPAPER_A5 = 11; { A5 148 x 210 mm }{$EXTERNALSYM DMPAPER_B4}DMPAPER_B4 = 12; { B4 (JIS) 250 x 354 }{$EXTERNALSYM DMPAPER_B5}DMPAPER_B5 = 13; { B5 (JIS) 182 x 257 mm }{$EXTERNALSYM DMPAPER_FOLIO}DMPAPER_FOLIO = 14; { Folio 8 12 x 13 in }{$EXTERNALSYM DMPAPER_QUARTO}DMPAPER_QUARTO = 15; { Quarto 215 x 275 mm }{$EXTERNALSYM DMPAPER_10X14}DMPAPER_10X14 = 16; { 10x14 in }{$EXTERNALSYM DMPAPER_11X17}DMPAPER_11X17 = 17; { 11x17 in }{$EXTERNALSYM DMPAPER_NOTE}DMPAPER_NOTE = 18; { Note 8 12 x 11 in }{$EXTERNALSYM DMPAPER_ENV_9}DMPAPER_ENV_9 = 19; { Envelope #9 3 78 x 8 78 }{$EXTERNALSYM DMPAPER_ENV_10}DMPAPER_ENV_10 = 20; { Envelope #10 4 18 x 9 12 }{$EXTERNALSYM DMPAPER_ENV_11}DMPAPER_ENV_11 = 21; { Envelope #11 4 12 x 10 38 }{$EXTERNALSYM DMPAPER_ENV_12}DMPAPER_ENV_12 = 22; { Envelope #12 4 \276 x 11 }{$EXTERNALSYM DMPAPER_ENV_14}DMPAPER_ENV_14 = 23; { Envelope #14 5 x 11 12 }{$EXTERNALSYM DMPAPER_CSHEET}DMPAPER_CSHEET = 24; { C size sheet }{$EXTERNALSYM DMPAPER_DSHEET}DMPAPER_DSHEET = 25; { D size sheet }{$EXTERNALSYM DMPAPER_ESHEET}DMPAPER_ESHEET = 26; { E size sheet }{$EXTERNALSYM DMPAPER_ENV_DL}DMPAPER_ENV_DL = 27; { Envelope DL 110 x 220mm }{$EXTERNALSYM DMPAPER_ENV_C5}DMPAPER_ENV_C5 = 28; { Envelope C5 162 x 229 mm }{$EXTERNALSYM DMPAPER_ENV_C3}DMPAPER_ENV_C3 = 29; { Envelope C3 324 x 458 mm }{$EXTERNALSYM DMPAPER_ENV_C4}DMPAPER_ENV_C4 = 30; { Envelope C4 229 x 324 mm }{$EXTERNALSYM DMPAPER_ENV_C6}DMPAPER_ENV_C6 = 31; { Envelope C6 114 x 162 mm }{$EXTERNALSYM DMPAPER_ENV_C65}DMPAPER_ENV_C65 = 32; { Envelope C65 114 x 229 mm }{$EXTERNALSYM DMPAPER_ENV_B4}DMPAPER_ENV_B4 = 33; { Envelope B4 250 x 353 mm }{$EXTERNALSYM DMPAPER_ENV_B5}DMPAPER_ENV_B5 = 34; { Envelope B5 176 x 250 mm }{$EXTERNALSYM DMPAPER_ENV_B6}DMPAPER_ENV_B6 = 35; { Envelope B6 176 x 125 mm }{$EXTERNALSYM DMPAPER_ENV_ITALY}DMPAPER_ENV_ITALY = 36; { Envelope 110 x 230 mm }{$EXTERNALSYM DMPAPER_ENV_MONARCH}DMPAPER_ENV_MONARCH = 37; { Envelope Monarch 3.875 x 7.5 in } {$EXTERNALSYM DMPAPER_ENV_PERSONAL}DMPAPER_ENV_PERSONAL = 38; { 6 34 Envelope 3 58 x 6 12 in } {$EXTERNALSYM DMPAPER_FANFOLD_US}DMPAPER_FANFOLD_US = 39; { US Std Fanfold 14 78 x 11 in } {$EXTERNALSYM DMPAPER_FANFOLD_STD_GERMAN}DMPAPER_FANFOLD_STD_GERMAN = 40; { German Std Fanfold 8 12 x 12 in } {$EXTERNALSYM DMPAPER_FANFOLD_LGL_GERMAN}DMPAPER_FANFOLD_LGL_GERMAN = 41; { German Legal Fanfold 8 12 x 13 in } {$EXTERNALSYM DMPAPER_ISO_B4}DMPAPER_ISO_B4 = 42; { B4 (ISO) 250 x 353 mm }{$EXTERNALSYM DMPAPER_JAPANESE_POSTCARD}DMPAPER_JAPANESE_POSTCARD = 43; { Japanese Postcard 100 x 148 mm } {$EXTERNALSYM DMPAPER_9X11}DMPAPER_9X11 = 44; { 9 x 11 in }{$EXTERNALSYM DMPAPER_10X11}DMPAPER_10X11 = 45; { 10 x 11 in }{$EXTERNALSYM DMPAPER_15X11}DMPAPER_15X11 = 46; { 15 x 11 in }{$EXTERNALSYM DMPAPER_ENV_INVITE}DMPAPER_ENV_INVITE = 47; { Envelope Invite 220 x 220 mm } {$EXTERNALSYM DMPAPER_RESERVED_48}DMPAPER_RESERVED_48 = 48; { RESERVED--DO NOT USE } {$EXTERNALSYM DMPAPER_RESERVED_49}DMPAPER_RESERVED_49 = 49; { RESERVED--DO NOT USE } {$EXTERNALSYM DMPAPER_LETTER_EXTRA}DMPAPER_LETTER_EXTRA = 50; { Letter Extra 9 \275 x 12 in } {$EXTERNALSYM DMPAPER_LEGAL_EXTRA}DMPAPER_LEGAL_EXTRA = 51; { Legal Extra 9 \275 x 15 in }{$EXTERNALSYM DMPAPER_TABLOID_EXTRA}DMPAPER_TABLOID_EXTRA = 52; { Tabloid Extra 11.69 x 18 in } {$EXTERNALSYM DMPAPER_A4_EXTRA}DMPAPER_A4_EXTRA = 53; { A4 Extra 9.27 x 12.69 in }{$EXTERNALSYM DMPAPER_LETTER_TRANSVERSE}DMPAPER_LETTER_TRANSVERSE = 54; { Letter Transverse 8 \275 x 11 in } {$EXTERNALSYM DMPAPER_A4_TRANSVERSE}DMPAPER_A4_TRANSVERSE = 55; { A4 Transverse 210 x 297 mm } {$EXTERNALSYM DMPAPER_LETTER_EXTRA_TRANSVERSE}DMPAPER_LETTER_EXTRA_TRANSVERSE = 56; { Letter Extra Transverse 9\275 x 12 in }{$EXTERNALSYM DMPAPER_A_PLUS}DMPAPER_A_PLUS = 57; { SuperASuperAA4 227 x 356 mm }{$EXTERNALSYM DMPAPER_B_PLUS}DMPAPER_B_PLUS = 58; { SuperBSuperBA3 305 x 487 mm }{$EXTERNALSYM DMPAPER_LETTER_PLUS}DMPAPER_LETTER_PLUS = 59; { Letter Plus 8.5 x 12.69 in }{$EXTERNALSYM DMPAPER_A4_PLUS}DMPAPER_A4_PLUS = 60; { A4 Plus 210 x 330 mm }{$EXTERNALSYM DMPAPER_A5_TRANSVERSE}DMPAPER_A5_TRANSVERSE = 61; { A5 Transverse 148 x 210 mm }{$EXTERNALSYM DMPAPER_B5_TRANSVERSE}DMPAPER_B5_TRANSVERSE = 62; { B5 (JIS) Transverse 182 x 257 mm }{$EXTERNALSYM DMPAPER_A3_EXTRA}DMPAPER_A3_EXTRA = 63; { A3 Extra 322 x 445 mm }{$EXTERNALSYM DMPAPER_A5_EXTRA}DMPAPER_A5_EXTRA = $40; { A5 Extra 174 x 235 mm }{$EXTERNALSYM DMPAPER_B5_EXTRA}DMPAPER_B5_EXTRA = 65; { B5 (ISO) Extra 201 x 276 mm }{$EXTERNALSYM DMPAPER_A2}DMPAPER_A2 = 66; { A2 420 x 594 mm }{$EXTERNALSYM DMPAPER_A3_TRANSVERSE}DMPAPER_A3_TRANSVERSE = 67; { A3 Transverse 297 x 420 mm }{$EXTERNALSYM DMPAPER_A3_EXTRA_TRANSVERSE}DMPAPER_A3_EXTRA_TRANSVERSE = 68; { A3 Extra Transverse 322 x 445 mm }{** the following sizes are reserved for the Far East version of Win95.** Rotated papers rotate the physical page but not the logical page.}{$EXTERNALSYM DMPAPER_DBL_JAPANESE_POSTCARD}DMPAPER_DBL_JAPANESE_POSTCARD = 69; { Japanese Double Postcard 200 x 148 mm } {$EXTERNALSYM DMPAPER_A6}DMPAPER_A6 = 70; { A6 105 x 148 mm }{$EXTERNALSYM DMPAPER_JENV_KAKU2 }DMPAPER_JENV_KAKU2 = 71; { Japanese Envelope Kaku #2 }{$EXTERNALSYM DMPAPER_JENV_KAKU3 }DMPAPER_JENV_KAKU3 = 72; { Japanese Envelope Kaku #3 }{$EXTERNALSYM DMPAPER_JENV_CHOU3 }DMPAPER_JENV_CHOU3 = 73; { Japanese Envelope Chou #3 }{$EXTERNALSYM DMPAPER_JENV_CHOU4 }DMPAPER_JENV_CHOU4 = 74; { Japanese Envelope Chou #4 }{$EXTERNALSYM DMPAPER_LETTER_ROTATED }DMPAPER_LETTER_ROTATED = 75; { Letter Rotated 11 x 8 1/2 11 in }{$EXTERNALSYM DMPAPER_A3_ROTATED }DMPAPER_A3_ROTATED = 76; { A3 Rotated 420 x 297 mm }{$EXTERNALSYM DMPAPER_A4_ROTATED }DMPAPER_A4_ROTATED = 77; { A4 Rotated 297 x 210 mm }{$EXTERNALSYM DMPAPER_A5_ROTATED }DMPAPER_A5_ROTATED = 78; { A5 Rotated 210 x 148 mm }{$EXTERNALSYM DMPAPER_B4_JIS_ROTATED }DMPAPER_B4_JIS_ROTATED = 79; { B4 (JIS) Rotated 364 x 257 mm }{$EXTERNALSYM DMPAPER_B5_JIS_ROTATED }DMPAPER_B5_JIS_ROTATED = 80; { B5 (JIS) Rotated 257 x 182 mm }{$EXTERNALSYM DMPAPER_JAPANESE_POSTCARD_ROTATED }DMPAPER_JAPANESE_POSTCARD_ROTATED = 81; { Japanese Postcard Rotated 148 x 100 mm } {$EXTERNALSYM DMPAPER_DBL_JAPANESE_POSTCARD_ROTATED }DMPAPER_DBL_JAPANESE_POSTCARD_ROTATED = 82; { Double Japanese Postcard Rotated 148 x 200 mm } {$EXTERNALSYM DMPAPER_A6_ROTATED }DMPAPER_A6_ROTATED = 83; { A6 Rotated 148 x 105 mm }{$EXTERNALSYM DMPAPER_JENV_KAKU2_ROTATED }DMPAPER_JENV_KAKU2_ROTATED = 84; { Japanese Envelope Kaku #2 Rotated} {$EXTERNALSYM DMPAPER_JENV_KAKU3_ROTATED }DMPAPER_JENV_KAKU3_ROTATED = 85; { Japanese Envelope Kaku #3 Rotated} {$EXTERNALSYM DMPAPER_JENV_CHOU3_ROTATED }DMPAPER_JENV_CHOU3_ROTATED = 86; { Japanese Envelope Chou #3 Rotated} {$EXTERNALSYM DMPAPER_JENV_CHOU4_ROTATED }DMPAPER_JENV_CHOU4_ROTATED = 87; { Japanese Envelope Chou #4 Rotated} {$EXTERNALSYM DMPAPER_B6_JIS }DMPAPER_B6_JIS = 88; { B6 (JIS) 128 x 182 mm }{$EXTERNALSYM DMPAPER_B6_JIS_ROTATED }DMPAPER_B6_JIS_ROTATED = 89; { B6 (JIS) Rotated 182 x 128 mm } {$EXTERNALSYM DMPAPER_12X11 }DMPAPER_12X11 = 90; { 12 x 11 in }{$EXTERNALSYM DMPAPER_JENV_YOU4 }DMPAPER_JENV_YOU4 = 91; { Japanese Envelope You #4 } {$EXTERNALSYM DMPAPER_JENV_YOU4_ROTATED }DMPAPER_JENV_YOU4_ROTATED = 92; { Japanese Envelope You #4 Rotated} {$EXTERNALSYM DMPAPER_P16K }DMPAPER_P16K = 93; { PRC 16K 146 x 215 mm }{$EXTERNALSYM DMPAPER_P32K }DMPAPER_P32K = 94; { PRC 32K 97 x 151 mm }{$EXTERNALSYM DMPAPER_P32KBIG }DMPAPER_P32KBIG = 95; { PRC 32K(Big) 97 x 151 mm } {$EXTERNALSYM DMPAPER_PENV_1 }DMPAPER_PENV_1 = 96; { PRC Envelope #1 102 x 165 mm } {$EXTERNALSYM DMPAPER_PENV_2 }DMPAPER_PENV_2 = 97; { PRC Envelope #2 102 x 176 mm } {$EXTERNALSYM DMPAPER_PENV_3 }DMPAPER_PENV_3 = 98; { PRC Envelope #3 125 x 176 mm } {$EXTERNALSYM DMPAPER_PENV_4 }DMPAPER_PENV_4 = 99; { PRC Envelope #4 110 x 208 mm } {$EXTERNALSYM DMPAPER_PENV_5 }DMPAPER_PENV_5 = 100; { PRC Envelope #5 110 x 220 mm } {$EXTERNALSYM DMPAPER_PENV_6 }DMPAPER_PENV_6 = 101; { PRC Envelope #6 120 x 230 mm } {$EXTERNALSYM DMPAPER_PENV_7 }DMPAPER_PENV_7 = 102; { PRC Envelope #7 160 x 230 mm } {$EXTERNALSYM DMPAPER_PENV_8 }DMPAPER_PENV_8 = 103; { PRC Envelope #8 120 x 309 mm } {$EXTERNALSYM DMPAPER_PENV_9 }DMPAPER_PENV_9 = 104; { PRC Envelope #9 229 x 324 mm } {$EXTERNALSYM DMPAPER_PENV_10 }DMPAPER_PENV_10 = 105; { PRC Envelope #10 324 x 458 mm } {$EXTERNALSYM DMPAPER_P16K_ROTATED }DMPAPER_P16K_ROTATED = 106; { PRC 16K Rotated } {$EXTERNALSYM DMPAPER_P32K_ROTATED }DMPAPER_P32K_ROTATED = 107; { PRC 32K Rotated } {$EXTERNALSYM DMPAPER_P32KBIG_ROTATED }DMPAPER_P32KBIG_ROTATED = 108; { PRC 32K(Big) Rotated } {$EXTERNALSYM DMPAPER_PENV_1_ROTATED }DMPAPER_PENV_1_ROTATED = 109; { PRC Envelope #1 Rotated 165 x 102 mm} {$EXTERNALSYM DMPAPER_PENV_2_ROTATED }DMPAPER_PENV_2_ROTATED = 110; { PRC Envelope #2 Rotated 176 x 102 mm} {$EXTERNALSYM DMPAPER_PENV_3_ROTATED }DMPAPER_PENV_3_ROTATED = 111; { PRC Envelope #3 Rotated 176 x 125 mm} {$EXTERNALSYM DMPAPER_PENV_4_ROTATED }DMPAPER_PENV_4_ROTATED = 112; { PRC Envelope #4 Rotated 208 x 110 mm} {$EXTERNALSYM DMPAPER_PENV_5_ROTATED }DMPAPER_PENV_5_ROTATED = 113; { PRC Envelope #5 Rotated 220 x 110 mm} {$EXTERNALSYM DMPAPER_PENV_6_ROTATED }DMPAPER_PENV_6_ROTATED = 114; { PRC Envelope #6 Rotated 230 x 120 mm} {$EXTERNALSYM DMPAPER_PENV_7_ROTATED }DMPAPER_PENV_7_ROTATED = 115; { PRC Envelope #7 Rotated 230 x 160 mm} {$EXTERNALSYM DMPAPER_PENV_8_ROTATED }DMPAPER_PENV_8_ROTATED = 116; { PRC Envelope #8 Rotated 309 x 120 mm} {$EXTERNALSYM DMPAPER_PENV_9_ROTATED }DMPAPER_PENV_9_ROTATED = 117; { PRC Envelope #9 Rotated 324 x 229 mm} {$EXTERNALSYM DMPAPER_PENV_10_ROTATED }DMPAPER_PENV_10_ROTATED = 118; { PRC Envelope #10 Rotated 458 x 324 mm } {$EXTERNALSYM DMPAPER_LAST}DMPAPER_LAST = DMPAPER_PENV_10_ROTATED;{$EXTERNALSYM DMPAPER_USER}DMPAPER_USER = $100;。
使用Delphi实现票据精确打印一、概述在银行,税务,邮政等行业的实际工作中,经常涉及到在印刷好具有固定格式的汇款单,储蓄凭证,税票等单据上的确定位置打印输出相关的信息。
在此类需求中,精确地定位单据并打印相关信息,是解决问题的关键。
一般情况下,开发者都是通过在打印机上通过重复的测试来达到实际需求。
那么,有没有简单有效而又灵活的方法实现上述功能呢?二、基本思路分析上述单据的特征,可以发现:此类打印输出的信息一般比较简短,不涉及到文字过长的折行处理,另外,其打印输出的位置相对固定。
因此,我们可以通过用尺子以毫米为单位,测量好每个输出信息位置的横向和纵向坐标,作为信息输出的位置。
但由于不同打印机在实际输出效果上,总是存在理论和实际位置的偏差,因此,要求程序具有一定的灵活性,供最终用户根据需要,进行必要的位置调整。
因此,可设置一打印配置文件,用于存储横坐标和纵坐标的偏移量,用于用户进行位置校正,从而提供了一定的灵活性。
三、精确打印输出的程序实现1.在Delphi中新建一个名为mprint.pas的单元文件并编写如下程序,单元引用中加入Printers 略://取得字符的高度function CharHeight: Word;varMetrics: TTextMetric;beginGetTextMetrics(Printer.Canvas.Handle, Metrics);Result := Metrics.tmHeight;end;file://取得字符的平均宽度function AvgCharWidth: Word;varMetrics: TTextMetric;beginGetTextMetrics(Printer.Canvas.Handle, Metrics);Result := Metrics.tmAveCharWidth;end;file://取得纸张的物理尺寸---单位:点function GetPhicalPaper: TPoint;varPageSize : TPoint;beginfile://PageSize.X; 纸张物理宽度-单位:点file://PageSize.Y; 纸张物理高度-单位:点Escape(Printer.Handle, GETPHYSPAGESIZE, 0,nil,@PageSize);Result := PageSize;end;file://2.取得纸张的逻辑宽度--可打印区域file://取得纸张的逻辑尺寸function PaperLogicSize: TPoint;varAPoint: TPoint;beginAPoint.X := Printer.PageWidth;APoint.Y := Printer.PageHeight;Result := APoint;end;file://纸张水平对垂直方向的纵横比例function HVLogincRatio: Extended;varAP: TPoint;beginAp := PaperLogicSize;Result := Ap.y/Ap.X;end;file://取得纸张的横向偏移量-单位:点function GetOffSetX: Integer;beginResult := GetDeviceCaps(Printer.Handle, PhysicalOffSetX); end;file://取得纸张的纵向偏移量-单位:点function GetOffSetY: Integer;beginResult := GetDeviceCaps(Printer.Handle, PhysicalOffSetY); end;file://毫米单位转换为英寸单位function MmToInch(Length: Extended): Extended;beginResult := Length/25.4;end;file://英寸单位转换为毫米单位function InchToMm(Length: Extended): Extended;beginResult := Length*25.4;end;file://取得水平方向每英寸打印机的点数function HPointsPerInch: Integer;beginResult := GetDeviceCaps(Printer.Handle, LOGPIXELSX); end;file://取得纵向方向每英寸打印机的光栅数function VPointsPerInch: Integer;beginResult := GetDeviceCaps(Printer.Handle, LOGPIXELSY) end;file://横向点单位转换为毫米单位function XPointToMm(Pos: Integer): Extended;beginResult := Pos*25.4/HPointsPerInch;end;file://纵向点单位转换为毫米单位function YPointToMm(Pos: Integer): Extended;beginResult := Pos*25.4/VPointsPerInch;end;file://设置纸张高度-单位:mmprocedure SetPaperHeight(Value:integer);varDevice : array[0..255] of char;Driver : array[0..255] of char;Port : array[0..255] of char;hDMode : THandle;PDMode : PDEVMODE;beginfile://自定义纸张最小高度127mmif Value < 127 then Value := 127;file://自定义纸张最大高度432mmif Value > 432 then Value := 432;Printer.PrinterIndex := Printer.PrinterIndex;Printer.GetPrinter(Device, Driver, Port, hDMode);if hDMode <> 0 thenbeginpDMode := GlobalLock(hDMode);if pDMode <> nil thenbeginpDMode^.dmFields := pDMode^.dmFields or DM_PAPERSIZE orDM_PAPERLENGTH;pDMode^.dmPaperSize := DMPAPER_USER;pDMode^.dmPaperLength := Value * 10;pDMode^.dmFields := pDMode^.dmFields or DMBIN_MANUAL;pDMode^.dmDefaultSource := DMBIN_MANUAL;GlobalUnlock(hDMode);end;end;Printer.PrinterIndex := Printer.PrinterIndex;end;file://设置纸张宽度:单位--mmProcedure SetPaperWidth(Value:integer);varDevice : array[0..255] of char;Driver : array[0..255] of char;Port : array[0..255] of char;hDMode : THandle;PDMode : PDEVMODE;beginfile://自定义纸张最小宽度76mmif Value < 76 then Value := 76;file://自定义纸张最大宽度216mmif Value > 216 then Value := 216;Printer.PrinterIndex := Printer.PrinterIndex;Printer.GetPrinter(Device, Driver, Port, hDMode);if hDMode <> 0 thenbeginpDMode := GlobalLock(hDMode);if pDMode <> nil thenbeginpDMode^.dmFields := pDMode^.dmFields or DM_PAPERSIZE orDM_PAPERWIDTH;pDMode^.dmPaperSize := DMPAPER_USER;file://将毫米单位转换为0.1mm单位pDMode^.dmPaperWidth := Value * 10;pDMode^.dmFields := pDMode^.dmFields or DMBIN_MANUAL;pDMode^.dmDefaultSource := DMBIN_MANUAL;GlobalUnlock(hDMode);end;end;Printer.PrinterIndex := Printer.PrinterIndex;end;file://在(Xmm, Ymm)处按指定配置文件信息和字体输出字符串procedure PrintText(X, Y: Extended; Txt: string; ConfigFileName: string; FontSize: Integer=12);varOrX, OrY: Extended;Px, Py: Integer;AP: TPoint;Fn: TStrings;FileName: string;OffSetX, OffSetY: Integer;beginfile://打开配置文件,读出横向和纵向偏移量tryFn := TStringList.Create;FileName := ExtractFilePath(Application.ExeName) + ConfigFileName;if FileExists(FileName) thenbeginFn.LoadFromFile(FileName);file://横向偏移量OffSetX := StrToInt(Fn.Values['X']);file://纵向偏移量OffSetY := StrToInt(Fn.Values['Y']);endelsebeginfile://如果没有配置文件,则生成Fn.Values['X'] := '0';Fn.Values['Y'] := '0';Fn.SaveToFile(FileName);end;finallyFn.Free;end;X := X + OffSetX;Y := Y + OffSetY;Px := Round(Round(X * HPointsPerInch * 10000/25.4) / 10000);Py := Round(Round(Y * VPointsPerInch * 10000/25.4) / 10000);Py := Py - GetOffSetY; file://因为是绝对坐标, 因此, 不用换算成相对于Y轴坐标Px := Px + 2 * AvgCharWidth; := '宋体';Printer.Canvas.Font.Size := FontSize;file://Printer.Canvas.Font.Color := clGreen;Printer.Canvas.TextOut(Px, Py, Txt);end;2.使用举例在主窗体中加入对mprint单元的引用,在一命令钮的OnClick事件中书写如下代码(用于在邮政汇款单上的相应方框内打印邮政编码843300):Printer.BeginDoc;PrintText(16, 14, '8', 'config.txt');PrintText(26, 14, '4', 'config.txt');PrintText(36, 14, '3', 'config.txt');PrintText(46, 14, '3', 'config.txt');PrintText(56, 14, '0', 'config.txt');PrintText(66, 14, '0', 'config.txt');Printer.EndDoc;观察结果,用尺子测量偏移量,在config.txt文件中修改X,Y的值即可。
在DELPHI中提供了一个PRINTERS程序单元,它说明了一个TPRINTER对象,封装了WINDOWS打印工作和输出打印机之间的接口,并提供常用的属性和方法,其中画布CANVAS是一个非常有用的属性,它代表了当前打印文件的表面,是以图形方式来工作的,整个的打印输出工作仅仅是将你打印的内容输出到TPRINTER的属性CANVAS上,当全部的输出工作完成以后,打印对象(TPRINTER)把CANVAS的属性值送到打印机上去。
下面举例来说明如何通过DELPHI实现文本内容的打印。
在DELPHI 中提供了PRINTDIALOG、PRINTERSETUPDIALOG两个控件允许我们进行打印机以及其他影响打印输出的选择,此外最重要的一点是要想实现打印功能必须在编译程序以前将PRINTERS加入到INTERFACE或者IMPLEMENTATION的UESE语句当中,因为PRINTER单元包括ASSIGNPRN和其他控制打印机的过程。
首先在FORM当中加入MEMO、PRINTDIALOG、PRINTERSETUPDIALOG和两个BUTTON控件,两个BUTTON的CAPTION分别为“打印设置”和“打印”。
然后编写BUTTON的事件驱动程序(代码在下面),这个简单的例子中只要单击“打印”按钮时便可以在打印机上输出文件0S2.TXT,打印事件的清单如下:
implementation
usesprinters;
{$R*.DFM}
procedureTForm1.BitBtn1Click(Sender:TObject);
begin
printersetupdialog1.execute;//选择输出的打印机以及其他打印控制选项
end;
procedureTForm1.BitBtn2Click(Sender:TObject);
var
lines:integer;
prntext:system.text;
//将PRNTEXT声名为一个在SYSTEM程序单元当中定义的文本文件begin
ifprintdialog1.executethen
assignprn(prntext);//将PRNTEST分配给打印机
rewrite(prntext);//调用REWRITE函数,为输出打开已分配的文件printer.canvas.font:=memo1.font;
//把当前MEMO1的字体指定给打印对象的CANVAS的字体属性forlines:=0tomemo1.lines.count-1do
writeln(prntext,memo1.lines[lines]);
//把MEMO的内容写到打印机对象
system.close(prntext);//关闭打印文件
end;
procedureTForm1.FormCreate(Sender:TObject);
begin
memo1.lines.loadfromfile('c:\dos\os2.txt');
//在FORM建立时读入C:\DOS\OS2.TXT文件
end;
end.
2、图形的打印功能,简单的图形打印功能也如打印文本一样的容易,只是告诉打印机对象(TPRINTER)开始打印,把图形简单的复制到打印机上去,最后告诉打印机结束打印工作。
举例说明:将上面的例子的MEMO控件换成IMAGE控件,再经过一些简单的修改,图形打印的代码如下:
procedureTForm1.BitBtn1Click(Sender:TObject);
begin
ifprintdialog1.executethen
begin
printer.begindoc;
printer.canvas.draw(0,0,image1.picture.graphic);
printer.enddoc;
end;
end;
在这种情况下,使用的是打印机的分辨率,图形在页面的左上角开始打印输出,打出的图形很小,在很多的情况下不能符合要求,但是打印机画布CANVAS的STRETHDRAW的方法,可以让我们对图形进行灵活的处理,画布(CANVAS)的STRETCHDRAW方法声名为:
procedureStretchDraw(constRect:TRect;Graphic:TGraphic);
其中的RECT参数代表图形输出区域的大小,TRECT的类型声名为:TRect=record
caseIntegerof
0:(Left,Top,Right,Bottom:Integer);
1:(TopLeft,BottomRight:TPoint);
end;
因此我们只要调整RECT的大小及其在打印页面上的位置,进而达到自己满意的效果,下面的代码是不断的放大图形,充满我们定义的矩
形区域,并将其定位在打印机画布(CANVAS)的中央进行输出。
代码如下:
procedureTForm1.Button1Click(Sender:TObject);
VAR
strect:Trect;//定义打印输出矩形框的大小
temhi,temwd:integer;
begin
ifprintdialog1.executethen
begin
temhi:=image1.picture.height;
temwd:=image1.picture.width;
while(temhiprinter.pageheightdiv2)and
//将图形放大到打印页面的1/2大小
(temwdprinter.pagewidthdiv2)do
begin
temhi:=temhi+temhi;
temwd:=temwd+temwd;
end;
withstrectdo//定义图形在页面上的中心位置输出
begin
left:=(printer.pagewidth-temwd)div2;
top:=(printer.pageheight-temhi)div2;
right:=left+temwd;
bottom:=top+temhi;
end;
withprinterdo
begin
begindoc;
//将放大的图形向打印机输出
canvas.stretchdraw(strect,image1.picture.graphic);
enddoc;
end;
end;
end;
以上代码在DELPHI2.0上编译通过,通过这些小小的例子,相信大家对于在DELPHI中打印图形和文本有一定的了解,同样通过打印机的画布(CANVAS)属性也可以实现数据库表单的打印,在这里不一一赘述,如果大家有兴趣不妨一试。