Delphi issue with sharing Image Lists across forms - delphi

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.

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.

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).

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".

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

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.
Open project
Open main form
Open secondary form
Result: WORKS
Open project
Open secondary form
Result: BUG
Open project
Open main form
Close main form
Open secondary from
Result: BUG
Open project
Open Secondary form
Result: BUG
Set Images property of component on secondary form to image list on main form
Close secondary form
Open secondary form
Result: WORKS ("caches" reference for the secondary form only; see below for "caches" explanation)
Open project
Open magic form (see below for what a "magic" form explanation)
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).

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.

Related

LiveBindings work in Designtime, but not RunTime

I am working on my first multi-platform app for Windows and MacOSX. I decided to go with SQLite, and a StringGrid to check connectivity. I have placed all necessary components on the form from looking at an SQLite Sample that came with Delphi 10.0.
I ran the LiveBindings Wizard connecting my FDTable to the StringGrid just fine. I can activate the table and it displays my data (imported from a BatchMove), see attachment. But when I run the app, connect my FDConnection and my Table, the grid doesn't get populated. What am I missing?
I am facing this problem.
Dataset sometimes lose value at runtime.
I solved this shortcoming with a line of code after the opening of such datasets
BindSourceGPS.DataSet:=TransTable;
Grigore
Sorry folks. Answered my own question. I had everything on a Dataform and that was being created first. I thought I had it running, but all of the examples I was looking at the data components were kept on the main form. And since I can hide non-visible components, I moved everything to the main form.
But, I forgot to change the form creation order. Moved the main form to be created first and Whala. Everything is working. Still not sure why having the data components and livebinding on separate forms worked in preview but not while running, but everything on one form, created first works just fine for me.

How to make Delphi re-save all forms?

After a component upgrade, some of its properties are stored differently, but only the next time the form is saved. This means that when I then edit a form that was last saved while still using the previous version of the component, in the VCS my actual changes are obscured by differences that result from the component upgrade. I could split them up into separate commits, but then I need to be on the lookout for these artifacts all the time and the effects of the component upgrade would scatter across the repository's history. Instead, I would like to have these changes bundled in a single commit right after I upgraded the component.
To make this happen, I need to force Delphi to re-save (generate) all forms in a project (group) even though no changes were made in the editor, so that the only file changes will be caused by the component upgrade. So far I did not even manage to make this happen for a single form without opening it, making a change and reverting it - the IDE seems to minimize writing to disk; just Save All without touching all units doesn't cut it. In the end I need to do it for as many forms at once as possible and opening them all in the editor isn't going to work because there are hundreds of them... I could write some AutoIt script to do everything I'd do by hand, but I hope there is some clever way that doesn't involve scripting the IDE.
(Just to remove this question from a list of unanswered questions)
Use DFMCheck, as Andreas Hausladen says in comments:
http://idefixpack.de/blog/ide-tools/dfmcheck (originally was at http://andy.jgknet.de/blog/ide-tools/dfmcheck)

Delphi .exe after build error

good day! i have a project and it runs perfectly, i did that project 3 months ago. Then, i tried to put some changes and even BUILD ONLY the project (no additional codes). When i open the .EXE it appears errors like this.
when i clicked DON'T SEND
and when i clicked OK
When i opened the form this message appers:
How to fixed it? I really need to add some functions to that project.
Thanks in advance!
Your .dfm file refers to a property that is not published by the component which is being streamed. The streaming framework is attempting to read into a property named Quality of an object named frxPDFExport1. And that object does not publish a property of that name.
Most likely there's a mismatch between the design time package that you used to generate the .dfm file, and the run time component that is reading that .dfm file. Have you upgraded one and not the other recently?
I'm afraid I cannot give you precise steps to fix the problem, but what I describe above is what is happening. Hopefully that will be enough to lead you to the solution.
You must have updated the component used, which looks like Fast Reports. You need to open up the form in Delphi and the new property will be added by Delphi. Any other forms that use the same component will also need to be opened up to update the properties.
When the error reading form message comes up, click ignore. This should add the missing property. You will want to view the DFM as text to make sure the property has been added.

Very Weird Behavior: Delphi 5 adding a component on my form with empty name

Now this is a very puzzling matter I hope you can help me.
I have a custom component derived from TCustomControl that is included in a package. This package is correctly compiled and installed in D5. The package also requires the use of another library of components the ImageEn library.
I have an application that uses this component, Now until some day ago everything seemed to be fine, but now, after some recent changes to the component (mostly changing the name of the types it uses) I am having a very weird behavior going on. On the form where this component is placed Delphi will create I would say just for no reason a TImageEnIo component (from the ImageEn library) that was not even included in the dfm of the form.
Even more puzzling is the fact that this added imageenio component has no name, thus causing me a lot of trouble when I try to run the application (run-time error). If I delete this component it will reappear as soon as something is updated (for example if I switch between the text and the form of the dfm). Delphi just adds this thing on any form , where I use my custom component. This happens only when my custom component is present, other comps of the package do not generate this problem.
I noticed that it creates 1 of these empty TImageenio for each custom component I have on the form, and moreover if I switch back and forth between the text and the form views of the dfmit will add another imageenio component each time I do this.
Finally the problem is not dependent from the application as it will happen with any application as long as I add my custom component on a form.
Now I have been recompiling everything the imageen and my package many times, I have even tried to restore an older version of the component but the problem persisted (I am quite sure I hadn't experience it with the older version), I have tried anything conceivable but I cannot figure it out. I am at a complete loss, please advice If you need more info please ask, I will try to explain better.
Many Thanks to those who will take the time to answer.
It would seem that the problem was introduced by recent changes in your custom component.
You should use your revision control system to go back to a known good version. Then advance to intermediate versions of the code, perhaps using a binary search for efficiency. Once you've isolated the revision which introduced the bug then you should be able to study the code changes in that revision and identify the problem.
Wild guess: Your custom component directly or indirectly instantiates a TImageEnIo with the wrong Owner. Instead of using Self (i.e. the custom component instance) it uses its Owner property, which points to the form it is sitting on.
The first thing I would try would be to start a new application, create one of your custom controls at run time and put breakpoints on the third party source code where the TImageEnIo component is instantiated, constructor of the component would be fine. If the design time behavior is exhibited at also run-time, the breakpoint would be hit and you would be able to figure out the code part creating the component from the stack trace.
Otherwise, it is possible to debug design-time behavior by debugging the IDE with another instance of the IDE, but I don't know how it can be done with D5.

Delphi: how to lock dfm-s to not change...?

We used Delphi 6 long times ago. Our problem, that Delphi have two problems with DFMs:
1.)
When some linked resource (like DataSet) will removed, Delphi many times forget to ask you that "some of the resources are linked, you need to redirect...". This happens, when the actual form is not added to the project, or it is not opened.
2.)
When we only open the DFM, and only see some thing, may we change it (active TabSheet, form position).
Then Delphi auto save the form - and sometimes it drops the links.
Another problem with this that we used SVN, and SVN detect these changes...
We thought that we change DFM files to read only, but this can prevent the usage of SVN too...
So somebody please help us: have the Delphi some extension (like gexpert) that can lock the DFMs to avoid changes, and some other tool to see that dataset is used in other forms or not?
You're kinda cheating on Delphi. It is built to manage the duality *.pas and *.dfm altogether, knowing how to maintain the links (and with form inheritance, it's better to have all the stack open).
If you want to manually interfere, you have to know what you are doing and do it very carefully. You're not supposed to fiddle with the dfm insides more than to edit the form code portion before the private section.
What I do when I have to edit the dfm manually is to make sure it's not open in any way in delphi (beware form inheritance) and then edit it in another editor.
Also when I check the pas/dfm back in, I do a diff on the dfm to make sure nothing bad happened to it.

Resources