Retrieve bitmap of populated panel that is not visible (offscreen)?

Hi All.
I have a requirement to efficiently get the bitmap of a control populated panel (or form) that is not visible to the user. I’ve tried a number of things including:
GetDC(0) and GetWindowsDC() but these are direct Windows API and seem to require that the control is actually visible to work.
The best I have achieved so far is using TWinControl.PaintTo() [AControl.PaintTo(FBitmap.Canvas, 0, 0);], which does work.
However, my initial testing shows that TMemo.PaintTo does NOT work properly when it is hidden. It draws incorrectly including missing the text. This occurs when styling is used or not.

  1. Any suggestions for another approach?
  2. Any hack available for the TMemo.PaintTo problem?
    VCL - Delphi 12 Patch 1 - Win32
    Thanks, Gerard Hook

This is going to be a problem. When you say “not visible to the user” do you mean that Visible = False? Or did you mean it is visible but it’s somewhere the user can’t see it?

If you mean is not being displayed then it likely has not got the right amount of rendering occurred for you to grab the contents - they literally do not exist yet.

You can use the new HandlesNeeded method - Vcl.Controls.TWinControl.ChildHandlesNeeded - RAD Studio API Documentation - to force the creation of some or all of the Windows handles and that might help.

You can also render the panel to a different device context (like you would to print it) and then grab that - but, again, it’s not always going to work, especially if you are using things like 3rd party controls and VCL styles. I’ve done similar things in the past to compose a large composite image/control for saving as a bitmap and/or printing.

If it’s a panel over which you have control, I would simply make it visible (set the visible property to true and thus force the rendering) but have it physically invisible/off-screen to the user.

1 Like

Thanks Ian,

You’ve confirmed what I have already spent too much time finding out. Vcl + Windows does not easily accommodate off screen drawing as far as I can tell.

I suspect that many of the issues I have faced would be mitigated under FMX where it would most likely be an achievable task.

I did try TWinControl.ChildHandlesNeeded and this did not help.

I have another way forward but I thank you for your confirmation.

Regards, Gerard Hook

Are you sure? I’ve experimented with creating a form, and a memo that’s not visible, and has content.

I moved the form such that only the button to capture the form (together with the memo) is visible.

After clicking the button, the saved image (bmp, png) contained the memo, and I took only about a few minutes to create this.

You’re not showing your reproducible code to let us know how it doesn’t work, and we’re all just guessing what part of your code doesn’t work.

Maybe it’s a good idea to show your code.

I think he meant that the control was not visible - as in the visible property is false from the start and not made true.

It also depends on the type of control and a few other factors such as parent visibility. I played around with a panel and some controls, and I found the same results Gerard did.

FMX works differently due to the whole rendering being handled by the framework and you get more opportunities to intervene in that process. The VCL is subject to the quirks of how Windows does things since many of the controls are effectively wrappers.

There was one question I answered recently where the person was enumerating child controls on a panel and the second time they did that they were getting ‘mystery’ child controls without a name. It turns out the drawing of the controls was dynamically creating a TLayout control during the visual rendering presumably to help with alignment.

Isn’t coding fun? :zany_face:

Which is what I’ve achieved, moving the control offscreen, and also Visible := False :grinning_face:

There’s also the more difficult method using TVirtualMethodInterceptor :grinning_face: which also works no matter where the control is, or the state of its Visible property.

1 Like

Thanks Chee/ Ian.

What I was attempting to do was to draw controls or panels or forms containing controls that are not seen by the user (visible= false or moved off-screen) to a Skia control for another purpose. I’ve moved on from this now because I’ve concluded that the VCL’s close ties to Windows (TWinControl) make it impossible to get a generic and consistent result that is useful. Some controls will paint correctly and others won’t. In addition, the VCL Styles mechanism also complicates things. I initially went down this rabbit hole because TWinControl will always draw on top of a TControl which is stated somewhere in the Delphi help. This alone I’m sure is one of the many annoyances that has been redesigned in FMX.

I’ve done many tests (in my sleep and awake) and I would recommend avoiding this problem in VCL.

Thanks again, Gerard Hook

1 Like