How To Subclass A Form in Delphi? Best Practices? - delphi

I've got a base form in Delphi 2007 that I'd like to reuse in another project, adding some other buttons and such.
I'm familiar with subclassing a non-GUI object, but it is possible to subclass a Form in the same fashion? Can you make changes to the subclass Form in design mode?
How do you go about doing this and what are some things to look out for?

As idursun said (he was a little quicker than me):
Add the base form to your new project.
Then choose "File\New\More..."
Form the "Delphi-Projects" branch select "Inheritable Elements", find your base form and click "OK".
(The actual names of the menu items may vary since I am using a german version of Delphi 2009)
You can then make changes to your new or your base form.
If I do so I make sure to have both forms open in the IDE since sometimes it seems Delphi doesn't get all the changes if I don't.

You should add your base form to your new project and in the new form window there should be an Inherit tab where you can select a base form for the new form.

Related

How to add a "unit only" item to "New" menu/object repository in Delphi

I've seen numerous examples of how to add a form wizard to the Delphi Object Repository (for instance, in the TeeChart source), but I want to add the equivalent of the "New Unit" but just with content that I generate. In other words, I can't figure out how to JUST create a unit without creating a form with it. I am currently trying to do this via OTA in Delphi XE via the IOTAModuleCreator, but it wants a form ancestor. Is there a different interface I should use, is there someplace I can just pass a nil to avoid the form, or is this not even something that can be done?
Per what Sir Rufo said, this indeed did exactly as I was looking for:
https://github.com/VSoftTechnologies/DUnitX/blob/f-d10-seattle/Expert/DUnitX.Expert.NewUnitWizard.pas

Linking different forms in DELPHI within the same project

I am currently designing a database interface in DELPHI 2010, and I have designed several form interfaces, all encapsulated in one Delphi project structure.
I began designing a particular interface form first, and, as a result, an irrelevant form first appears when I run the .exe file, whereas I want a menu form to appear when the program is loaded. My questions are:
How can I get my menu form to open first when and .exe of my compiled project is run?
What function do I need to use to program navigation buttons on this menu to open new forms up?
What function should I use on the "Exit" buttons each of my forms to close the forms down individually, without closing the whole program?
I have good knowledge in Pascal, but I am new to programming object orientated solutions in this platform.
You should determine if you forms would be auto-created or created on demand.
You should also decide which form would be main one.
The corner question would be if you can have several open forms of the same class, for example if you made "File Viewer" form there may be sense to have several of them open for different files.
For auto-created forms:
1.1 Open project source (.dpr file, Project/View Source menu) or open Project options in Forms section. Set MenuForm the 1st (topmost) one in creation list.
1.2 Check that all other forms have their .visible property false
2: Depending on the logic of your program you should use Form1.Show or Form1.ShowModal
3: Self.Close or Self.Hide or Self.Visible := false. Better 1st: http://docwiki.embarcadero.com/Libraries/XE2/en/Vcl.Forms.TCustomForm.Close
If u use OnClose event of those forms - ensure you did not changed default caHide action for closing
For manually lifetime controlled forms:
1: Open project source (.dpr file, Project/View Source menu) or open Project options in Forms section. Set MenuForm the only one created.
2.1. some-temporary-variable := TFormClass.Create(Application);
2.2. Then you tweak some properties of some-temporary-variable like filename to open or some data source or whatever.
2.3. Then you do some-temporary-variable.Show or some-temporary-variable.ShowModal.
Beware: using ShowModal may freeze your application, in cases like TFormClass.Create(SomeAnotherForm), use Application for parent.
3: Self.Release http://docwiki.embarcadero.com/Libraries/XE2/en/Vcl.Forms.TCustomForm.Release
or Self.Close and specify caFree action in OnClose event - http://docwiki.embarcadero.com/Libraries/XE2/en/Vcl.Forms.TCustomForm.OnClose

Convert TMainMenu to TActionBars

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.

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.

Resources