我作了一个打印程序,可以选择DBGRID中的例来打印,可是打印的效果不好,列与列
之间太紧密,改了几次也不行?请高手指点。如何在打印之前预览DBGRID中的数据,
请讲一下思路?
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, DBGrids, Menus, DB, ADODB;type
  TForm1 = class(TForm)
    ADOConnection1: TADOConnection;
    DataSource1: TDataSource;
    ADOQuery1: TADOQuery;
    PopupMenu1: TPopupMenu;
    N1: TMenuItem;
    N2: TMenuItem;
    DBGrid1: TDBGrid;
    Button1: TButton;
    Button2: TButton;
    FontDialog1: TFontDialog;
    ADOQuery1Cnt: TIntegerField;
    ADOQuery1Name: TStringField;
    ADOQuery1Money: TBCDField;
    procedure DBGrid1TitleClick(Column: TColumn);
    procedure N1Click(Sender: TObject);
    procedure N2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    CurrentColumn : TColumn;
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementationuses DefinePrinter;{$R *.dfm}procedure TForm1.DBGrid1TitleClick(Column: TColumn);
var PT: TPoint;
begin
  GetCursorPos(PT); CurrentColumn :=Column;PopupMenu1.Popup(PT.X,PT.Y);
end;procedure TForm1.N1Click(Sender: TObject);
var I : Integer;
begin
  for I := 0 to DBGrid1.Columns.Count -1 do
    DBGRid1.Columns[i].Visible := True;end;procedure TForm1.N2Click(Sender: TObject);
begin
  CurrentColumn.Visible := False;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
  miPrint(ADOQuery1,DBGrid1,FontDialog1.Font)
end;procedure TForm1.Button2Click(Sender: TObject);
begin
  FontDialog1.Execute
end;end.
//
unit DefinePrinter;interfaceuses
  Printers,Sysutils, Forms,Windows,StdCtrls,ADODB,DateUtils,ExtCtrls,ComCtrls,
  Classes,DBGrids,Graphics,Dialogs,Unit1;
Var
    AmountPrinted:Integer;
    LineHeight: Integer;
    PixelsInInchx : Integer;
    TenthsOfInchpixelsY : Integer;
  procedure PrintLine(AItems : TStringList);
  Procedure PrintColumnNames(AGrid:TDBGrid);
  procedure miPrint(AAdoQuery:TAdoquery;AGrid:TDBGrid;AFont:TFont);implementationprocedure PrintLine(AItems : TStringList);
var OutRect : TRect;
  Inches : Double;
  I : Integer;
begin
  OutRect.Left :=0;
  OutRect.Top := AmountPrinted;
  OutRect.Bottom := OutRect.Top +LineHeight;
  with Printer.Canvas do
  begin
    for I := 0 to AItems.Count -1 do
    begin
      Inches :=LongInt(AItems.Objects[I])*0.1;
      OutRect.Right := OutRect.Left + Round(PixelsInInchx*Inches) ;
      //if not Printer.Abort  then
      TextRect(OutRect,OutRect.Left,OutRect.Top,AItems[i]);
      OutRect.Left :=OutRect.Right+AmountPrinted;
    end;
    AmountPrinted := AmountPrinted +TenthsOfInchpixelsY*2;  end;
end;Procedure PrintColumnNames(AGrid:TDBGrid);
var ColNames : TStringList;
  I ,Awidth: Integer;
begin
  ColNames := TStringList.Create;
  try
    Printer.Canvas.Font.Style :=[fsBold,fsUnderLine];
    with ColNames do
    begin
      for I :=0 to AGrid.Columns.Count-1 do
      if AGrid.Columns[i].Visible then
      begin
       // AWidth := round(AGrid.Columns[i].Width / Screen.PixelsPerInch);
        AddObject(AGrid.Columns[i].Title.Caption,Pointer(Length(AGrid.Columns[i].Title.Caption));
      end;
    end;
    PrintLine(ColNames);
    Printer.Canvas.Font.Style :=[];
  finally
    ColNames.Free;
  end;
end;procedure miPrint(AAdoQuery:TAdoquery;AGrid:TDBGrid;AFont:TFont);
 var AItems : TStringList;
    I ,AWidth: Integer;
begin
  AItems := TStringList.Create;
  try
    PixelsInInchX := GetDeviceCaps(Printer.Handle,LOGPIXELSX);
    TenthsOfInchPixelsY := GetDeviceCaps(Printer.Handle,LOGPIXELSY) div 10;
    AmountPrinted :=0;      Printer.BeginDoc;
      Printer.Canvas.Font.Assign(AFont);
      //AboutForm.Show;
      //Application.ProcessMessages;
      LineHeight := Printer.Canvas.TextHeight('X')+TenthsOFInchPixelsY;
     // if edtHeiderFont.Text<>'' then
      //  PrintHeader;
      PrintColumnNames(AGrid);
      AADoquery.First;
      while not AADoquery.Eof do {or Printer.ABorted}
      begin
        //Application.ProcessMessages
        with AItems do
        begin
          for I := 0 to AGrid.Columns.Count-1 do
          if AGrid.Columns[i].Visible then
          begin
           // ShowMessage(IntToStr(i));
            //AWidth := round(AGrid.Columns[i].Width / Screen.PixelsPerInch );
            AddObject(AADoquery.Fields[i].AsString,Pointer(Length(AADOQuery.Fields[i].AsString)));
          end;
        end;
        PrintLine(AItems);
        if AMountPrinted +LineHeight >Printer.PageHeight then
        begin
          AmountPrinted :=0;
          //if not Printer.Abort then
            Printer.NewPage;
          PrintColumnNames(AGrid);
        end;
        AItems.Clear;
        AAdoquery.Next;
      end;
     // if not Printer.Abort then
        Printer.EndDoc;
  finally
    AItems.Free;
  end;
end;end.

解决方案 »

  1.   

    AmountPrinted := AmountPrinted +TenthsOfInchpixelsY*2;
    将其中的2改大一些,如4、6。
    最好的是不要设置每列为固定的宽度,而将AGrid.Columns[i].Width 乘以一个因子作为列宽。
    ————————————————————————————————————
    宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。
    ————————————————————————————————————
      

  2.   

    谢谢你。你给了我研究的勇气。可能与屏幕分辨率有关,下面是我改好的程序.
    unit DefinePrinter;interfaceuses
      Printers,Sysutils, Forms,Windows,StdCtrls,ADODB,DateUtils,ExtCtrls,ComCtrls,
      Classes,DBGrids,Graphics;
    Var
        AmountPrinted:Integer;
        LineHeight: Integer;
        PixelsInInchx : Integer;
        TenthsOfInchpixelsY : Integer;
      procedure PrintLine(AItems : TStringList);
      Procedure PrintColumnNames(AGrid:TDBGrid);
      procedure miPrint(AAdoQuery:TAdoquery;AGrid:TDBGrid);implementationprocedure PrintLine(AItems : TStringList);
    var OutRect : TRect;
      Inches : Double;
      I : Integer;
    begin
      OutRect.Left :=0;
      OutRect.Top := AmountPrinted;
      OutRect.Bottom := OutRect.Top +LineHeight;
      with Printer.Canvas do
      begin
        for I := 0 to AItems.Count -1 do
        begin
          Inches :=LongInt(AItems.Objects[I]);
          OutRect.Right := OutRect.Left + Round(PixelsInInchx*Inches) ;
          //if not Printer.Abort  then
          TextRect(OutRect,OutRect.Left,OutRect.Top,AItems[i]);
          OutRect.Left :=OutRect.Right;
        end;
        AmountPrinted := AmountPrinted +TenthsOfInchpixelsY*2;
      end;
    end;Procedure PrintColumnNames(AGrid:TDBGrid);
    var ColNames : TStringList;
      I ,Awidth: Integer;
    begin
      ColNames := TStringList.Create;
      try
        Printer.Canvas.Font.Style :=[fsBold,fsUnderLine];
        with ColNames do
        begin
          for I :=0 to AGrid.Columns.Count-1 do
          if AGrid.Columns[i].Visible then
          begin
            AWidth := round(AGrid.Columns[i].Width / Screen.PixelsPerInch);
            AddObject(AGrid.Columns[i].Title.Caption,Pointer(AWidth));
          end;
        end;
        PrintLine(ColNames);
        Printer.Canvas.Font.Style :=[];
      finally
        ColNames.Free;
      end;
    end;procedure miPrint(AAdoQuery:TAdoquery;AGrid:TDBGrid);
     var AItems : TStringList;
        I ,AWidth: Integer;
    begin
      AItems := TStringList.Create;
      try
        PixelsInInchX := GetDeviceCaps(Printer.Handle,LOGPIXELSX);
        TenthsOfInchPixelsY := GetDeviceCaps(Printer.Handle,LOGPIXELSY) div 10;
        AmountPrinted :=0;      Printer.BeginDoc;
          //AboutForm.Show;
          //Application.ProcessMessages;
          LineHeight := Printer.Canvas.TextHeight('X')+TenthsOFInchPixelsY;
         // if edtHeiderFont.Text<>'' then
          //  PrintHeader;
          PrintColumnNames(AGrid);
          AADoquery.First;
          while not AADoquery.Eof do {or Printer.ABorted}
          begin
            //Application.ProcessMessages
            with AItems do
            begin
              for I := 0 to AGrid.Columns.Count-1 do
              if AGrid.Columns[i].Visible then
              begin
               // AWidth := round(AADoquery.Fields[i].DisplayWidth / Screen.PixelsPerInch );
                AWidth := round(AGrid.Columns[i].Width / Screen.PixelsPerInch );
                AddObject(AADoquery.Fields[i].AsString,Pointer(AWidth));
              end;
            end;
            PrintLine(AItems);
            if AMountPrinted +LineHeight >Printer.PageHeight then
            begin
              AmountPrinted :=0;
              //if not Printer.Abort then
                Printer.NewPage;
              PrintColumnNames(AGrid);
            end;
            AItems.Clear;
            AAdoquery.Next;
          end;
         // if not Printer.Abort then
            Printer.EndDoc;
      finally
        AItems.Free;
      end;
    end;end.