Recent

Author Topic: SOLVED: Capturing a Panel inside ScrollBox  (Read 1391 times)

SaraT

  • Full Member
  • ***
  • Posts: 121
  • A little student
SOLVED: Capturing a Panel inside ScrollBox
« on: April 08, 2020, 10:46:36 pm »
Hi there,

I want to save a Panel to image but the saved image has a part in black.
The scrollbox is hidding the rest of the Panel.

How can I take a screen shot of the whole panel?

See attached gif. Thanks a lot.

Used code:
Code: Pascal  [Select][+][-]
  1. var
  2.   bmp: TBitmap;
  3.   d:THandle;
  4. begin
  5.   d:=GetDC(Panel1.Handle);
  6.   bmp := TBitmap.Create;
  7.   bmp.Width := Panel1.Width;
  8.   bmp.Height := Panel1.Height;
  9.   bmp.LoadFromDevice(d);
  10.   bmp.SaveToFile('C:\Users\Username\Desktop\test.bmp');
  11.   bmp.Free;
  12.   ReleaseDC(Panel1.Handle, d);
« Last Edit: April 09, 2020, 06:54:50 pm by SaraT »

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Capturing a Panel inside ScrollBox
« Reply #1 on: April 08, 2020, 10:53:48 pm »
You have PaintTo, but I thinking it isn't going to work for you if it's covered up..

of course you prep a Tbitmap to accept it.


 You could always use a Timage…

« Last Edit: April 08, 2020, 10:55:48 pm by jamie »
The only true wisdom is knowing you know nothing

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Capturing a Panel inside ScrollBox
« Reply #2 on: April 09, 2020, 12:20:12 am »
Hi!

If you make a screenshot with

LoadFromDevice

it does exactly what the names says:

It shots all visible parts of a visible element.
If a part is hidden it can not be shot.
Like a camera.

Further : give all message or dialog boxes time to vanish with an
application.processmessages.

I once took a screenshot with a big black rectangle in the middle:
That was the "leftover" of the file save dialog because it was not complete closed, when the screenshot was done.

Winni

eljo

  • Sr. Member
  • ****
  • Posts: 468
Re: Capturing a Panel inside ScrollBox
« Reply #3 on: April 09, 2020, 03:12:41 am »
Sorry the way the windows widgets works that is not possible. Why not just copy everything from the image directly?

SaraT

  • Full Member
  • ***
  • Posts: 121
  • A little student
Re: Capturing a Panel inside ScrollBox
« Reply #4 on: April 09, 2020, 04:13:29 am »
Sorry the way the windows widgets works that is not possible. Why not just copy everything from the image directly?
Thnx coders,

@eljo, I have others TImages controls with transparent png (like layers) so I have to do a screenshot the panel.

Estructure (bottom to up):

->TImage...
->TImage (smaller than main)
->Timage (main background)
Panel container

eljo

  • Sr. Member
  • ****
  • Posts: 468
Re: Capturing a Panel inside ScrollBox
« Reply #5 on: April 09, 2020, 04:35:38 am »
@eljo, I have others TImages controls with transparent png (like layers) so I have to do a screenshot the panel.

Estructure (bottom to up):

->TImage...
->TImage (smaller than main)
->Timage (main background)
Panel container
That does not change the fact that the portion that is outside the visible area of the scrollbox is not painted at all. There is nothing on screen to capture.
You have to create a bitmap, set its size to the maximum size required to paint everything then work your way up the EStructure from bottom to top and use bitmap.canvas.draw(x,y, imageX.picture) to paint the different graphics on the bitmap then save it, copy it to the clipboard, or print it as you need.
« Last Edit: April 09, 2020, 04:37:12 am by eljo »

bobkos

  • New Member
  • *
  • Posts: 32
    • Personal Finance Manager
Re: Capturing a Panel inside ScrollBox
« Reply #6 on: April 09, 2020, 08:15:56 am »
Some time ago I've wrote the following function:

Code: Pascal  [Select][+][-]
  1. function ScrollBox2Bmp(const ExportArea:THandle;ScrollArea:TScrollBox;ReportFile:string;CompressFile:boolean):boolean;
  2. var
  3.   ScrollStep:integer;
  4.   MySCRcap:THandle;
  5.   bmp,buff:TBitmap;
  6.   SourceRect,DestRect:TRect;
  7.   jpg:TJPEGImage;
  8. begin
  9.   Result:=True;
  10.   ScrollStep:=ScrollArea.ClientHeight;
  11.   ScrollArea.VertScrollBar.Position:=0;
  12.   ScrollArea.Refresh;
  13.   buff:=TBitmap.Create;
  14.   bmp:=TBitmap.Create;
  15.   MySCRcap:=GetDC(ExportArea);
  16.   buff.LoadFromDevice(MySCRcap);
  17.   ReleaseDC(ExportArea,MySCRcap);
  18.   bmp.Assign(buff);
  19.   repeat
  20.     if ScrollArea.VertScrollBar.Position+ScrollStep >= ScrollArea.VertScrollBar.Range-ScrollArea.ClientHeight then repeat
  21.       dec(ScrollStep,1);
  22.     until ScrollArea.VertScrollBar.Position+ScrollStep <= ScrollArea.VertScrollBar.Range-ScrollArea.ClientHeight;
  23.     ScrollArea.VertScrollBar.Position:=ScrollArea.VertScrollBar.Position+ScrollStep;
  24.     ScrollArea.Refresh;
  25.     MySCRcap:=GetDC(ExportArea);
  26.     buff.LoadFromDevice(MySCRcap);
  27.     ReleaseDC(ExportArea,MySCRcap);
  28.     bmp.Height:=bmp.Height+ScrollStep;
  29.     SourceRect:=Rect(0,buff.Height-ScrollStep,buff.Width,buff.Height);
  30.     DestRect:=Rect(0,bmp.Height-ScrollStep,bmp.Width,bmp.Height);
  31.     bmp.Canvas.CopyRect(DestRect,buff.Canvas,SourceRect);
  32.   until (ScrollArea.VertScrollBar.Position >= ScrollArea.VertScrollBar.Range-ScrollArea.ClientHeight);
  33.   FreeAndNil(buff);
  34.   bmp.Width:=ScrollArea.ClientWidth;
  35.   jpg:=TJPEGImage.Create;
  36.   jpg.Assign(bmp);
  37.   jpg.CompressionQuality:=CompressRatio;
  38.   try
  39.     if CompressFile then jpg.SaveToFile(ReportFile) else bmp.SaveToFile(ReportFile);
  40.   except
  41.     Result:=False;
  42.   end;
  43.   FreeAndNil(jpg);
  44.   FreeAndNil(bmp);
  45.   ScrollArea.VertScrollBar.Position:=0;
  46.   ScrollArea.Refresh;
  47. end;
  48.  

I believe you can try to use it.

zeljko

  • Hero Member
  • *****
  • Posts: 1591
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: Capturing a Panel inside ScrollBox
« Reply #7 on: April 09, 2020, 09:14:38 am »
Hi there,

I want to save a Panel to image but the saved image has a part in black.
The scrollbox is hidding the rest of the Panel.

How can I take a screen shot of the whole panel?

See attached gif. Thanks a lot.

Used code:
Code: Pascal  [Select][+][-]
  1. var
  2.   bmp: TBitmap;
  3.   d:THandle;
  4. begin
  5.   d:=GetDC(Panel1.Handle);
  6.   bmp := TBitmap.Create;
  7.   bmp.Width := Panel1.Width;
  8.   bmp.Height := Panel1.Height;
  9.   bmp.LoadFromDevice(d);
  10.   bmp.SaveToFile('C:\Users\Username\Desktop\test.bmp');
  11.   bmp.Free;
  12.   ReleaseDC(Panel1.Handle, d);

Try with Panel1.PaintTo(). Don't know what widgetset you use, but under qt/qt5 everything works fine with PaintTo() and LoadFromDevice().
Note that LoadFromDevice() takes screenshoot of control, so if it's obscured by some other window you'll get garbled output.

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Capturing a Panel inside ScrollBox
« Reply #8 on: April 09, 2020, 01:04:23 pm »
Its best to have a background image.

In the end you'll go this way.. ;)

The Display wasn't designed to be used this way.

if you were doing gaming/GL stuff then you would have buffers of the image but this leads us back to just using a Timage or a background TBitmap to contain your image you display in the panel
The only true wisdom is knowing you know nothing

SaraT

  • Full Member
  • ***
  • Posts: 121
  • A little student
Re: Capturing a Panel inside ScrollBox
« Reply #9 on: April 09, 2020, 06:54:36 pm »
Try with Panel1.PaintTo(). Don't know what widgetset you use, but under qt/qt5 everything works fine with PaintTo() and LoadFromDevice().
Note that LoadFromDevice() takes screenshoot of control, so if it's obscured by some other window you'll get garbled output.

Hi @zeljko, it worked like a charm with PaintTo(). No more missing part even if the window is smaller than scrollbox.
Below the final code.

Many thanks guys, for all your help.

Code: Pascal  [Select][+][-]
  1. bmp := TBitmap.Create;
  2. bmp.Width := Panel1.Width;
  3. bmp.Height := Panel1.Height;
  4. Panel1.PaintTo(bmp.Canvas,0,0);
  5. bmp.SaveToFile('C:\Users\Username\Desktop\test.bmp');
  6. bmp.Free;

 

TinyPortal © 2005-2018