StringGrid生成后,个别的行和列都进行了调整
很多地方都进行了合并,所以并不是一个规则的表格
同时,有些合并了的单元格里面的字数很多,又因为StringGrid不能换行,
在显示的时候通过Canvas.TextOut()方式进行了换行
而且整个StringGrid通过DrawCells方法进行了上下左右的居中美化
但打印的时候这些效果都又恢复原样了
怎样才能把屏幕上显示的效果通过打印机打印出来呢?
我用的是AdvStringGrid控件包
最好不要通过FastReport等控件或者QReport等表来打印
有知道的侠客们能指点一下吗?

解决方案 »

  1.   

    用copyrectuses
    printers;printer.Canvas.CopyRect(stringgrid1.ClientRect,stringgrid1.Canvas,stringgrid1.ClientRect);//我试验过,肯定没有问题。
    //不用任何的控件
    //printer 的操作,具体看帮助。
    //如果我提示能够帮助你,别忘了给点分。
      

  2.   

    区域打印  , ARect是指定的TRect if not PrintDialog.Execute then Exit;  Printer.BeginDoc;
      Img := TImage.Create(nil);
      try
        OutputWidth := ARect.Right - ARect.Left;
        OutputHeight := ARect.Bottom - ARect.Top;    Img.Width := Round(OutputWidth);
        Img.Height := Round(OutputHeight);
        FDynAnalysisFrame.Plot1.Repaint;
        Img.Canvas.CopyRect(ARect, ASource, ARect);    AspectRatio := OutputWidth / OutputHeight;
        if (OutputWidth < Printer.PageWidth) and (OutputHeight < Printer.PageHeight) then
        begin
          if OutputWidth < OutputHeight then
          begin
            OutputHeight := Printer.PageHeight;
            OutputWidth := OutputHeight * AspectRatio;
          end
          else
          begin
            OutputWidth := Printer.PageWidth;
            OutputHeight := OutputWidth / AspectRatio;
          end
        end;
        if OutputWidth > Printer.PageWidth then
        begin
          OutputWidth := Printer.PageWidth;
          OutputHeight := OutputWidth / AspectRatio;
        end;
        if OutputHeight > Printer.PageHeight then
        begin
          OutputHeight := Printer.PageHeight;
          OutputWidth := OutputHeight * AspectRatio;
        end;
        Printer.Canvas.StretchDraw(Rect(0, 0, Trunc(OutputWidth), Trunc(OutputHeight)), Img.Picture.Graphic);
      finally
        Printer.EndDoc;
        Img.Free;
      end;
      

  3.   

    Thanks flashtong!不过这个方法我试过后没有办法满足要求,它对StringGrid的Scrollbar没有效果,只能将屏幕上显示出来的部分打印出来。
    另外,用copyRect,怎么同时把握屏幕上出现的打印对话框都打印出来了,遮挡住了部分表格,不知道是什么问题?我把Canvas锁住了,还是会出现把对话框打印出来的问题!也谢谢byteh,我试了试你的代码,总是编译通不过,存在两个问题没弄明白
    1、FDynAnalysisFrame.Plot1.Repaint; 这个是什么?
    2、Img.Canvas.CopyRect(ARect, ASource, ARect)总提示我参数错误!
       我用的是Img.Canvas.CopyRect(Grid1.ClientRect, Img.Canvas, Grid1.ClientRect);
       或者   Img.Canvas.CopyRect(Img.ClientRect, Img.Canvas, Grid1.ClientRect);
       都提示“参数错误”,不明白是怎么回事?
    3、用byteh你的这种方法,是不是也没有办法把表格完全打印到一张纸上呢?
       我的所有的StringGrid都是比较长,用了VSrollBar上下滚动,但打印出来都可以在一张纸上放下。用了CopyRect后,总是只能打印可视部分的表格不知道有没有办法解决呢?谢谢
      

  4.   

    非要用FastReport吗?
    难道delphi自身实现不了这样的需求吗?
      

  5.   

    你可以先把StringGrid里面的内容导入到Excel里面,然后在Excel里面调整后调用打印,这样的话,你也不用再编写打印代码了。下面这段代码实现将StringGrid内容导入到.XLS
    procedure stringGridtoExcell(stringgrid1:Tstringgrid);
    var
        eclApp,WorkBook:Variant;
        xlsFileName:string;
        l_row,l_col:integer;
    begin
        xlsFileName:='ex.xls';
        try
          //创建OLE对象Excel Application与 WorkBook
          eclApp:=CreateOleObject('Excel.Application');
          WorkBook:=CreateOleobject('Excel.Sheet');
        except
         ShowMessage('您的机器里未安装Microsoft Excel。');
         Exit;
       end;
       try
       workBook:=eclApp.workBooks.Add;
       for l_row:=0 to stringgrid1.rowcount-1 do
       begin
        for l_col:=0 to stringgrid1.ColCount-1 do
        begin
         eclApp.cells[l_row+1,l_col+1]:=stringgrid1.cells[l_col,l_row];
        end;
       end;   form1.SaveDialog1.Filter:='Excel文件|*.xls';//上句可省略,只是作显示。
       if not form1.SaveDialog1.Execute then exit;   WorkBook.saveas(form1.SaveDialog1.FileName);
      //打印预览
        eclApp.Visible:=true;
        eclApp.WindowState := 2;
      //再最大化
        eclApp.WindowState := 1;
        //退出Excel Application
        //释放VARIANT变量
        except
        ShowMessage('不能正确操作Excel文件。可能是该文件已被其他程序打开, 或系统错误。');
        WorkBook.close;
        //释放VARIANT变量
    //    eclApp:=Unassigned;
        end;
    end;
      

  6.   

    1、FDynAnalysisFrame.Plot1.Repaint;   这个是什么? 
    2、Img.Canvas.CopyRect(ARect,   ASource,   ARect)总提示我参数错误! 
          我用的是Img.Canvas.CopyRect(Grid1.ClientRect,   Img.Canvas,   Grid1.ClientRect); 
          或者       Img.Canvas.CopyRect(Img.ClientRect,   Img.Canvas,   Grid1.ClientRect); 
          都提示“参数错误”,不明白是怎么回事? sorry,这是从我的代码里面粘过来的,供你参考,不能直接用的,不好意思!
    如果是规矩的二维表,不行就放到Excel里面,执行个打印
    你想都打印到一页?
      

  7.   

    为什么大家这么喜欢拷屏打印的方式?我觉得这种打印效果未免太粗糙了吧?另外,VCL的Canvas用于打印图象,非常不乐观,因为有时候打印出来或者什么没有,或者就一个深色方块,这种情况,我经常遇到,很多资料有说明,也提出了各种解决方案。VCL的TForm的Print方法,就是拷屏打印的,但Borland自己都不乐意用Canvas方法来打印,可以打开Forms单元去看Borland是怎么打印Form的!
      

  8.   

    回复楼上的,你可以仔细看看vcl的 forms 的4693行 到 4763行,我的是d7。楼主,你的这个完全可以用 canvas打印出来的。在csdn搜了一个,思路可以,楼主看下;
    procedure PrintGrid(sGrid: TStringGrid; sTitle: string);
    var
      X1, X2: Integer;
      Y1, Y2: Integer;
      TmpI: Integer;
      F: Integer;
      TR: TRect;
    begin
      Printer.Title := sTitle;
      Printer.BeginDoc;
      Printer.Canvas.Pen.Color := 0;
      Printer.Canvas.Font.Name := 'Times   New   Roman';
      Printer.Canvas.Font.Size := 12;
      Printer.Canvas.Font.Style := [fsBold, fsUnderline];
      Printer.Canvas.TextOut(0, 100, Printer.Title);
      for F := 1 to sGrid.ColCount - 1 do begin
        X1 := 0;
        for TmpI := 1 to (F - 1) do
          X1 := X1 + 5 * (sGrid.ColWidths[TmpI]);
        Y1 := 300;
        X2 := 0;
        for TmpI := 1 to F do
          X2 := X2 + 5 * (sGrid.ColWidths[TmpI]);
        Y2 := 450;
        TR := Rect(X1, Y1, X2 - 30, Y2);
        Printer.Canvas.Font.Style := [fsBold];
        Printer.Canvas.Font.Size := 7;
        Printer.Canvas.TextRect(TR, X1 + 50, 350, sGrid.Cells[F, 0]);
        Printer.Canvas.Font.Style := [];
        for TmpI := 1 to sGrid.RowCount - 1 do begin
          Y1 := 150 * TmpI + 300;
          Y2 := 150 * (TmpI + 1) + 300;
          TR := Rect(X1, Y1, X2 - 30, Y2);
          Printer.Canvas.TextRect(TR, X1 + 50, Y1 + 50, sGrid.Cells[F, TmpI]);
        end;
      end;
      Printer.EndDoc;
    end;