Link to home
Start Free TrialLog in
Avatar of d32coder
d32coder

asked on

TImage

My app uses a 800x600 TImage as a background.  It's loaded at design time so I assume the data is in my res file.

When the form is shown the first time, the controls in the foreground appear before the Image in the background (loading time?)

How can I paint the image to the form before its first OnShow event?

Don
Avatar of cubud
cubud
Flag of United Kingdom of Great Britain and Northern Ireland image

Are you in 256 colour resolution ?
I saw this problem when Delphi had to map the image to the current palette.  If so I don't know of a solution.

Have you tried setting Form1.DoubleBuffered := True in the OnCreate method ?

Pete
====
http://www.HowToDoThings.com (Articles)
http://www.Stuckindoors.com/delphi (Open source)
Avatar of Stuart_Johnson
Stuart_Johnson

Could you paint the bitmap to the form's canvas?
I haven't checked yet, but if the dbl buffer thing doesn't work I'd try painting it yourself.  Catch the WM_PAINT message, draw the image to your form, then call inherited.  I'm not sure if that'll just draw over your image in silver though.  Have to get back to you later

GL
Mike
if your image is the forms background, why not paint the form in the paint background message ?
 
procedure WMEraseBkgnd (var Msg : TMessage); message WM_ERASEBKGND;

be sure NOT to call inherited
Hi,
Select the image in design mode, right-click on it and select 'Send To Back' from the popup menu. It could solve your problem.

Regards ,Geo
Avatar of d32coder

ASKER

I'd rather try to paint the TImage before the form shows, perhaps even while loading the forms during Application.Initialize;

I'd like to keep the TImage component rather than painting the actual form as the TImage size controls the Form size while Form.AutoSize = TRUE

Points increased.

Don
you cannot show the image during the application.initialize step because the image
needs a parent and that parent is created after the  Application.CreateForm(TForm1, Form1);
step.

a possible solution is to create the image with the mainform as parent
and to put all other controls that should not be seen in a panel. i guess you already
did something like that. during the start that panel is invisible and only the picture is seen.
during the onshow start a timer. after .5 seconds or so that timer sets the visibility of the panel
to TRUE and sets that panel as parent of the background image.

maybe you need a sendtoback so that the image is behind the buttons, but that should be
before you set the visibility.

fred
another posibility is to create a second form that shows only that image
show it at first and create the rest in the background

fred
If you use the TCanvas StretchDraw you can draw the image on the entire form client area, it would look just like a TImage with AutoSize = true.

As Slick812 was saying, catch the WM_ERASEBKGND message and do like this:

procedure TForm1.WMEraseBkgnd(var Msg : TMessage);
begin
  Form1.Canvas.StretchDraw(Rect(0, 0, ClientWidth, ClientHeight), BgImg);
end;

GL!
Correction: it would look just like a TImage with Stretch = true.
Hi, just an idea,
could you simply set all controls Visible to False at design time and set back to True in a loop at runtime when the form is first shown?
ASKER CERTIFIED SOLUTION
Avatar of Fraction
Fraction

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
here is some code I have used to get an Image as the forms background. I put the Background bitmap (BACKPIC in res file) in a .RES file compiled into the app.

  private
    { Private declarations }
    BackBmp: TBitmap;
    procedure WMEraseBkgnd (var Msg : TMessage); message WM_ERASEBKGND;

procedure TForm1.FormCreate(Sender: TObject);
var
ResHandle : THandle;
ResStm : TResourceStream;
begin
ResHandle := FindResource(hInstance, 'BACKPIC', 'BMP');
if (ResHandle <> 0) then
  begin
  ResStm := TResourceStream.Create(hInstance, 'BACKPIC', 'BMP');
  BackBmp := TBitmap.Create;
  BackBmp.LoadFromStream(Res);
  ResStm.Free;
{if this Form is a NON-changable size set the Client
size to the bitmap size to insure form border with
variations don't skew the client fit
  ClientWidth := BackBmp.Width;
  ClientHeight := BackBmp.Height;}
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FreeAndNil(BackBmp);
end;

procedure TForm1.WMEraseBkGnd;
begin
{do NOT call Inherited}
{I use API here so I can use the WParam HDC for drawing
and not have to worry about a Canvas,
the WParam HDC is created and freed by Windows OS}

{use BitBlt if your form is a FIXED size
BitBlt(Msg.WParam, 0, 0, BackBmp.Width, BackBmp.Height,
      BackBmp.Canvas.Handle, 0, 0, SRCCOPY);}

{use StretchBlt if your form is resizable, this works
well except in extream stretches}
StretchBlt(Msg.WParam,     // handle of destination device context
    0,     // x-coordinate of upper-left corner of dest. rect.
    0,     // y-coordinate of upper-left corner of dest. rect.
    Form1.ClientWidth,     // width of destination rectangle
    Form1.ClientHeight,     // height of destination rectangle
    BackBmp.Canvas.Handle,     // handle of source device context
    0,     // x-coordinate of upper-left corner of source rectangle
    0,     // y-coordinate of upper-left corner of source rectangle
    BackBmp.Width,     // width of source rectangle
    BackBmp.Height,     // height of source rectangle
    SRCCOPY      // raster operation code
   );
Msg.Result := 1;
{hint - you can also "tile" a smaller bitmap to fill the Form as already sugessted}
end;
 - - - - - - - - - - - - - - - - - - - - -  - --

this will make the backpic fit the forms client size and won't overdraw controls
let me know
after thought - - It's been a while since I used a TImage as a form background, but if I remember, a TImage will overdraw non-window controls placed on the form before the TImage (creation order as form placement order), you might try selecting the disapearing control and then "Cut" it in the Edit menu. The focus will jump to another control, go to the Object Inspector and get Form1 (MainForm) to have focus, then "Paste" the control back on the form. I think this will have that control drawn After TImage in the creation. (or you could edit the .dfm file to change creation order) I don't think the Z order does much in the creation painting.

And if you are using a 24bit 800x600 bitmap as background then you can save alot of app Kbs if you jpg it and include jpegs in your uses, then decompress it to a bitmap.
Slick812: It would be easier for d32coder to do what I said earlier, i.e. send the image to back instead of cutting and pasting all controls on the form.

d32coder: have you tried my proposal? No additional painting code is required in this case.

Regards, Geo
Geobul

The SendtoBack thing is default, how does that affect the painting order?  I did send it back but it was already there with no appreciable change.


I am using a JPEG in the TImage but I think its the decoding that causing the delay.  Since size is not a concern, would a bmp be faster?

Jpeg is compressed and must be "decoded", bmp is much larger and needs load longer, so I think it would not make that much difference, if you're not running on a really slow computer.
Here's what I'm really looking for...

The delay in showing the image only occurs the first time the form is displayed, subsequent Form.Visible := TRUE doesn't have the delay.  My assumption is the the image data is buffered in RAM after the first display and therefore much faster.  I would like to accomplish this 'buffering' prior to the first display, perhaps in the Form.OnCreate event.

Ideas?

Points Increased.
In the Forms OnShow event put some code to repaint the vanishing controls. The OnShow is called after the form has been created, so repainting (or Invalidate) should show them. I still think you should use the WMEraseBkGnd; event, your TImage as a background is like painting a wall, you build a Canvas cover (TImage) over the wall and paint that, which covers the doors and windows, when you can just paint the wall with WMEraseBkGnd;
Thanks for all the comments.  I do appreciate the effort all of you have put into this thread.

Let me try to clarify.  The controls aren't being hidden by the TImage, the controls show up fine, they just show up first.  

Example, as the Form is being shown for the first time, I see the gray background and the controls, and about one second later the Image (background) is painted.  

It only happens the first time each form is shown  (there are about 5).  I want to paint the image BEFORE the controls.  Can I force the form to show the TImage first?  I want to avoid the ugly gray background from showing.  Perhaps I can the paint the TImage while the form is still invisible.  None of these forms are the MainForm so I have time to paint before making Form2.Visible := TRUE;

If I cant do this I will probably go with Fraction's Form Canvas painting though it would require alot of re-coding on an app that is nearly complete.

I hope I have been more descriptive about the problem and again, thanks for the help.  

Don
are you sure you have the
  backgroundimage.Picture.LoadFromFile('.\mybackground.bmp');
line in the form.create events?

normally this should be enough.

one other thing you could try is to load the image during designtime
(so the exe is bigger but the image should be there at the same time as the buttons)
I do load the image at design time, which is why I don't understand the delay in displaying it.  My processor and RAM are sufficient to avouid the delay.  Still pondering.

Thanks for the comments.  Still trying to solve it.

Don
In the past I haved same problem in one of my programs .
I solved then with a panel who can tile a bitmap inside it .  If you can't find one on net I can send a copy to you .

Now I use Billenium Effects - solve this problem . Very good components ( flicker free and with COOOOL controls transition effects ).
Unfortunatelly is not freeware . But I think that deserve any dolar .
If you try the panel way allign to client the panel and copy all others in it .