tags:

views:

452

answers:

6

I've been sharing image lists across multiple forms in Delphi for years now. I have a TImageList on the main form of my app and then I have other forms that have components where I set the Images property to the image list from the main form (e.g. MyMainForm.MyImageList) at design time.

The problem I'm having is that randomly the Images property gets cleared on those forms that reference the image list on the main form.

This seemed to have only start recently, but I haven't been able to pinpoint the exact cause yet. I can't seem to find a way to reproduce the issue at will; it just seems to happen randomly. I did notice it happens right when a form is opened.

One thing that I did change recently in Delphi is I enabled the Autosave Project desktop and symbols feature. So now when I open this project it always remembers what forms were open. So because this issue happens when a form is opened, and because it now reopens all forms that were opened the last time the project was opened, it happens more often.

We have a few developers working on this project, and we are using SVN for version control. One issue that enabling the Autosave Project desktop and symbols feature has led to is that when we do an SNV update on the project, the symbol file can become invalid (because we don't have the symbol file under version control). This just leads to an error message from Delphi, but other than that it seems harmless. We just recompile the project and it fixes the symbol file.

Btw, I'm using Delphi 7.

If you have questions or want clarifications, leave a comment, and I'll update the question.

+5  A: 

When I encountered this type of behaviour, it was always because I'd opened the "other" form without the main form open in the IDE... the IDE would try to resolve the MyMainForm.MyImageList reference, fail, and remove the reference.

We worked around this by manually assigning the imagelist in code (usually in AfterConstruction).

moobaa
So it does resolve the issue if I set the Images property in the AfterConstruction method of the form, but when I do it that way, I can't see the images at design time (on a toolbar, for example, that references the image list). Any solution for that?
Liron Yahdav
Well, you can set it at Design time (if MyMainForm's open, of course) and design as normal; the AfterConstruction just ensures the property remains set. A safeguard, if you will.
moobaa
This won't change the wrong designtime behaviour...
AhmetC
+3  A: 

Ah - and the "AutoSave Project desktop" feature will sometimes open files (and, hence, forms) in "reverse" order - exacerbating the IDE-doesn't-know-about-MyMainForm "feature".

moobaa
Yes, if you read my answer, you'll see I worked around this issue by disabling AutoSave. What's strange though is that even w/AutoSave disabled, I can still reproduce the issue in my main project, but not in a brand new project (see my answer for more).
Liron Yahdav
A: 

I did a bunch of experimenting with some really weird results. But I did make some changes so I can work on my project without this issue occurring. I had to disable the AutoSave feature (this prevents secondary forms which may reference the main form from opening up before the main form). Then I had to make sure to delete the .dsk file of the project (the project desktop AutoSave file). So now when I open up the project it always opens the main form, so I never get the issue of references to the main form getting cleared. But I do still get the issue if after opening the project I close the main form and then open a form that references the main form.

Also I was unable to reproduce this issue of references to another form getting cleared in a brand new project with the AutoSave feature disabled, even though I can reproduce it w/AutoSave disabled in my current project. I have no idea why, but I don't feel like this is worth investigating further.

Below is the data on some of my experiments performed on my existing project. WORKS means the reference to the main form is fine. BUG means the reference to the main form got cleared. This was done w/AutoSave on and always closing all forms manually before I closed the project.


  1. Open project
  2. Open main form
  3. Open secondary form
  4. Result: WORKS


  1. Open project
  2. Open secondary form
  3. Result: BUG


  1. Open project
  2. Open main form
  3. Close main form
  4. Open secondary from
  5. Result: BUG


  1. Open project
  2. Open Secondary form
  3. Result: BUG
  4. Set Images property of component on secondary form to image list on main form
  5. Close secondary form
  6. Open secondary form
  7. Result: WORKS ("caches" reference for the secondary form only; see below for "caches" explanation)


  1. Open project
  2. Open magic form (see below for what a "magic" form explanation)
  3. Result: WORKS ("caches" any reference to main form for all forms; see below for "caches" explanation)


Other interesting findings:

  • When you open up the form and the image list does not show up, the .dfm is modified however delphi does not say that the file is modified (e.g. if you close the form it won't warn you about unsaved changes). Only once you press save on the form will the dfm clear the imagelist reference.
  • I noticed there are some "magic" forms in my project (for lack of a better term). Magic forms reference my project's main form in their .dfm and they don't lose their references to the main form after you Open them, even if they are opened before any other form.
  • These magic forms cause the "caching" of all image list references from the main form. Once you open one of these forms, then you can open up any form that references the main form, and it won't lose it's references during this project session (even if the magic form is then closed).
Liron Yahdav
+1  A: 

Do you have mainform.pas included in project? Not only as "uses mainform.pas" somewhere in .pas, but as

  fMainForm in 'fMainForm.pas' {MainForm},

in your Application**.dpr**. That comment {MainForm} is necessary for Delphi - for resolving inherited forms and links between them.

DiGi
I do have the main form included in the project and it has that comment that's necessary for Delphi.
Liron Yahdav
+2  A: 

I put kind of shared things to Datamodules instead of forms. Try with this way.

AhmetC
Thanks, this gave me the clue I needed to fix the issue. Jan's post gives more detail, so I marked it as the answer.
Liron Yahdav
+3  A: 

I ran into the same problem many years ago. Ever since, I've had the habit of putting image lists that are shared by several forms onto a TDataModule. Then Delphi doesn't lose the link. Putting non-visual components on data modules also reduces design time clutter on your forms. At runtime, the TDataModule is instantiated before the main form.

Jan Goyvaerts
Thank you very much. This fixed all my problems!
Liron Yahdav