我创建了一个打印预览对象,它允许我将来自不同来源的多个图形对象组织到打印页面上。
为了在打印机画布上渲染这些对象,我必须首先将它们渲染为计算大小的位图,然后使用 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;