0

I use this code to save a screenshot of a Form to a bitmap file:

var
  Bmp : Graphics.TBitmap;
begin
  Bmp := GetFormImage;
  try
    Bmp.SaveToFile( _DestFilePath );
  finally
    Bmp.Free;
  end;
end;

However, it doesn't seem to work well when a TRichEdit control is placed on the Form. Instead of a TRichEdit control and all its content, a white rectangle is saved into the final image.

How can I get a complete screenshot of a Form that contains a non-blank TRichEdit control?

I use Delphi 2009.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Max Smith
  • 395
  • 1
  • 2
  • 13

1 Answers1

2

If GetFormImage() fails, you should try to BitBlt() the Form's contents yourself, eg:

var bm := TBitmap.Create(ClientWidth, ClientHeight);
try
  BitBlt(bm.Canvas.Handle, 0, 0, ClientWidth, ClientHeight, Self.Canvas.Handle, 0, 0, SRCCOPY);
  // use bm as needed...
finally
  bm.Free;
end;

This successfully copies a Form with a TRichEdit for me.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • You can't *safely* use the Form's `Canvas` from outside of its `OnPaint` event. Note that internally, `GetFormImage()` uses `TControl.PaintTo()` which simulates `WM_ERASEBKGND` and `WM_PAINT` messages to draw the Form and each of its controls onto the returned `TBitmap` canvas. So the original problem has to be with how `PaintTo()` interacts with `TRichEdit`. – Remy Lebeau Aug 01 '22 at 21:43
  • @RemyLebeau: Could you please elaborate on the `Canvas` issue? Also, why do you want "Form" to be capitalized? English nouns aren't typically capitalized in sentence case. – Andreas Rejbrand Aug 01 '22 at 22:48
  • "*English nouns aren't typically capitalized*" - a *Proper Noun* (a **specific** person, place, or thing) is always capitalized. A *Common Noun* (a **generic type** of person, place, or thing) is capitalized only at the beginning of a sentence. I guess it comes down to whether you consider a reference to a `TForm` object to be a *Proper* noun or a *Common* noun. I prefer the former. It just looks cleaner and easier to read, especially when talking about a specific `TForm` object. – Remy Lebeau Aug 01 '22 at 22:57
  • @RemyLebeau: I disagree. Surely you don't want to take the Dog for a walk in its favourite Park, even if it is a very specific dog and an equally specific park. And in Windows, you can have five buttons and a check box in a window (or a form). – Andreas Rejbrand Aug 01 '22 at 23:25
  • (I disagree *respectfully*.) – Andreas Rejbrand Aug 01 '22 at 23:29
  • So we agree to disagree. I'll leave it at that. This is an off-topic discussion. – Remy Lebeau Aug 01 '22 at 23:56
  • The code kindly suggested by Andreas Rejbrand is functional, however, at least in Delphi 2009, you can't create a bitmap instance as shown in the answer, as the constructor doesn't take any arguments. You still need to set its dimensions though, which can be done once you instantiate it. – Max Smith Aug 02 '22 at 09:52
  • @MaxSmith: Correct, that constructor overload is rather new. You need to do `bm.SetSize(ClientWidth, ClientHeight)`. Also, inline variable declarations aren't possible in Delphi 2009, so `var bm :=... ` won't work. Instead, you need to declare `bm` in the `var` section before `begin`. – Andreas Rejbrand Aug 02 '22 at 09:58