So I've filled a canvas on my printer object and it prints perfectly. Now I need to save to a file that same canvas that's filled in the printer.canvas. I know I can save a bitmap object and I thought I could just instantiate a bitmap and assign it the printer canvas, but alas, its read-only. This is the line with the error. Anyone has any idea?
bitmapAGuardar.Canvas := Printer.Canvas;
This isn't how to do it, and in fact what you ask can't be done.
Write a function that receives a canvas as its parameter. Have that function perform the necessary drawing. When you need to print to a printer call the function passing the printer canvas. When you need to save to a bitmap, call the function passing the bitmap canvas.
You'll likely need to account for the fact that the printer canvas resolution will be much greater than the resolution you want for the bitmap.
Related
In addition to drawing GDI+ onto a control canvas via TGPGraphics (which has been working fine), I'm also trying to draw onto a TBitmap using GDI+ as well, and then drawing that bitmap to the control canvas. However, nothing actually appears to get drawn.
The following code is within the WM_PAINT message handler, which again works for the actual control canvas, but when creating an equivalent TGPGraphics object and passing this TBitmap handle, nothing gets drawn:
FBitmapCanvas:= CreateGPCanvas(FBitmap.Handle);
try
FBitmapCanvas.DrawLine(FSomePen, P1, P2); //Same pen used to successfully draw to control canvas
finally
FreeAndNil(FBitmapCanvas);
end;
Canvas.Draw(0, 0, FBitmap); //Draw this bitmap to control canvas
CreateGPCanvas looks like so, and is used for both this bitmap and the control:
function CreateGPCanvas(const DC: HDC): TGPGraphics;
begin
Result:= TGPGraphics.Create(DC);
Result.SetInterpolationMode(InterpolationMode.InterpolationModeHighQuality);
Result.SetSmoothingMode(SmoothingMode.SmoothingModeHighQuality);
Result.SetCompositingQuality(CompositingQuality.CompositingQualityHighQuality);
end;
On the other hand, if I don't try to use the TGPGraphics and instead draw a line directly via the TBitmap.Canvas property, it works fine (but of course looks ugly because it's not GDI+). So I know the actual bitmap gets drawn correctly to the control canvas.
FBitmap.Canvas.MoveTo(P1.X, P1.Y);
FBitmap.Canvas.LineTo(P2.X, P2.Y);
What am I doing wrong here, and how do I make the TGPGraphics work on this bitmap canvas?
PS - The only reason I'm using a TBitmap at all is because what I'm actually writing needs to "remember" a portion of what was previously drawn and retain it, rather than repainting it over and over.
Just figured out the problem, and it was a silly mistake.
When creating a TGPGraphics object, instead of passing FBitmap.Handle, it should rather be FBitmap.Canvas.Handle.
You need the handle of the bitmap's canvas, not of the bitmap itself.
I have a form that is higher than the screen, and when I try to simulate the printscreen key with
keybd_event(VK_SNAPSHOT, 1, 0, 0);
of course, the form gets cropped.
So I tried to do the following on the active form:
Clipboard.Assign(GetFormImage);
but still, even in this case, the bitmap gets cropped too.
There was an old Delphi component, BDPrint, that was available here:
http://www.efg2.com/Lab/Library/Delphi/Printing/
but it's not available anymore, that was able to print a form creating a temporary tImage and then printing it, even the off screen portion, but I do not have the source code of it anymore.
How can I generate a bitmap of the active form, with the off screen portion too, and store it in the clipboard? Thank you
Off the top of my head, I could search around some more if I had the time:
fist get the handle of the window (with FindWindow or somesuch)
GetwindowDC
BitBlt onto a TBitmap's Canvas.Handle of your own (or StretchBlt or a personal favorite PlgBlt)
You don't need to involve the clipboard, or otherwise capture the screen. Try passing the form's Handle property to PrintWindow(), or send a WM_PRINT message directly to the Form. Either one will let you specify an HDC (such as the one from the TBitmap.Canvas.Handle property) for the window to draw itself onto.
I try to make use of a TImage32 to combine several layers with positions and transparency etc. So I create in runtime a TImage32, set parent to nil, load from file a bitmap and load from file a layer on top of that bitmap. Now I want to save the result, but I seem to be unable to find where the actual result is. If I do the same with creating the TImage32 in designtime, make it visible, the result of the combined bitmaps is in the Buffer field of TImage32, and I can save the result using Image32.Buffer.SaveToFile('test.bmp'). If the component is not visible, the Buffer is an empty bitmap and the combined bitmap seem to be not created.
Can someone shed light on this? How do I combine bitmaps with GR32, save them, but with invisible components?
Thanks a lot!
Willem
You don't need to use visual controls like TImage.
The library you're using graphics32 has all the methods you need.
Use TBitmap32: The Bitmap can be displayed and scaled using its DrawMode, MasterAlpha and StretchFilter properties.
You simply use the MyBitmap.LoadFromFile method to get it.
I suggest you then store your bitmaps in a TObjectList.
Combine them using TBitmap32.Draw{To}, note that you can use the DrawMode to modify the behavior of Draw.
And use the SaveToFile method as usual when done manipulating the bitmap.
In VCL we can get the color of specific pixel from Canvas or bitmap like this:
Canvas.Pixels[X,Y]
but we have not such a thing for canvas and bitmap in firemonkey components. how can we read or write a specific point on a canvas in FMX?
I presume that you are working with a bitmap, if you wish to operate on pixel data. In which case you use the Map method of the TBitmap class. More details here:
http://www.fmxexpress.com/get-direct-pixel-access-to-bitmaps-in-delphi-xe5-firemonkey-on-android-and-ios/
http://members.adug.org.au/2012/10/05/read-write-image-bitmap-pixels-in-delphi-xe3/
http://docwiki.embarcadero.com/CodeExamples/en/FMX.AlphaColorToPixel_(Delphi)
does any one know how to initilize directX using hdc? the problem is i want to draw my stuff in a component inside a window and these things usualy only have HDC but DX gets HWND which is assigned to a window.
You can create an invisible window using CreateWindow with 0 width and 0 height and use that hwnd to create the device. Then you can render the images to a texture, retreive the raw buffer from it and pass it to the application where the image is copied to the window. You do no need the HDC too.
HDC represents your rendering device, while HWND represents your window.
You can get get an HDC representing the Window's rendering target with GetDC (don't forget to ReleaseDC it when you're done).
Hope that helps?