【问题标题】:BitBlt Printer.Canvas to a TBitMap displays as solid whiteBitBlt Printer.Canvas 到 TBitMap 显示为纯白色
【发布时间】:2013-07-24 07:05:24
【问题描述】:

我正在尝试使用 BitBlt 将 Printer.Canvas 捕获为位图。然后我想获取该位图并将其显示在油漆盒上。但是,当我尝试这样做时,我只会得到一个与我为 Bitmap.SetSize 输入的值成比例的白色矩形。我的打印输出看起来是正确的,所以我几乎可以肯定打印机的画布​​正在正确绘制。我尝试了以下代码,使用变量位图作为目标,油漆盒作为源(本质上,我在油漆盒中绘制了一个简单的矩形和一行文本,将它位映射到位图,清除它,然后发布它回到画框),但现在 Printer.Canvas.Handle 是它不显示的源。

我知道屏幕和打印机之间的尺寸不同,所以我会清楚地指出尺寸,以防我做错了。

procedure TForm2.btnDrawClick(Sender: TObject);
begin
  Printer.BeginDoc;
  Printer.Canvas.Font.Size := 10; //Not Sure if this is necessary
  Printer.Canvas.Font.Name := 'Arial'; //Not Sure if this is necessary
  Printer.Canvas.Font.Color := clBlack; //Not Sure if this is necessary
  Printer.Canvas.Rectangle(100,100,200,200); //Should print very tiny to paper
                                             //But will look bigger when posted to 
                                             //The Paintbox
  Printer.Canvas.TextOut(120,120,'XRay-Cat');
  PCBitmap.SetSize(Paintbox1.Width,Paintbox1.Height); //Paint box is 300W,300H
  Application.ProcessMessages;
  BitBlt(PCBitmap.Canvas.Handle, //PCBitmap, is created on create, freed on destroy,
                                 //Defined in the private section                            
         0,
         0,
         PCBitmap.Width, //300
         PCBitmap.Height, //300
         Printer.Canvas.Handle,
         0,
         0,
         SRCCOPY);
  Application.ProcessMessages;
  Printer.EndDoc;

procedure TForm2.btnPostBMClick(Sender: TObject);
begin
  PaintBox1.Canvas.Draw(0,0,PCBitmap); 
end;

我希望画布也会被写入,画布将被复制到位图,然后可以在画盒上绘制。然而,我看到的只是一个白色矩形。我将位图的尺寸设置为整个画框,而不是打印机的整个画布。我这样做是因为如果我理解正确,我应该只在打印机画布的 TopLeft 0,0 和 BottomRight 300,300 之间绘制,就像在我的油漆盒上一样。我希望看到与直接对 Paintbox 执行此操作时相同的结果。

任何帮助将不胜感激。提前致谢。

鉴于我收到的 cmets,似乎我试图做的事情是不可能的。我想做的是写入打印机画布,然后获取该画布的图像数据并将其存储在位图中。由于无法使用 BitBlt 有没有办法做我想做的事?我认为不是,因为有人告诉我 Printer.Canvas 无法读取。在这一点上,我找到了解决方法,但我只是好奇。

【问题讨论】:

  • 你不能使用 BitBlt...您需要使用 DIB...查看 GetDIBits 和 SetDIBits 和 StretchDIBits
  • 你能解释一下为什么吗?我有兴趣了解为什么 Printers.Canvas.Handle 与 Paintbox.Canvas.Handle 不同(除了显而易见的)。感谢您的回复,我将对此进行调查。
  • 您无法从打印机 读取,原因与您无法写入扫描仪相同> 或麦克风
  • 这是有道理的。谢谢你的解释。
  • 鉴于我收到的 cmets 似乎我试图做的事情是不可能的。我想做的是写入打印机画布,然后获取该画布的图像数据并将其存储在位图中。由于无法使用 BitBlt 有没有办法做我想做的事?我认为不是,因为有人告诉我 Printer.Canvas 无法读取。在这一点上,我找到了解决方法,但我只是好奇。

标签: delphi printing bitblt


【解决方案1】:

切换您的逻辑...绘制到 PaintBox...并打印 PaintBox

procedure TForm55.Button1Click(Sender: TObject);
var
  a_BM: TBitMap;
begin
  a_BM := TBitmap.Create;
  try

    PaintBox1.Canvas.Font.Size := 10; //Not Sure if this is necessary
    PaintBox1.Canvas.Font.Name := 'Arial'; //Not Sure if this is necessary
    PaintBox1.Canvas.Font.Color := clBlack; //Not Sure if this is necessary
    PaintBox1.Canvas.Rectangle(0,0,300,300); //Should print very tiny to paper
                                               //But will look bigger when posted to
                                               //The Paintbox
    PaintBox1.Canvas.TextOut(120,120,'XRay-Cat');
    PaintBox1.Width := 300;
    PaintBox1.Height := 300;
    a_BM.SetSize(PaintBox1.Width, PaintBox1.Height);
    BitBlt(a_BM.Canvas.Handle, 0, 0, a_BM.Width, a_BM.Height, PaintBox1.Canvas.Handle, 0, 0, SRCCOPY);
    Application.ProcessMessages;
    Printer.BeginDoc;
    Printer.Canvas.Draw(a_BM.Canvas.ClipRect.Left, a_BM.Canvas.ClipRect.Top, a_BM);
    Printer.EndDoc;
    Application.ProcessMessages;
  finally
    a_BM.Free;
  end;
end;

【讨论】:

  • 这也不是很聪明。想象一下,您打印到 300 dpi 的 PDF 文件,然后将此 PDF 打印到 600 dpi 的打印机。重新采样的结果很可能很丑陋。此外,您在 PDF 中有一个大位图,并且 PDF 文件很大,就像是扫描件一样。 IMO 没有通用的方法来解决这个问题,您必须尽可能打印没有透明度的矢量图形和图像。或从打印机画布复制并希望它会返回有效数据。一些 PDF 打印机返回有效数据。
  • 他并没有要求打印 pdf...他是在询问如何将 BitBlt 打印到打印机并想知道为什么它不起作用。所以我展示了如何让 BitBlt 与他正在使用的 PaintBox 和打印机一起工作。
  • 不,他问的是如何从打印机画布上进行 BitBlt。我没有回答他的问题,但评论了你的回答。因为在这种特殊情况下它可能会解决他的问题,但总的来说这不是一个好的解决方案。出于某种原因,他想打印一些东西(打印机可以是 pdf 打印机),我来到这里是因为我遇到了类似的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-07
  • 1970-01-01
  • 2020-01-25
  • 2019-09-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-30
相关资源
最近更新 更多