I have a C++Builder (XE6) project containing multiple Vcl forms. Only one of them is listed as auto-create on Project>Options>Forms, I create the rest using new as and when needed.
The problem is that every so often, C++Builder will insert a load of lines like:
USEFORM("TMainForm.cpp", mainForm);
into the file with my WinMain method. It will also occasionally shift around the order of these lines.
This leads to the version control history for that file being mostly full of garbage. So is there a way to prevent it inserting the USEFORM macro?
In a word, NO. You just have to live with it, and delete the macros if you don't want them.
If you are worried about version control issues, see suggestions in this topic:
IDE generated USEFORM macro calls changing their order.
Related
Just upgraded from Delphi XE to Tokyo, and was hoping for some updated IDE features.
One nice to have feature would be automatically providing options to add a unit to the uses clause. For example, if you reference something in code that isn't in a uses, it would be nice if the IDE prompted you to add the related unit(s).
For example, keeping it simple, in IntelliJ, you might declare a Button, but not yet have added the associated Library to the Import clause.
When this happens, the offending line is highlighted (just like in Delphi), but the IDE will let you add the necessary library with an Alt-Enter. If there are multiple libraries (it knows about it) it will prompt you for the one you want.
Anything like this for Delphi?
Delphi 2007 and later versions support this for most types that it knows about (in the search or library path). (It may have been available in D2005/2006; I don't have them installed anywhere now to check. I know it was not in Delphi 7.)
Put in the type, and use the Refactor menu (Refactor->Find Unit) or press Ctrl+Shift+A.
Here's an example:
It's not 100% effective, but it's a vast improvement over the old way.
(And yes, I know about TArray<string>, before someone chimes in. I just grabbed a quick type that I knew wouldn't be in the default VCL form uses clause for an example.)
To maintain its project, Delphi sometimes adds or removes stuff from the DPR file (project source). I quite like to format my stuff in the DPR as if it is an ordinary unit, for example to group together the 'used' frame references and project source files. I make copies of it and can go back when this happens but every so often, I'll notice that the DPR has had all its source file references smashed into a single block.
Anyone else suffer from this? Is there any way of preventing this from happening (other than a read-only file).
Thanks
What I do for most of my projects is to have these 2 files:
MyProgram.dpr
MyProgramUnit.pas
MyProgramUnit has a public method Main that contains all the logic from the .dpr (including any conditional defines)
MyProgram just calls Main.
Edit 1:
You can put uses lists in MyProgramUnit.pas, but they don't automatically become part of your project.
That might or might not be an issue, it depends if you like having Delphi finding units in a search path, or add files to your project to make them visible.
What you can do, is to document the uses-lists in MyProgramUnit.pas and group them by cause. This is what I normally do in most units anyway, not only in the main unit.
Edit 2:
Don't go the {$I MyIncludeFile.inc} way.
Delphi - especially the IDE - is bad with include files. Code Completion, etc, fail at irregular places.
I've been heavy on include files in the past; not so any more. I even stopped using them for defines, and moved from {$IFDEF define} ... {$ENDIF} towards {$IF Constant1 >= Constant2} ... {$IFEND}.
The .dpr is a normal Delphi file, alright, but once it is opened in the IDE, it is more or less "owned" by the IDE. There is no way to stop the IDE from adding or removing code from it, when the IDE thinks that is necessary (e.g. when you added a unit, changed some settings, etc.). That can also mean it reformats parts of the code.
If you want "immutable" code, put it in a unit.
I think Rudy's got this one right.
IMO, it's wiser to keep hands off the dpr uses block in the editor - the project manager is designed to do that - by hand you're liable to corrupt your project settings and introduce some hard to track down bugs in large projects. As for formatting, in Delphi XE there is autoformat that will do your whole project and is configurable.
I often edit the 'program' section of the dpr (that also requires some knowledge and caution) but not the uses block.
One additional point: some of what happens in the dpr can be controlled from your project options settings.
HTH
Personally I make a copy of my uses clause in a giant comment at end of my DPR file.
So when Delphi modifies it, I "restore" it from the comment.
Of Course I have to be cautious of maintaining my "uses comment" up to date.
Note :
I'm using external tools that scan the project file so I cannot use the "external unit" approach, although it seems the cleanest solution.
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.
I am currently working with 'inherited' code that has (scattered randomly throughout) a whole bunch of conditional compiler directives based on the version of Delphi, going back to Delphi 2 . From now on, all development will be with Delphi 2009 or future. Is there a tool in Delphi 2009 , or a plugin, that will automatically remove compiler conditional code segments based on a specified 'minimum' version?
I highly recommend the Delphi Inspiration Pascal Preprocessor (DIPP)
This can do a number of things with a source file in addition to removing conditional defines, including the "inlining" of include files and removing comments (all of course highly configurable and controllable by options supplied to the processor).
The conditional defines functionality is especially useful as you can either have all such conditionals simply removed or provide a set of DEFINE's that you wish to apply. DIPP will then emit a source file that reflects how it would appear to the compiler with those symbols DEFINED, but without the conditional directives themselves.
So in your case you would simply defined the symbols appropriate to your "baseline" Delphi version.
You should give JEDI PreProcessor (Pascal PreProcessor) in the JCL a try.
In the trunk in our SVN the source can be found in the dir jcl/devtools/jpp and in our latest release (2.1) zip-file the jpp.exe can be found in the dir devtools.
I don't know of such a tool but it should be relatively straight-forward to write it.
Loop through all files in the directory using FindFirst and FindNext
Use TStringList.LoadFromFile to read all pas files.
Loop through the strings and look for {$IfDef} directives. If the version specified in the conditional section is older than D2009 remove all text until the {$EndIf}.
Use TStringList.SaveToFile to write the modified file to disk.
My advice would be to ONLY change code you completely manage. If however you are also going to modify existing 3rd party code, then I suggest you go through each IFDEF defined for validation. Some vendors do not use the standard IFDEF VERxxx calls, but create their own which might be called something like VER70UP or such. The most common place for this would be in include files, so look for a {$I ???.INC} file near the beginning of each file, then analyze this for what is being used and how.
The other reason to analyze each $DEFINE/$UNDEF is the fact that a version specific one might turn on a new define that your previously not checking...one that ultimately leads into dead code.
Use GExperts, you can use both GrepSearch or GrepRegularExpressions to search in your code and then use the Replace tool in the GrepResults to remove whatever you need.
You can do a search and replace
operation on all of the matches in the
list or only the selected file/match.
When you choose one of those options,
a dialog appears prompting for the
string to use in place of the matched
text. Note that forms that are
currently open can not have their text
replaced, due to limitations in the
IDE. Please close all forms before
trying to replace text in them.
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.