2

I am trying to capture Printer.Canvas as a Bitmap using BitBlt. I want to then take that Bitmap and display it on a paintbox. However, when I attempt this I am given only a white rectangle proportionate to the values I entered for Bitmap.SetSize. My printout looks correct, so I am almost positive the canvas of the printer is being properly drawn to. I attempted the following code using the variable bitmap as the destination and the paintbox as the source (in essence I was drawing a simple rectangle and line of text to the Paintbox, bitblt-ing it to a bitmap, clearing it, and then posting it back to the paintbox), but now that Printer.Canvas.Handle is the source it doesn't display.

I understand that the dimensions between the screen and printer are different so I will clearly indicate dimensions, just in case I am doing it wrong.

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;

I expect that the canvas would be written too, the canvas would be copied to a bitmap, then be available to be drawn on the paintbox. However all I see is a white rectangle. I am setting the dimensions of the bitmap to be the entire paintbox rather than the entire canvas of the printer. I am doing this because if I understand it correctly I should be only be drawing between the printer canvas's TopLeft 0,0 and BottomRight 300,300 the same way I would on my paint box. I would expect to see the same results as I would if I did this directly to the Paintbox.

Any help would be greatly appreciated. Thanks in advance.

Given the comments I've received it seems what I was trying to do was not possible. What I wanted to do was to write to a printers canvas and then get the image data of that canvas and store it in a bitmap. Since BitBlt can't be used is there a way to do what I wanted? I assume not, as I was told Printer.Canvas cannot be read from. At this point I have Found a way around it but I am just curious.

CodeMonkey
  • 135
  • 2
  • 13
  • 1
    You can't use BitBlt...you need to work with DIB...look at GetDIBits and SetDIBits and StretchDIBits – House of Dexter Jul 23 '13 at 17:16
  • Can you explain why? I am interested to understand why the Printers.Canvas.Handle, is different from Paintbox.Canvas.Handle (besides the obvious). Thanks for the response I will look into this. – CodeMonkey Jul 23 '13 at 17:20
  • 1
    You cannot **read** from **printer** by the same reason as you cannot **write** to **scanner** or **microphone**. – OnTheFly Jul 23 '13 at 17:43
  • Given the comments I've received it seems what I was trying to do was not possible. What I wanted to do was to write to a printers canvas and then get the image data of that canvas and store it in a bitmap. Since BitBlt can't be used is there a way to do what I wanted? I assume not, as I was told Printer.Canvas cannot be read from. At this point I have Found a way around it but I am just curious. – CodeMonkey Jul 23 '13 at 18:45
  • And what was he using....yes he was trying to draw to the printer and then take that and show it in a PaintBox...Where if he had drawn to the PaintBox first he could easily print that. – House of Dexter Aug 23 '16 at 05:18

1 Answers1

0

Switch your logic...draw to the PaintBox...and Print the 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;
House of Dexter
  • 386
  • 1
  • 7
  • Which is not very clever as well. Imagine you print to a PDF file with 300 dpi and then later this PDF to a printer with 600 dpi. The resampled result will be most probably ugly. In addition you have one large bitmap in the PDF and the PDF file is big like if it was a scan. IMO there is no generic method to solve this problem, you have to print vector graphics and images without transparency whenever possible. Or copy from the printer canvas and hope it will return valid data. Some PDF printers return valid data. – tk_ Aug 18 '16 at 15:24
  • He wasn't asking to print a pdf...he was asking how to BitBlt to printer and wondering why it wouldn't work. So I showed how to make BitBlt work with what he was working with which was a PaintBox and Printer. – House of Dexter Aug 18 '16 at 17:12
  • No he was asking how to BitBlt from printer canvas. An I did not answer his question but commented your answer. Because it might solve his question in this particular case but in general this is not a nice solution. For some reason he wanted to print something (printer can be pdf printer) and I came here because I had similar problem. – tk_ Aug 20 '16 at 15:11