打印panel中的内容(包括image、memo),一页中含有多幅图片时,有时打印出来最后一幅图片会空白。我的打印部分代码如下,十万火急,请大侠指导。SetPrinter(nil);
printer.CleanupInstance;
printer.Title:=trim(form1.Caption);
printer.BeginDoc;
SetMapMode(printer.Canvas.Handle,MM_ANISOTROPIC);
SetWindowExtEx(printer.Canvas.Handle,PanelRep.Width,PanelRep.Height,nil); //PanelRep是一个panel,里面包括数个image、memo
SetViewportExtEx(printer.Canvas.Handle,printer.PageWidth,printer.PageHeight,nil);
panelRep.PaintTo(printer.Canvas,0,0);
printer.EndDoc;在win2000、xp下均出现过图片漏打,打印机包括HP 1600、2600彩激。新注册,积分少,但我会非常感谢的。
printer.CleanupInstance;
printer.Title:=trim(form1.Caption);
printer.BeginDoc;
SetMapMode(printer.Canvas.Handle,MM_ANISOTROPIC);
SetWindowExtEx(printer.Canvas.Handle,PanelRep.Width,PanelRep.Height,nil); //PanelRep是一个panel,里面包括数个image、memo
SetViewportExtEx(printer.Canvas.Handle,printer.PageWidth,printer.PageHeight,nil);
panelRep.PaintTo(printer.Canvas,0,0);
printer.EndDoc;在win2000、xp下均出现过图片漏打,打印机包括HP 1600、2600彩激。新注册,积分少,但我会非常感谢的。
bit: TBitmap;
begin
SetPrinter(nil);
printer.CleanupInstance;
printer.Title := trim(form1.Caption);
printer.BeginDoc;
SetMapMode(printer.Canvas.Handle, MM_ANISOTROPIC);
SetWindowExtEx(printer.Canvas.Handle, PanelRep.Width, PanelRep.Height, nil); //PanelRep是一个panel,里面包括数个image、memo
SetViewportExtEx(printer.Canvas.Handle, printer.PageWidth, printer.PageHeight, nil);
///***
bit := TBitmap.Create;
try
bit.PixelFormat := pf24bit;
bit.Transparent := True;
bit.Width := PanelRep.Width;
bit.Height := PanelRep.Height;
panelRep.PaintTo(bit.Canvas, 0, 0);
Printer.Canvas.Draw(0, 0, bit);
finally
bit.Free;
end;
///***
printer.EndDoc;
end;
试试吧
在Printer.Canvas.Draw(0, 0, bit);插入一个定时器,定时1秒,然后EndDoc。打印成功。
看来Printer.Canvas.Draw的优先级比较低,或则没有结束绘图就返回句柄,才打出空白页。
但是blazingfire的方法打印出来的分辨率太低了。
我还是仍旧用原来的方法打印,panelRep.PaintTo(printer.Canvas,0,0)和printer.EndDoc之间插入一个定时器试试看,如果问题解决,会回来报告的。
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, Printers, StdCtrls, DBCtrls, Mask, ComCtrls, Grids, DBGrids,
Chart;type
TPPanel = class(TPanel)
private
{ Private declarations }
SX,SY:Real;
FShowBorder:Boolean; FXOffset:Integer;
FYOffset:Integer; PreviewForm:TForm;
protected
{ Protected declarations }
public
{ Public declarations }
Constructor Create(AOwner:TComponent); Override;
Procedure PrintToCanvas(ACanvas:TCanvas); Procedure WhenKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
Procedure WhenFormPaint(Sender: TObject);
Procedure WhenFormClose(Sender: TObject; var Action: TCloseAction);
published
{ Published declarations }
Function Print(Preview:Boolean):Boolean;
Procedure About; Property ShowBorder:Boolean Read FShowBorder Write FShowBorder;
Property XOffset:Integer Read FXOffset Write FXOffset;
Property YOffset:Integer Read FYOffset Write FYOffset;
end;procedure Register;implementation//注册组件
procedure Register;
begin
RegisterComponents('Standard', [TPPanel]);
end;Constructor TPPanel.Create(AOwner:TComponent);
Begin
Inherited; FXOffset:=0;
FYOffset:=0;
End;//关于组件
Procedure TPPanel.About;
Begin
Application.MessageBox('PPanel 作者:彭富章 2000.03','关于 PPanel',MB_OK+MB_ICONINFORMATION);
End;//打印预览窗口键盘按下
Procedure TPPanel.WhenKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
Begin
If Key=VK_Return Then
Begin
Self.Print(False);
If Sender Is TForm Then
TForm(Sender).ModalResult:=mrOK;
End
Else If Key=VK_ESCAPE Then
PreViewForm.Close;
End;//窗口刷新
Procedure TPPanel.WhenFormPaint(Sender: TObject);
Begin
PrintToCanvas(PreviewForm.Canvas);
End;//窗口关闭
Procedure TPPanel.WhenFormClose(Sender: TObject; var Action: TCloseAction);
Begin
Action:=caFree;
End;//打印
Function TPPanel.Print(Preview:Boolean):Boolean;
Var SS:TStringList;
Begin
If FileExists(ExtractFilePath(Application.ExeName)+'PRINT.INI') Then
Begin
SS:=TStringList.Create;
SS.LoadFromFile(ExtractFilePath(Application.ExeName)+'PRINT.INI'); Try
If SS.Count>0 Then FXOffset:=StrToInt(SS.Strings[0]);
If SS.Count>1 Then FYOffset:=StrToInt(SS.Strings[1]);
Except
End; SS.Clear;
SS.Free;
End; Result:=False;
If Preview Then
Begin
SX:=1.0;
SY:=1.0; PreViewForm:=TForm.Create(Application);
PreViewForm.Caption:='打印预览 按[Enter]打印 按[Esc] 关闭';
PreViewForm.BorderStyle:=bsDialog;
PreViewForm.ClientWidth:=self.Width;
PreViewForm.ClientHeight:=self.Height;
PreViewForm.Color:=clWhite;
PreviewForm.Position:=poScreenCenter; PreviewForm.OnKeyDown:=WhenKeyDown;
PreviewForm.OnPaint:=WhenFormPaint;
PreviewForm.OnClose:=WhenFormClose; If PreViewForm.ShowModal=mrOK Then
Result:=True;
End
Else
Begin
SX:=GetDeviceCaps(Printer.Handle,logPixelsX)/Screen.PixelsPerInch;
SY:=GetDeviceCaps(Printer.Handle,logPixelsY)/Screen.PixelsPerInch; Printer.BeginDoc;
Printer.Title:='Doc printed by PrintPanel '+FormatDateTime('YYYY-MM-DD HH:MM:SS',Now);
PrintToCanvas(Printer.Canvas);
Printer.EndDoc; Result:=True;
End;
End;
Procedure TPPanel.PrintToCanvas(ACanvas:TCanvas);
Var NowPage:Integer;
I,N:Integer;
AObj:TControl;
ARect:TRect;
PX,PY:Integer;
Stemp:String; WidthArray:Array[1..24] of Integer;
ValueArray:Array[1..24] Of String;
ColumnCount,X,Y,NowX,NowY:Integer; NowRow:Integer;
Begin
NowPage:=1; Try
ACanvas.Lock; With ACanvas Do
For I:=0 To ControlCount-1 Do
If Controls[I].Visible Then
Begin
AObj:=Controls[I];
ARect:=AObj.BoundsRect; ARect.Left:=ARect.Left+FXOffset;
ARect.Top:=ARect.Top+FYOffset;
ARect.Right:=ARect.Right+FXOffset;
ARect.Bottom:=ARect.Bottom+FYOffset; PX:=Round((ARect.Left+4)*SX);
PY:=Round((ARect.Top+2)*SY); ARect.Left:=Round(ARect.Left*SX);
ARect.Top:=Round(ARect.Top*SY);
ARect.Right:=Round(ARect.Right*SX);
ARect.Bottom:=Round(ARect.Bottom*SY); Font:=self.Font; If (FShowBorder ) Then //OR (AObj Is TStringGrid)
If ((AObj Is TEdit) OR (AObj Is TDBEdit) OR (AObj Is TMaskEdit) OR (AObj Is TDateTimePicker) OR (AObj Is TComboBox)
OR (AObj Is TDbComboBox) OR (AObj Is TMemo) OR (AObj Is TDBmemo) OR (AObj Is TDBGrid) OR (AObj Is TStringGrid)) Then
Begin
Pen.Width:=1;
MoveTo(ARect.Left,ARect.Top);
LineTo(ARect.Right,ARect.Top);
LineTo(ARect.Right,ARect.Bottom);
LineTo(ARect.Left,ARect.Bottom);
LineTo(ARect.Left,ARect.Top);
End; If AObj Is TLabel Then
Begin
Stemp:=Uppercase(TLabel(AObj).Caption);
Font:=TLabel(AObj).Font; If Stemp='%UP%' Then
Begin
If NowPage>1 Then
TextOut(ARect.Left,ARect.Top,'接上页');
End
Else If Stemp='%DOWN%' Then
TextOut(ARect.Left,ARect.Top,'接下页')
Else If Stemp='%PAGE%' Then
TextOut(ARect.Left,ARect.Top,'第 '+IntToStr(NowPage)+' 页')
Else If Stemp='%DATE%' Then
TextOut(ARect.Left,ARect.Top,FormatDateTime('YYYY-MM-DD',Now))
Else If Stemp='%TIME%' Then
TextOut(ARect.Left,ARect.Top,FormatDateTime('HH:MM:SS',Now))
Else If Stemp='%YYYY%' Then
TextOut(ARect.Left,ARect.Top,FormatDateTime('YYYY',Date))
Else If Stemp='%MM%' Then
TextOut(ARect.Left,ARect.Top,FormatDateTime('MM',Date))
Else If Stemp='%DD%' Then
TextOut(ARect.Left,ARect.Top,FormatDateTime('DD',Date))
Else
TextOut(ARect.Left,ARect.Top,TLabel(AObj).Caption);
End
Else If AObj Is TDBText Then
Begin
Try
If Not TDBText(AObj).DataSource.DataSet.Active Then Continue; Font:=TDBText(AObj).Font;
TextOut(ARect.Left,ARect.Top,TDBText(AObj).Field.DisplayText);
Except
End;
End
Else If AObj Is TEdit Then
Begin
Font:=TEdit(AObj).Font;
TextOut(PX,PY,TEdit(AObj).Text);
End
Else If AObj Is TDBEdit Then
Begin
Try
If Not TDBEdit(AObj).DataSource.DataSet.Active Then Continue; Font:=TDBEdit(AObj).Font;
TextOut(PX,PY,TDBEdit(AObj).Field.DisplayText);
Except
End;
End
Else If AObj Is TMaskEdit Then
Begin
Font:=TMaskEdit(AObj).Font;
TextOut(PX,PY,TMaskEdit(AObj).Text);
End
Else If AObj Is TDateTimePicker Then
Begin
Stemp:='';
Font:=TDateTimePicker(AObj).Font;
If TDateTimePicker(AObj).ShowCheckBox Then
Begin
If TDateTimePicker(AObj).Checked Then
Stemp:='■'
Else
Stemp:='□';
End; If TDateTimePicker(AObj).Kind=dtkDate Then
Stemp:=Stemp+FormatDateTime('YYYY-MM-DD',TDateTimePicker(AObj).Date)
Else
Stemp:=Stemp+FormatDateTime('HH:MM:SS',TDateTimePicker(AObj).Time); TextOut(PX,PY,Stemp);
End
Else If AObj Is TBevel Then
Begin
If TBevel(AObj).Shape=bsBottomLine Then
Begin
MoveTo(ARect.Left,ARect.Bottom);
LineTo(ARect.Right,ARect.Bottom);
End
Else If TBevel(Aobj).Shape=bsTopLine Then
Begin
MoveTo(ARect.Left,ARect.Top);
LineTo(ARect.Right,ARect.Top);
End
Else If TBevel(AObj).Shape=bsLeftLine Then
Begin
MoveTo(ARect.Left,ARect.Top);
LineTo(ARect.Left,ARect.Bottom);
End
Else If TBevel(AObj).Shape=bsRightLine Then
Begin
MoveTo(ARect.Right,ARect.Top);
LineTo(ARect.Right,ARect.Bottom);
End
Else If TBevel(AObj).Shape=bsBox Then
Begin
MoveTo(ARect.Left,ARect.Top);
LineTo(ARect.Right,ARect.Bottom);
End
Else
Begin
MoveTo(ARect.Left,ARect.Top);
LineTo(ARect.Right,ARect.Top);
LineTo(ARect.Right,ARect.Bottom);
LineTo(ARect.Left,ARect.Bottom);
LineTo(ARect.Left,ARect.Top);
End;
End
Else If AObj Is TComboBox Then
Begin
Font:=TComboBox(AObj).Font;
TextOut(PX,PY,TComboBox(AObj).Text);
End
Else If AObj Is TDBComboBox Then
Begin
If Not TDBComboBox(AObj).DataSource.DataSet.Active Then Continue; Font:=TDBComboBox(AObj).Font;
TextOut(PX,PY,TDBComboBox(AObj).Field.AsString);
End
Else If AObj Is TCheckBox Then
Begin
Font:=TCheckBox(AObj).Font;
If TCheckBox(AObj).Checked Then
TextOut(PX,PY,'■'+TCheckBox(AObj).Caption)
Else
TextOut(PX,PY,'□'+TCheckBox(AObj).Caption);
End
Begin
If Not TDBCheckBox(AObj).DataSource.DataSet.Active Then Continue; Font:=TDBCheckBox(AObj).Font;
If TDBCheckBox(AObj).Checked Then
TextOut(PX,PY,'■'+TDBCheckBox(AObj).Caption)
Else
TextOut(PX,PY,'□'+TDBCheckBox(AObj).Caption);
End
Else If AObj Is TRadioButton Then
Begin
Font:=TRadioButton(AObj).Font;
If TRadioButton(AObj).Checked Then
TextOut(PX,PY,'●'+TRadioButton(AObj).Caption)
Else
TextOut(PX,PY,'◎'+TRadioButton(AObj).Caption);
End
Else If AObj Is TChart Then
Begin
TChart(AObj).DrawToMetaCanvas(Canvas,ARect);
End
{Else If AObj Is TDBChart Then
Begin
TDBChart(AObj).DrawToMetaCanvas(Canvas,ARect);
End}
Else If AObj Is TImage Then
Begin
StretchDraw(ARect,TImage(AObj).Picture.Graphic);
End
Else If AObj Is TDBImage Then
Begin
StretchDraw(ARect,TDBImage(AObj).Picture.Graphic);
End
Else If AObj Is TDBGrid Then
Begin
Font:=TDBGrid(AObj).Font; ColumnCount:=TDBGrid(AObj).Columns.Count;
If ColumnCount>24 Then ColumnCount:=24; NowX:=ARect.Left;
For X:=0 To ColumnCount-1 Do
Begin
WidthArray[X+1]:=Round(TDBGrid(AObj).Columns[X].Width*SX);
ValueArray[X+1]:='';
NowX:=NowX+WidthArray[X+1];
If NowX>ARect.Right Then
Begin
ColumnCount:=X;
Break;
End;
End; //draw DBGrid Title
NowX:=ARect.Left;
NowY:=ARect.Top;
For X:=0 To ColumnCount-1 Do
Begin
TextOut(NowX+4,NowY+2,TDBGrid(AObj).Columns[X].Field.DisplayLabel);
NowX:=NowX+WidthArray[X+1];
End; NowY:=NowY+Round((ABS(TDBGrid(AObj).Font.Height)+4)*SY);
//NowY:=NowY+TDBGrid(AObj).DefaultRowHeight*SY;
Pen.Width:=2;
MoveTo(ARect.Left,NowY);
LineTo(ARect.Right,NowY);
Pen.Width:=1; //draw records
TDBGrid(AObj).DataSource.DataSet.First;
While Not TDBGrid(AObj).DataSource.DataSet.Eof Do
Begin
//draw a record
NowX:=ARect.Left;
For X:=0 To ColumnCount-1 Do
Begin
If TDBGrid(AObj).Columns[X].Field.AsString<>ValueArray[X+1] Then
Begin
ValueArray[X+1]:=TDBGrid(AObj).Columns[X].Field.AsString;
TextOut(NowX+8,NowY+2,TDBGrid(AObj).Columns[X].Field.AsString);
End
Else
TextOut(NowX+8,NowY+2,TDBGrid(AObj).Columns[X].Field.AsString); NowX:=NowX+WidthArray[X+1];
End; TDBGrid(AObj).DataSource.DataSet.Next;
NowY:=NowY+Round((ABS(TDBGrid(AObj).Font.Height)+4)*SY);
If (NowY+Round((ABS(TDBGrid(AObj).Font.Height)+4)*SY))>ARect.Bottom Then
Break; MoveTo(ARect.Left,NowY);
LineTo(ARect.Right,NowY);
NowY:=NowY+Round(4*SY);
End; //draw lines
Pen.Width:=2;
NowX:=ARect.Left;
For X:=1 To ColumnCount-1 Do
Begin
NowX:=NowX+WidthArray[X];
MoveTo(NowX,ARect.Top);
LineTo(NowX,ARect.Bottom);
End;
Pen.Width:=1;
End
Else If AObj Is TStringGrid Then
Begin
Font:=TStringGrid(AObj).Font;
Pen.Width:=0; ColumnCount:=TStringGrid(AObj).ColCount;
If ColumnCount>24 Then ColumnCount:=24; NowX:=ARect.Left;
NowY:=ARect.Top;
For X:=0 To ColumnCount-1 Do
Begin
WidthArray[X+1]:=Round(TStringGrid(AObj).ColWidths[X]*SX);
NowX:=NowX+WidthArray[X+1];
If NowX>ARect.Right Then
Begin
ColumnCount:=X;
Break;
End;
End; //draw
NowRow:=0;
While NowRow<TStringGrid(AObj).RowCount Do
Begin
//draw a record
NowX:=ARect.Left;
For X:=0 To ColumnCount-1 Do
Begin
TextOut(NowX+8,NowY+Round(2*SY),TStringGrid(AObj).Cells[X,NowRow]);
NowX:=NowX+WidthArray[X+1];
End; Inc(NowRow);
//NowY:=NowY+Round((ABS(TStringGrid(AObj).Font.Height)+4)*SY);
NowY:=NowY+Round(TStringGrid(AObj).DefaultRowHeight*SY);
If (NowY+Round((ABS(TStringGrid(AObj).Font.Height)+4)*SY))>ARect.Bottom Then
Break; //MoveTo(ARect.Left,NowY);
//LineTo(ARect.Right,NowY);
NowY:=NowY+Round(4*SY);
End; //draw lines
{Pen.Width:=2;
NowX:=ARect.Left;
For X:=1 To ColumnCount-1 Do
Begin
NowX:=NowX+WidthArray[X];
MoveTo(NowX,ARect.Top);
LineTo(NowX,ARect.Bottom);
End;
Pen.Width:=1;}
End;
End;
Finally
ACanvas.Unlock;
End;
End;end.
要打印的东西放在上面 调用 .Print 方法就可以打印了