1

我创建了一个打印预览对象,它允许我将来自不同来源的多个图形对象组织到打印页面上。

为了在打印机画布上渲染这些对象,我必须首先将它们渲染为计算大小的位图,然后使用 canvas.draw(x,y,bitmap) 方法将位图渲染到 Tprinter 画布的正确位置。

我很早就发现需要一个与设备无关的位图,并将像素格式设置为 pf24bit。

在办公室 HP Laserjet 上试过,工作正常,HP 彩色 Deskjet 工作正常,Cannon 彩色打印机但不工作或偶尔在随机点出现断断续续的图形。

现在,如果我让图形对象直接渲染到打印机画布上,那么一切正常。

然而,由于各种原因,直接渲染到打印机画布对我来说不是一个可行的长期解决方案。

所以,我的问题是,Tprinter.canvas 是什么使它依赖于硬件并且有任何解决方法吗?

一些示例代码将页面划分为具有边距和单元格填充的 4 个象限,并在每个象限中放置一个图形对象。每个图形对象都有一个绘制图形的 RenderToBitmap 方法。

procedure TMultiPrintForm.PrintBtnClick(Sender: TObject);
var w,h,h2,w2,mv,iw,ih,pv,cw,ch:integer; Abmp:Tbitmap;
begin
  Abmp:=Tbitmap.create;
  Abmp.PixelFormat := pf24bit;
  try
    with Printer do
    begin
      w:=pagewidth;   
      h:=pageheight; 
      h2:=h div 2; 
      w2:=w div 2;
      mv:=h*margin.value div 200;    //margin percentage div 2 
      pv:=h*padding.value div 400;   //padding percentage div 4
      iw:=w-mv;                      //internal width
      ih:=h-mv;                      //internal height
      cw:=(iw-mv) div 2-pv;          //Quadrant Cell Width
      ch:=(ih-mv) div 2-pv;          //Quadrant Cell Height
      Abmp.width:=cw;
      Abmp.height:=ch;
      If Fsources[0]<>nil then
      begin
        Fsources[0].rendertoBitmap(Abmp);
        canvas.draw(mv,mv,Abmp);
      end;
      If Fsources[1]<>nil then
      begin
        Fsources[1].rendertoBitmap(Abmp);
        canvas.draw(w2+pv,mv,Abmp);
      end;
      If Fsources[2]<>nil then
      begin
        Fsources[2].rendertoBitmap(Abmp);
        canvas.draw(mv,h2+pv,Abmp);
      end;
      If Fsources[3]<>nil then
      begin
        Fsources[3].rendertoBitmap(Abmp);
        canvas.draw(w2+pv,h2+pv,Abmp);
      end;
    end;
  finally
    printer.Enddoc;
    Abmp.free;
  end
end;

在网上的进一步调查中,我在 PrintBitmap 程序中积累了一些建议,该程序使用了 Microsoft 推荐的技术。

我用 PrintBitmap 调用替换了所有 Canvas.draw 调用(它假设 begindoc 和 enddoc 设置在调用之外)。

由于是周末,我无法在办公室有问题的打印机上对其进行测试,但它至少不会破坏家用 HP Deskjet 打印机的打印(无论如何都适用于这两种方法)。

procedure PrintBitmap(X,Y:integer; Abmp:Tbitmap);
var Info: PBitmapInfo;
  InfoSize,ImageSize: DWORD;  Image: Pointer;
  DIBWidth, DIBHeight: LongInt;
begin
  with Printer do
  begin
    GetDIBSizes(Abmp.Handle, InfoSize, ImageSize);
    Info  := AllocMem(InfoSize);
    Image := AllocMem(ImageSize);
    try
      GetDIB(Abmp.Handle, 0, Info^, Image^);
      with Info^.bmiHeader do
      begin
        DIBWidth := biWidth;
        DIBHeight := biHeight;
      end;
      StretchDIBits(Canvas.Handle, X, Y, DIBWidth, DIBHeight, 0, 0,
      DIBWidth, DIBHeight, Image, Info^, DIB_RGB_COLORS, SRCCOPY);
    finally
      FreeMem(Image, ImageSize);
      FreeMem(Info, InfoSize);
    end
  end;
end;
4

0 回答 0