• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 386
  • Last Modified:

[QUESTION] TForm(fStayOnTop) and TPicture weird behavior

Hi everyone,

i have a strange problem (i've a workaround but...) involving in appearance order : Delphi7 Enterprise, a TForm and a Timage component.

i set my FormStyle as fsStayOnTop. i put a TImage component on my form and add the JPEG unit in the uses clause.

When i load an image for the first time (with the form shown on screen), everything goes fine, my jpeg picture is loaded and displayed with no error.

Then, when i load another picture, i got a violent 'Access Violation' with the TPicture.loadfromfile at this place :

procedure TPicture.LoadFromFile(const Filename: string);
  Ext: string;
  NewGraphic: TGraphic;
  GraphicClass: TGraphicClass;
  Ext := ExtractFileExt(Filename);
  Delete(Ext, 1, 1);
  GraphicClass := FileFormats.FindExt(Ext);
  if GraphicClass = nil then
    raise EInvalidGraphic.CreateFmt(SUnknownExtension, [Ext]);

  NewGraphic := GraphicClass.Create;
    NewGraphic.OnProgress := Progress;
    NewGraphic.LoadFromFile(Filename);     <=== AccessViolation Here !
  FGraphic := NewGraphic;
  FGraphic.OnChange := Changed;

after several hours of debugging, a lot of cup of coffee, i've found a workaround setting the form as normal and using the SetForegroundWindow function...

But it's not very satisfying...

So if anyone has an explanation... just listening...

thanks in advance,

best regards,


ps: setting 125 points for it, as it's not, for the moment very important, but i think it might not be very easy to find the solution...
  • 3
  • 3
1 Solution
fsurferAuthor Commented:
After some more debugging sessions, it appears that my workaround 'SetForegroundWindow' API call is producing the same error.

it seems that when a TImage Component is on a form which is either with the fsStayOnTop's FormStyle or in the foreground using SetforegroundWindow, you can't load another picture once one is loaded...

am i doing something wrong or has anyone reproduced this ?

thanks in advance,

best regards,

Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
in my d7 test (on W2K sp4) nothing's wrong....wich is your os? and how are you loading the new image....
post a little more code....
fsurferAuthor Commented:
hi Ferrucio,

thanks for your answer.

Effectively, nothing was wrong.

in fact, it's my mistake. Here's why :
In the FormClose event, i was setting Action to caFree. BUT, the Form variable was not freed except that the Canvas was freed. So, when reusing the form to display another image, i had an error when it was trying to load it.

here're parts of my code :

FormClose event :
procedure TfrmGrandEcran.FormClose(Sender: TObject;  var Action: TCloseAction);
       ... MyStuff ...

Elsewhere in my code when reusing the form :

... my stuff ...
if Assigned(frmGrandEcran) then
    frmGrandEcran.Image1.LoadFromFile('myimage.jpg'); <= here the access violation triggered.

And in fact, everything is normal (everything on the form is freed and destroyed) except the form itself !

but i'll give you the points any way... some may know why...

Thanks again for your interest !

best regards,

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
Many thanks to you...i really got a present with this :)
SO now let's see why it appens:

From delphi help:
When you call Free for a component, it calls Free for all components that it owns—that is, all components in its component list. Since a form owns all the controls and nonvisual components that are created on it in design mode, those components are automatically freed when the form is freed. By default, all forms are owned by the Application object....

Because you have stored a variable pointed to the form in the app. then the allocated memory for that variable will be realased just on freeing the Application (closing it), so freeing a form, it never will become nil.
So how to workaround it?
Well, let's create the form and then, after using it, let's release its memory...

if form2 = nil then
form2 := Tform2.create(form2);

Just to justify your points assignment :)

F68 ;-)  
fsurferAuthor Commented:

In order to go a bit farer than your sample and getting close to what i've done, in your TForm2 OnClose event, put the following code :

... your stuff ...

In my opinion, you should get an error message on your 'FreeAndNil(form2)'.

(sorry, don't have time to test it, but that's waht i have done, and there was my mistake)

Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
yes of course, in that case you'd try to re-free a destroyed form so an exception should be raised....
cafree just destroy all child components and itself, but doesn't realase  the allocated memory...
so the correct way is to let close the form without any CloseAction options and free-release it from application....
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.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now