How to make Delphi re-save all forms? - delphi

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)

Related

Visual component become invisible in design mode and cannot get them back in Fire Monkey

I am using a TScaledLayout as a background and after I load the project a few times ALL visual components become invisible, they are there and will compile and run fine but I cannot get them to become visible again. Has happened 4 times now and have had to revert to a backup each time.
I have encountered quite a few bugs in the IDE when using Firemonkey - it is nowhere near as reliable as VCL (yet). In particular the '.lfm' and '.pas' can become unsynchronised, so that there are components in the lfm, which are defined not in the pas file.
This doesn't seem to affect runtime but sure can be confusing when you are coding... Try checking to see that all of the components in the lfm are also defined on the form. There also seems to a few issues surrounding form inheritance, where you just have to do a lot of things manually as changes to ancestors are often not picked up by descendants.
Also note that most Firemonkey components also now have a property called 'DesignVisible'. Check to see that this is set correctly.

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.

"Rename control" in Delphi 7?

Following up on this question, I'm working on a large Delphi 7 codebase which was not written very nicely.
I'm looking at code like this, as a small example:
if FMode=mdCredit then begin
Panel8.Caption:='Credit';
SpeedButton3.Enabled:=false;
SpeedButton4.Enabled:=false;
SpeedButton5.Enabled:=false;
SpeedButton5.Enabled:=false;
SpeedButton6.Visible:=False;
SpeedButton10.Visible:=False;
end;
Followed by another 6 very similar blocks. The whole thing is in this style.
So I'm thinking that this would be much easier to read if the controls were named sensibly.
I could just use a global search and replace, but I'll run into problems when multiple forms use the same names, and also I'd have to be careful to change (eg) SpeedButton10 before SpeedButton1.
Is there some plugin which has the ability to perform a "smart" rename for me?
Edit:
Sorry, I should have mentioned this before: I tried both GExperts and Castalia's "Rename Component" feature, but they both seem to be intended for use when adding the component to the form initially.
They don't do a search+replace in the code, or rename existing events (SpeedButtonXClick() -> cmdCreditClick()).
Have I missed something?
Not exactly a plug-in, but you can use one of the more recent versions of Delphi and the refactoring feature in there. Maybe you could use the free Turbo Edition . . .
You might try ModelMaker for Delphi 7. It has refactoring support that might work for you.
The Rename Symbol refactoring in recent Delphi versions will work across units in a project. Since you say Delphi 7 I guess that's not going to help you, and in the past I've just used TextPad, a great editor that (like many others) will do powerful search/replace across files (with or without confirmation).
HTH
Edit: Craig's right - GExperts will do this, as will Castalia.
I think GExperts has a search and replace like this.
Don't know if it can work in your case, but you could try to load your project in a later version of Delphi that has the refactoring capability and use it to change the components names while taking care of all the dependencies. Then you just have to do a diff and see what has been changed.
Why not use Sync Edit? Its part of the IDE (at least in 2006+):
The Sync Edit feature lets you simultaneously edit indentical identifiers in selected code. For example, in a procedure that contains three occurrences of label1, you can edit just the first occurrence and all the other occurrences will change automatically.
(copied from the BDS2006 Help)
You will have to rename your components first, but it takes the pain out of most of this. I prefer the GExperts wizard of renaming components as they are added to the form, but as you pointed out, it only works when the component is added to the form, and doesn't reach into the individual usages of the components in code. The reason for the renaming of the components first is that when you select the entire block of code to do the rename, it won't make the appropriate changes in the dfm file...just your locally selected code block.
To use the feature, select your entire implementation block, then press the button in the gutter that has two pencils "linked" by a line...then press tab until you get the first one you want to edit...when you change its name, it will change globally in the rest of your source file. Press ESC when your done.

Delphi issue with sharing Image Lists across forms

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.

Resources