Tprinter打印任何表格控件

unit MyLib;

interface

uses
  classes, Printers, DBGrids, Graphics, Sysutils, Windows, Forms, DB, Grids,
  Dialogs, ComObj, Controls,StdCtrls,ShellAPI;

type//打印Tdbgrid
  TPrnOut = class(TObject)
    procedure PrintHeader(s:string);
    procedure PrintFoot(s:string);
    procedure PrintLine(x1,y1,x2,y2:integer);
    procedure PrintRow(Items:TStringList;rowDBGrid:TDBGrid);
    procedure PrintColumns(colDBGrid:TDBGrid);
    procedure PrintRecords(recDBGrid:TDBGrid);
    procedure PrintPart(MDBG,PDBG:TDBGrid);
    procedure SingleDBGPrint(DBgrid:TDBGrid;Header,Footer:string);
    procedure DoubleDBGPrint(MainDBG,PartDBG:TDBGrid;Header,Footer:string);
  private
    { Private declarations }
    strHead,strFoot:string;
    iPage:integer;
    iWordWidth,iWordHeight:integer;  //单位字宽与字高
    iAmount:integer;
    iPageHeight,iPageWidth:integer;  //有效打印区域高度与宽度
    PixelsInInchX:integer;
    {Number of pixels in 1/10 of an inch.This is used for lin spacing}
    TenthsOfInchPixelsY: Integer;
  end;

type//打印TstringGrid
  TStrGridPrn = class(TObject)
    procedure PrintHeader(s:string);
    procedure PrintFoot(s:string);
    procedure PrintLine(x1,y1,x2,y2:integer);
    procedure PrintRow(Items:TStringList;StrGrid:TStringGrid);
    procedure PrintColumns(StrGrid:TStringGrid);
    procedure PrintRecords(StrGrid:TStringGrid);
    procedure StrGridPrint(StrGrid:TStringGrid;Header,Footer:string);
  private
    { Private declarations }
    strHead,strFoot:string;
    iPage:integer;
    iWordWidth,iWordHeight:integer;  //单位字宽与字高
    iAmount:integer;
    iPageHeight,iPageWidth:integer;  //有效打印区域高度与宽度
    PixelsInInchX:integer;
    {Number of pixels in 1/10 of an inch.This is used for lin spacing}
    TenthsOfInchPixelsY: Integer;
  end;

implementation

{TPrnOut}

procedure TPrnOut.PrintHeader(s:string);
begin
  {页头打印}
  if s='' then s :='<无标题>';
  With Printer do
  begin
    with Canvas.Font do
    begin
      Size :=12;
      Name:='宋体';
    end;
    if (not Aborted) then
      Canvas.TextOut((PageWidth div 2)-(Canvas.TextWidth(s) div 2),0,s);
    iAmount :=iAmount+Canvas.TextHeight(s)*2;
  end;
end;

procedure TPrnOut.PrintFoot(s:string);
var
  str:string;
begin
  {页脚打印}
  if s='' then str:=s+'第'+IntToStr(iPage)+'页'
  else str:= s +'  '+'第'+IntToStr(iPage)+'页';

  With Printer do
    if (not Aborted) then
      Canvas.TextOut((PageWidth div 2)-(Canvas.TextWidth(str) div 2),
      (iPageHeight-iWordHeight),str);
  iAmount :=0;
  iPage :=iPage+1;
end;

procedure TPrnOut.PrintLine(x1,y1,x2,y2:integer);
begin
  with Printer.Canvas do
  begin
    MoveTo(x1,y1);
    LineTo(x2,y2);
  end;
end;

procedure TPrnOut.PrintRow(Items:TStringList;rowDBGrid:TDBGrid);
var
  OutRect:TRect;
  i:integer;
  Inches:Double;
begin
  OutRect.Left :=50;
  OutRect.Top :=iAmount;
  With Printer.Canvas do
  begin
    for i := 0 to Items.Count -1 do
    begin
      Inches :=LongInt(Items.Objects[i])*0.1;
      OutRect.Right :=OutRect.Left + Round(PixelsInInchx * Inches);

      if OutRect.Right>iPageWidth then
      begin
        {换行打印}
        OutRect.Left :=70;
        OutRect.Right :=70+OutRect.Left + Round(PixelsInInchx * Inches);
        iAmount := iAmount + iWordHeight;
        OutRect.Top := iAmount;
      end;

      {换页}
      if (iAmount+iWordHeight)>(iPageHeight-iWordHeight) then
      begin
        PrintFoot('');   //打印页脚
        iAmount :=0;
        if not Printer.Aborted then
          Printer.NewPage;
        PrintHeader('');
        PrintColumns(rowDBGrid);  //打印列头
        OutRect.Left :=70;
        OutRect.Right :=70+OutRect.Left + Round(PixelsInInchx * Inches);
        iAmount := iAmount + iWordHeight;
        OutRect.Top := iAmount;
      end;

      if not printer.Aborted then
        TextRect(OutRect,OutRect.Left,OutRect.Top,Items[i]);
      OutRect.Left :=OutRect.Right;
    end;
  end;
  iAmount :=iAmount + iWordHeight+2;
end;

procedure TPrnOut.PrintColumns(colDBGrid:TDBGrid);
var
  lst:TStringList;
  i:integer;
begin
  {打印列标题}
  lst :=TStringList.Create;
  try
    {获取打印机字的大小}
    with printer.Canvas do
    begin
      Font.Style :=[fsBold,fsUnderline];
      iWordWidth :=TextWidth('x');
      iWordHeight :=TextHeight('x');
    end;
    for i:=0 to colDBGrid.Columns.Count-1 do
      lst.AddObject(colDBGrid.Columns[i].Title.Caption,
      Pointer((colDBGrid.Columns[i].Width div 10)+2));

    PrintRow(lst,colDBGrid);
    Printer.Canvas.Font.Style :=[];
  Except
    lst.Free;
    printer.EndDoc;
  end;
end;

procedure TPrnOut.PrintRecords(recDBGrid:TDBGrid);
var
  lst:TStringList;
  i:integer;
begin
  {打印记录}
  lst :=TStringList.Create;
  try
    with recDBGrid.DataSource.DataSet do
    begin
      First;
      While (not Eof) or Printer.Aborted do
      begin
        Application.ProcessMessages;
        for i:=0 to recDBGrid.Columns.Count-1 do
          lst.AddObject(recDBGrid.Columns[i].Field.DisplayText,
          Pointer((recDBGrid.Columns[i].Width div 10)+2));
        PrintRow(lst,recDBGrid);  //行打印
        lst.Clear;
        Next;
      end;
    end;
  finally
    lst.Free;
  end;
end;

procedure TPrnOut.PrintPart(MDBG,PDBG:TDBGrid);
var
  lst:TStringList;
  i:integer;
begin
  lst :=TStringList.Create;
  try
    with MDBG.DataSource.DataSet do
    begin
      First;
      While (not Eof) do
      begin
        Application.ProcessMessages;
        for i:=0 to FieldDefs.Count-1 do
          lst.AddObject(MDBG.Columns[i].Field.DisplayText,
          Pointer((MDBG.Columns[i].Width div 10)+2));
        PrintRow(lst,MDBG);  //行打印
        lst.Clear;
        PrintColumns(PDBG);
        PrintRecords(PDBG);
        Next;
      end;
    end;
  finally
    lst.Free;
  end;
end;

procedure TPrnOut.SingleDBGPrint(DBGrid:TDBGrid;
  Header,Footer:string);
begin
  screen.Cursor :=crHourglass;
  strHead :=Header;
  strFoot :=Footer;
  iPage :=1;
  {单表打印}
  try
    with Printer do
    begin
      PixelsInInchX :=GetDeviceCaps(Handle,LOGPIXELSX);
      TenthsOfInchPixelsY :=GetDeviceCaps(Printer.Handle,LOGPIXELSY) div 10;
      iPageHeight :=PageHeight;
      iPageWidth :=PageWidth;    //减去左右边距
      Canvas.Font.Size :=11;
      BeginDoc;
    end;
    {打印页头}
    PrintHeader(Header);
    {打印标题栏:粗体,下划线}
    PrintColumns(DBGrid);
    {循环打印记录}
    PrintRecords(DBGrid);
    {打印页脚:页码}
    PrintFoot(Footer);
  finally
    printer.EndDoc;
    screen.Cursor :=crDefault;
  end;
end;

procedure TPrnOut.DoubleDBGPrint(MainDBG,PartDBG:TDBGrid;
  Header,Footer:string);
begin
  screen.Cursor :=crHourglass;
  iPage :=1;
  {明细表打印}
  try
    with Printer do
    begin
      PixelsInInchX :=GetDeviceCaps(Handle,LOGPIXELSX);
      TenthsOfInchPixelsY :=GetDeviceCaps(Printer.Handle,LOGPIXELSY) div 10;
      iPageHeight :=PageHeight;
      iPageWidth :=PageWidth;    //减去左右边距
      Canvas.Font.Size :=11;
      BeginDoc;
    end;
    {打印页头}
    PrintHeader(Header);
    {打印标题栏:粗体,下划线}
    PrintColumns(MainDBG);
    {循环打印记录}
    PrintPart(MainDBG,PartDBG);
    {打印页脚:页码}
    PrintFoot(Footer);
    {新页起始:重复上面工作}
  finally
    printer.EndDoc;
    screen.Cursor :=crDefault;
  end;
end;

{TStrGridPrn}

procedure TStrGridPrn.PrintHeader(s:string);
begin
  {页头打印}
  if s='' then s :='<无标题>';
  With Printer do
  begin
    with Canvas.Font do
    begin
      Size :=12;
      Name:='宋体';
    end;
    if (not Aborted) then
      Canvas.TextOut((PageWidth div 2)-(Canvas.TextWidth(s) div 2),0,s);
    iAmount :=iAmount+Canvas.TextHeight(s)*2;
  end;
end;

procedure TStrGridPrn.PrintFoot(s:string);
var
  str:string;
begin
  {页脚打印}
  if s='' then str:=s+'第'+IntToStr(iPage)+'页'
  else str:= s +'  '+'第'+IntToStr(iPage)+'页';

  With Printer do
    if (not Aborted) then
      Canvas.TextOut((PageWidth div 2)-(Canvas.TextWidth(str) div 2),
      (iPageHeight-iWordHeight),str);
  iAmount :=0;
  iPage :=iPage+1;
end;

procedure TStrGridPrn.PrintLine(x1,y1,x2,y2:integer);
begin
  with Printer.Canvas do
  begin
    MoveTo(x1,y1);
    LineTo(x2,y2);
  end;
end;

procedure TStrGridPrn.PrintRow(Items:TStringList;StrGrid:TStringGrid);
var
  OutRect:TRect;
  i:integer;
  Inches:Double;
begin
  OutRect.Left :=50;
  OutRect.Top :=iAmount;
  With Printer.Canvas do
  begin
    for i := 0 to Items.Count -1 do
    begin
      Inches :=LongInt(Items.Objects[i])*0.1;
      OutRect.Right :=OutRect.Left + Round(PixelsInInchx * Inches);

      if OutRect.Right>iPageWidth then
      begin
        {换行打印}
        OutRect.Left :=70;
        OutRect.Right :=70+OutRect.Left + Round(PixelsInInchx * Inches);
        iAmount := iAmount + iWordHeight;
        OutRect.Top := iAmount;
      end;

      {换页}
      if (iAmount+iWordHeight)>(iPageHeight-iWordHeight) then
      begin
        PrintFoot('');   //打印页脚
        iAmount :=0;
        if not Printer.Aborted then
          Printer.NewPage;
        PrintHeader('');
        PrintColumns(StrGrid);  //打印列头
        OutRect.Left :=70;
        OutRect.Right :=70+OutRect.Left + Round(PixelsInInchx * Inches);
        iAmount := iAmount + iWordHeight;
        OutRect.Top := iAmount;
      end;

      if not printer.Aborted then
        TextRect(OutRect,OutRect.Left,OutRect.Top,Items[i]);
      OutRect.Left :=OutRect.Right;
    end;
  end;
  iAmount :=iAmount + iWordHeight+2;
end;

procedure TStrGridPrn.PrintColumns(StrGrid:TStringGrid);
var
  lst:TStringList;
  i:integer;
begin
  {打印列标题}
  lst :=TStringList.Create;
  try
    {获取打印机字的大小}
    with printer.Canvas do
    begin
      Font.Style :=[fsBold,fsUnderline];
      iWordWidth :=TextWidth('x');
      iWordHeight :=TextHeight('x');
    end;
    for i:=0 to StrGrid.ColCount-1 do
      lst.AddObject(StrGrid.Cells[i,0],
      Pointer((StrGrid.ColWidths[i] div 10)+2));

    PrintRow(lst,StrGrid);
    Printer.Canvas.Font.Style :=[];
  Except
    lst.Free;
    printer.EndDoc;
  end;
end;

procedure TStrGridPrn.PrintRecords(StrGrid:TStringGrid);
var
  lst:TStringList;
  i,iRow:integer;
begin
  {打印记录}
  lst :=TStringList.Create;
  try
    for iRow :=1 to StrGrid.RowCount-1 do
    begin
      Application.ProcessMessages;
      for i:=0 to StrGrid.ColCount-1 do
        lst.AddObject(StrGrid.Cells[i,iRow],
        Pointer((StrGrid.ColWidths[i] div 10)+2));
      PrintRow(lst,StrGrid);  //行打印
      lst.Clear;
    end;
  finally
    lst.Free;
  end;
end;

procedure TStrGridPrn.StrGridPrint(StrGrid:TStringGrid;
  Header,Footer:string);
begin
  screen.Cursor :=crHourglass;
  strHead :=Header;
  strFoot :=Footer;
  iPage :=1;
  {单表打印}
  try
    with Printer do
    begin
      PixelsInInchX :=GetDeviceCaps(Handle,LOGPIXELSX);
      TenthsOfInchPixelsY :=GetDeviceCaps(Printer.Handle,LOGPIXELSY) div 10;
      iPageHeight :=PageHeight;
      iPageWidth :=PageWidth;    //减去左右边距
      Canvas.Font.Size :=11;
      BeginDoc;
    end;
    {打印页头}
    PrintHeader(Header);
    {打印标题栏:粗体,下划线}
    PrintColumns(StrGrid);
    {循环打印记录}
    PrintRecords(StrGrid);
    {打印页脚:页码}
    PrintFoot(Footer);
  finally
    printer.EndDoc;
    screen.Cursor :=crDefault;
  end;
end;

end.

posted @ 2008-11-19 14:41  delphi中间件  阅读(641)  评论(0编辑  收藏  举报