Convert TMainMenu to TActionBars - delphi

I have in a old project, standard menus on my forms. The menu items are populated by TActions that I have made using the TActionManager.
I am updating this old project and would now like to change the appearance of my menu to XP Style as set by the TActionManager, so it can match the TToolBars on my forms which have changed to dsGradient.
Is there a non lazy way of making this transformation?
Otherwise it means I have to manually go through my forms, remove the TMainMenus, drop a TActionMainMenuBar on the form and then begin creating the TActionBars to populate the menus again, which I will be honest with you right now I don't feel like spending so much time doing this.
So if there is a way to automate the conversion somehow I would be interested to know, then I don't have to spend so much time manually changing them.
Equally, if the above can be done without manually making the changes, I would be interested to see if it is possible to reverse convert, eg TActionBar menu to TMainMenu?
If I must do it manually then so be it, but if there is a quicker better option then I really would like to know.

I strongly suggest you to study the following converter utilities by ChoosPill :
TB2KImpTb97
TB2KImport
They are distributed in source code and support the import of all relevant items and properties from stock VCL components TMainMenu, TPopupMenu, TMenuItem and TToolBar to Jordan Russel's famous Toolbar97/Toolbar2000 components respectfully.
You can also consider to take a glimpse at TBXLib converter source code .
You can also consider delving into TdxBarConverter's source code if you are a DevExpress registred user.
They can serve as a good starting point for you.

Related

Number of TActionManager components in a project

I've used TActionLists in D7 for many projects, one for each TForm where it seemed relevant. Now, starting a new project i XE2, the users require a Ribbon, which seems to require a TActionManager.
Reading online and the documentation doesn't give me a clear idea on how to utilize the TActionManager in the way it was developed. My questions are:
Am I supposed to put just one TActionManager in ex. TDataModule or am I supposed to stick by my usual procedure, and put one on each TForm?
Should I use it in conjunction with TActionLists, or is that only for existing projects, where the TActionManager is introduced later?
Anything to be aware of when using TActionManager in SDI or MDI applications?
Links to examples etc. are appreciated.
Thanks,
/Mikkel
(1) Although conceptually, it is preferable to limit components on forms to visual components and components that are very closely tied to presentation, moving aside all others to data-modules, TActionLists and TActionManagers are the exception to the rule for a practical reason. If you put an actionmanager on a datamodule and have action bars on a form with buttons and menu items linked to contained actions of the actionmanager, the IDE will sometimes destroy all your actionbar hosted controls. To save frustration, put one actionmanager each form.
(2) Once you start using Actionmanagers, there is no reason to use ActionLists. An actionmanager is like an actionlist on steriods. While you could have a mix, it seems simpler to have just all of one kind in a project. Compare the look and feel of an actionband main menu with an XPStyle style setting, with an old fashioned main menu.
(3) There is no issue with using actionmanagers in SDI or MDI applications, that I am aware of.
(4) ActionBands are more than a decade old now. Here are some links authored two great Delphi luminaries...
http://www.blong.com/Conferences/DCon2001/Actions/Actions.htm
http://www.stevetrefethen.com/wiki/Default.aspx?Page=Delphi%20ActionBand%20FAQ
http://cc.embarcadero.com/Item/19272

Is there a Delphi option to 'lock' the design (layout) of a form against accidental changes?

After years of Delphi development I now have hundreds of forms shared throughout our Applications. Compilation ranges from Delphi 7 through to XE, thus one form might be opened in any IDE. The well-known Explicitxxx property addition after Delphi 7 has solutions to avoid a form accidentally acquiring properties that earlier compilers can't process (e.g Andreas's DDevExtensions) but I'd like a more positive 'switch' that prevented Delphi from making or saving any form modifications at all. Period.
Of course you could use the read-only flag, and a version control system provides additional means particulay of seeing that such a modification has occured. What I'd really like though is a {$LockDFM} switch that I could put in the form's unit, or a context menu option when viewing the form layout.
Can anyone think of a neat way of achieving this?
Thanks
The only thing I can think of (other than the read-only/VCS options you mentioned) is the Edit menu's Lock Controls option. This sets a flag that prevents controls from being moved around. I'm not sure how much good it would actually do, as I've never tried it; I just know it's there.
Helo
I am pretty sure that Delphi has no such a thing. I have been searching for a solution to this problem as well.
But, theres one thing you can do: You can write your own Delphi addon using OTA (Open Tools API). I know that there are a few classes which are able to notify you when something are about to be saved. You can intercept this event and decide if you wanna save it (in your case, if it is a DFM).
BTW, if you have plans to do such component, tell me. :)
EDIT:
I have found a piece of code that may help you. Extracted from http://www.gexperts.org/otafaq.html
TMyFormNotifier = class(TNotifierObject, IOTANotifier, IOTAFormNotifier)
protected
procedure FormActivated;
procedure FormSaving;
procedure ComponentRenamed(ComponentHandle: TOTAHandle; const OldName, NewName: string);
end;
In design time there is Edit->Lock Control.
LE: this is only for resizing/repositioning the controls on the forms. Concerning the ObjectInspector I don't know if there is anything that can 'lock' the values set there(so the developer can not change them).
Basically, no. Aside from the f'ing (pardon my french) explicit size and position properties which IMO never should have been in the .dfm, there are some third party components will change stuff just by you viewing the form. F.x. TMS components will update a version number even if you didn't change a thing since the previous version of their components.

Visual Form Inheritance problem. "cannot inherit from (parent form). Contains a component that does not support inheritance"

I have a base form with descendents. The base form has a TElRelDataSource on it (from ElPack v4.00). When I open the descendent form I get an error "cannot inherit from (parent form). Contains a component that does not support inheritance". This is with the ancestor forms open (there are two), to avoid the "ancestor for (parent form) not found" error.
Delphi 7 doesn't (AFAIK) support finalising classes, but this seems to be a standard error message. It's in the index for "Tomes of Delphi: Troubleshooting" but I don't have a copy of that and I'm reluctant to spend $US60 to read an entry like "this is why you should avoid VFI" (being pessimistic about the contents of the book). Other than that, no references in Google or Bing.
This is in code that I've recently inherited from someone who left a while ago and I'm the first person to change it since they left. Which means I can't ask how he created the offending form.
So, how do I get around this error message?
You got yourself into an interesting problem. First of all, you say the parent form already includes the offending DataSource, so you've got to ask yourself a question: How did the original developer manage to put the dataset on the parent form and then create child forms, if creating child forms is rejected by the datasource?
The original code didn't have the TElRelDataSource
This implies you're trying to add it your self. Don't add it, find an other solution that doesn't rely on the TElRelDataSource.
The original code did have it!
The original was probably compiled against a different version of TElRelDataSource, one that did allow inheritance. "Inherability" is controlled by the "csInheritable" component style. That is, if the component doesn't include "csInheritable" in ComponentStyle, the Delphi IDE will not allow visual inheritance. You have a number of options:
Use a different version of TElRelDataSource, maybe the original was compiled against a NEWER version of TElRelDataSource. If you are using the latest TElRelDataSource, the author probably decided it's code can't handle visual inheritance so he/she removed the csInheritable flag from ComponentStyle!
Try making your own derived component and set that style yourself. This is easily done, but if TElRelDataSource's author removed the csInheritable flag for a reason, you'll probably get into trouble.
Normally HeartWare's idea would work just fine; Unfortunately it's not that easy with a DATA SOURCE component: I assume you have DB-Aware controls linked to that data source. If you create the DataSource from code, you'll need to re-create the connections to data-aware controls as well, and that's going to take a lot of "if-s" (or clever use of RTTI).
You may try moving the DataSource to a TDataModule. This is probably more trouble then it's worth it.
One option would be to remove the offending component from the form and allocate it dynamically in the FormCreate event. Depending on how many properties the (presumed) non-visual Data Source component has, this could be fairly simple.

Switching Control Types (but not names) for Lots of Controls on a Form in Delphi

I need to switch every control of a particular type on a form to a different type while maintaining the name and the code associated with each control.
For example, let's say I need to switch a dozen or more TEdit fields to TSpinEdits. How can I do that in Delphi 2007 with minimal effort?
Use the GExperts Replace Components expert. It's free, and is the only tool I've seen that does what you're asking, including mapping properties from the old component to the new one.
If you don't feel like using any external tools, you could always try switching to view the form as text, then search and replace TEdit to TSpinEdit. When you switch back and save the form, the IDE should tell you that the declarations in the .pas file are incorrect and offer to correct them automatically. Property mappings shouldn't be a problem unless there are properties that are named differently that you want to map from one class to the other. Properties that don't exist on the new class will be deleted. This is how it works in Delphi 7 anyway...
If you're not happy with the results, you might try GExperts as recommended by Craig, which are a great addition to the IDE for many reasons.
I use the CNTools component replacer (couldn't find the one in GExperts), it's got a good Component Selector feature too so you can select multiple controls based one some simple queries.

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

Resources