Solved

TImage

Posted on 2001-09-16
24
697 Views
Last Modified: 2010-04-06
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
0
Comment
Question by:d32coder
  • 5
  • 4
  • 4
  • +7
24 Comments
 
LVL 3

Expert Comment

by:cubud
ID: 6485971
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)
0
 
LVL 6

Expert Comment

by:Stuart_Johnson
ID: 6486294
Could you paint the bitmap to the form's canvas?
0
 
LVL 6

Expert Comment

by:edey
ID: 6486303
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
0
 
LVL 33

Expert Comment

by:Slick812
ID: 6486584
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
0
 
LVL 17

Expert Comment

by:geobul
ID: 6486862
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
0
 

Author Comment

by:d32coder
ID: 6487378
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
0
 
LVL 3

Expert Comment

by:gandalf_the_white
ID: 6487479
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
0
 
LVL 3

Expert Comment

by:gandalf_the_white
ID: 6487483
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
0
 
LVL 1

Expert Comment

by:Fraction
ID: 6487528
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!
0
 
LVL 1

Expert Comment

by:Fraction
ID: 6487576
Correction: it would look just like a TImage with Stretch = true.
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 6488006
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?
0
 
LVL 1

Accepted Solution

by:
Fraction earned 300 total points
ID: 6488123
I just tested how to do a tiled background form, dono if that's what your interested in, but I post it here anyway.


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure WMEraseBkgnd(var Msg : TMessage); message WM_ERASEBKGND;
    procedure FormDestroy(Sender: TObject);
  private
    BgImg: TBitmap;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  BgImg := TBitmap.Create;
  BgImg.LoadFromFile('c:\Windows\DeepBlue.bmp');
end;

procedure TForm1.WMEraseBkgnd(var Msg : TMessage);
var
  Bmp: TBitmap;
  srcX, dstX, srcY, dstY: integer;
  srcSL, dstSL: pByteArray;
  i: integer;
begin
  Bmp := TBitmap.Create;
  Bmp.Width := ClientWidth;
  Bmp.Height := ClientHeight;
  Bmp.PixelFormat := pf24bit;
  srcY := 0;
  for dstY := 0 to Bmp.Height-1 do begin
    srcSL := BgImg.ScanLine[srcY];
    dstSL := Bmp.ScanLine[dstY];
    srcX := 0;
    for dstX := 0 to Bmp.Width-1 do begin
      for i := 0 to 2 do dstSL[(dstX * 3)+i] := srcSL[(srcX * 3)+i];
      inc(srcX);
      if srcX>=BgImg.Width then srcX := 0;
    end;
    inc(srcY);
    if srcY>=BgImg.Height then srcY := 0;
  end;
  Form1.Canvas.Draw(0, 0, Bmp);
  Bmp.Free;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  BgImg.Free;
end;

end.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 33

Expert Comment

by:Slick812
ID: 6488190
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
0
 
LVL 33

Expert Comment

by:Slick812
ID: 6489084
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.
0
 
LVL 17

Expert Comment

by:geobul
ID: 6489599
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
0
 

Author Comment

by:d32coder
ID: 6490058
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?

0
 
LVL 1

Expert Comment

by:Fraction
ID: 6490311
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.
0
 

Author Comment

by:d32coder
ID: 6490739
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.
0
 
LVL 33

Expert Comment

by:Slick812
ID: 6491051
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;
0
 

Author Comment

by:d32coder
ID: 6491140
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
0
 
LVL 3

Expert Comment

by:gandalf_the_white
ID: 6499184
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)
0
 

Author Comment

by:d32coder
ID: 6499637
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
0
 
LVL 9

Expert Comment

by:ginsonic
ID: 6503344
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 .
0
 
LVL 9

Expert Comment

by:ginsonic
ID: 6503357
If you try the panel way allign to client the panel and copy all others in it .
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now