TImage problem

TImage problem

How to put components to TImage and save them as picture file, if components are hided (on TForm) or visible:=false ?

Thank You.
zuipoAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

DeerBearCommented:
Hi,

To do this you need to get a snapshot of the control, not an easy task.
Looking into JCL sources, you will find a ScreenShot routine that you can use as a base to derive your own code.

HTH,

Andrew
0
zuipoAuthor Commented:
Thank You, DeerBear !

Can You give me example for screenshot.

I tried :

screenshot(Image1.Picture.Bitmap,0,0,100,100,BitBtn1);

and Delphi shows me this error :

[Error] Unit1.pas(29): There is no overloaded version of 'ScreenShot' that can be called with these arguments
0
Pierre CorneliusCommented:
The problem is that various controls have different ways of rendering themselves on the screen. e.g. Descendents of TWinControl could have a PainTo method which you can use to paint to any canvas but even this I couldn't get working properly. When using this method on a TEdit for example, it painted the edit box, but not the text inside it.

I reckon your best bet is to let the controls draw themselves (they know their individual ways of how to do it) and then capture the screen.

I've put together a new form class for you that can do this. It captures the entire screen when you close the form, but you could customise it to capture each control in a separate bitmap if you wish simply modify the BitBlt function parameters accordingly using the controls Top, left, width and height properties.

To do:
1.) Create a new application
2.) drop a TButton on it and assign the following to its OnClick event:
         
            procedure TForm1.Button1Click(Sender: TObject);
            begin
                  with TShowInvisibleControls.Create(self) do Show;
            end;

3.) Add the following to your units type declaration interface:

  TShowInvisibleControls = class(TCustomForm)
  private
    procedure Show;
    procedure Showmodal; reintroduce;
  public
    constructor Create(AOwner: TForm); reintroduce;
    procedure DoOnClose(Sender: TObject; var Action: TCloseAction);
  end;

4.) Add the following to your implementation section of the unit:

{ TShowInvisibleControls }

constructor TShowInvisibleControls.Create(AOwner: TForm);
begin
  //no different, only enforcing a TForm as the owner
  CreateNew(AOwner);
  Caption:= 'Invisible Controls on Form:' +TForm(AOwner).Name;
  Width:= TForm(Owner).Width;
  Height:= TForm(Owner).Height;
  Position:= poDesktopCenter;
  OnClose:= DoOnClose;
end;

procedure TShowInvisibleControls.Show;
begin
  //only allow modal state because controls parents must be
  //reset to the owner when finished
  ShowModal;
end;

procedure TShowInvisibleControls.Showmodal;
var i: integer;
    InvisibleControls: array of TControl;
begin
  //get the invisible controls
  for i:= 0 to TForm(Owner).ControlCount-1 do
  begin
    if (NOT TForm(Owner).Controls[i].Visible) then
    begin
      SetLength(InvisibleControls, Length(InvisibleControls)+1);
      InvisibleControls[Length(InvisibleControls)-1]:= TForm(Owner).Controls[i];
    end;
  end;

  try
    //Become parent for the invisible controls
    for i:= low(InvisibleControls) to High(InvisibleControls) do
    begin
      InvisibleControls[i].Parent:= self;
      InvisibleControls[i].Visible:= true;
    end;

    inherited ShowModal;

  finally
    //reset controls parent to the owner
    for i:= low(InvisibleControls) to High(InvisibleControls) do
    begin
      InvisibleControls[i].Visible:= false;
      InvisibleControls[i].Parent:= TForm(Owner);
    end;
    Free;
  end;

end;


procedure TShowInvisibleControls.DoOnClose(Sender: TObject; var Action: TCloseAction);
var SaveDlg: TSaveDialog;
    bmp: TBitmap;
begin
  SaveDlg:= tSaveDialog.Create(self);
  SaveDlg.Filter:= 'Bitmap *.bmp|*.bmp';
  if SaveDlg.Execute then
  begin
    bmp:= TBitmap.Create;
    bmp.Width:= self.ClientWidth;
    bmp.Height:= self.ClientHeight;
    BringToFront;
    Repaint;
    bitblt(bmp.Canvas.Handle, ClientRect.Left, ClientRect.Top,
           ClientWidth, ClientHeight, self.Canvas.Handle,
           0,0, SRCCOPY);
    bmp.SaveToFile(SaveDlg.FileName);
    bmp.Free;
  end;
  SaveDlg.Free;
end;


One thing I haven't built in is the fact that the controls viewed in the new derived form are live and working. You should consider disabling them to prevent the user from doing anything to or with them.


Kind regards
Pierre Cornelius
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
zuipoAuthor Commented:
OK. Thank You.

I'll give all points to

PierreC.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.