Forum > LCL

Saving form contents as image partially

<< < (2/2)

Zoran:
Only now I understand what you actually asked, sorry.

I beleive that this is what you want:


--- Code: ---uses
  ...,  LCLIntf, LCLType;

...

procedure TForm1.Button2Click(Sender: TObject);
var
  MyBitmap, MyBitmap2: TBitmap;
  MyDC: HDC;
  R: TRect;
begin
  MyBitmap2 := TBitmap.Create;
  MyBitmap := TBitmap.Create;
  try
    MyDC := GetDC(Self.Handle);
    try
      MyBitmap.LoadFromDevice(MyDC);

    finally
      ReleaseDC(Self.Handle, MyDC);
    end;

    R.TopLeft := Image1.BoundsRect.TopLeft;
    R.BottomRight := Panel1.BoundsRect.BottomRight;

    MyBitmap2.Width := R.Right - R.Left;
    MyBitmap2.Height := R.Bottom - R.Top;

    MyBitmap2.Canvas.CopyRect(Rect(0, 0, MyBitmap2.Width, MyBitmap2.Height),
                                      MyBitmap.Canvas, R);
    MyBitmap2.SaveToFile('ImageAndPanel.bmp');
  finally
    FreeAndNil(MyBitmap);
    FreeAndNil(MyBitmap2);
  end;
end;

--- End code ---

Leledumbo:
Thanks, Zoran. I implemented it more or less the same as you do, except that I use ControlToScreen to get screen coordinates of the image and panel.

However, after trying it myself I conclude that taking screenshot and CopyRect-ing it isn't a good idea. I ask the user for a filename before saving it, and it tries to get the screenshot before the save dialog really closes, so the dialog is included in the image. The temporary solution is to call Sleep() with some value (currently 500) before LoadFromDevice(), this will give (enough?) time for the dialog to close. If anyone has a better idea, please tell me.

Zoran:

--- Quote from: Leledumbo on April 06, 2010, 04:18:07 am ---Thanks, Zoran. I implemented it more or less the same as you do, except that I use ControlToScreen to get screen coordinates of the image and panel.

However, after trying it myself I conclude that taking screenshot and CopyRect-ing it isn't a good idea. I ask the user for a filename before saving it, and it tries to get the screenshot before the save dialog really closes, so the dialog is included in the image. The temporary solution is to call Sleep() with some value (currently 500) before LoadFromDevice(), this will give (enough?) time for the dialog to close. If anyone has a better idea, please tell me.

--- End quote ---

I found a solution, you must call Application.ProcessMessages.

This works:

--- Code: ---procedure TForm1.Button1Click(Sender: TObject);
var
  MyBitmap, MyBitmap2: TBitmap;
  MyDC: HDC;
  R: TRect;
  S: String;
begin
  if InputQuery(Application.Title, 'Your password:', True, S) then begin
    if S = 'pass' then begin
      Application.ProcessMessages;
      MyBitmap2 := TBitmap.Create;
      MyBitmap := TBitmap.Create;
      try
        MyDC := GetDC(Self.Handle);
        try
          MyBitmap.LoadFromDevice(MyDC);

        finally
          ReleaseDC(Self.Handle, MyDC);
        end;

        R.TopLeft := Image1.BoundsRect.TopLeft;
        R.BottomRight := Panel1.BoundsRect.BottomRight;

        MyBitmap2.Width := R.Right - R.Left;
        MyBitmap2.Height := R.Bottom - R.Top;

        MyBitmap2.Canvas.CopyRect(Rect(0, 0, MyBitmap2.Width, MyBitmap2.Height),
                                          MyBitmap.Canvas, R);
        MyBitmap2.SaveToFile('ImageAndPanel.bmp');
      finally
        FreeAndNil(MyBitmap);
        FreeAndNil(MyBitmap2);
      end;

    end else
      ShowMessage('Wrong password');

  end;
end;

--- End code ---

The password dialog is not actually removed from screen (and the main form is not repainted yet) until the Application.ProcessMessages is called.

It gets called automaticaly AFTER the buttons message handler, but you need to call it before taking the screenshot, so the solution is rather simple -- call it manually!

Navigation

[0] Message Index

[*] Previous page

Go to full version