Creating a Form Wizard - Part 1

It is often nice to have a form’s contents persist from one end user session to another.  Delphi provides for saving a form’s properties and contents from one design time session to another and loading those settings and contents as the form’s initial values when the containing application starts, but it doesn’t provide a means of saving and restoring a form’s settings and contents from one end user session to the next.  So, I decided to embark on a project to figure out how to provide this functionality myself.  Having a fair bit of experience writing custom components for Delphi, I thought “How hard can this be?”.  It turns out to be quite difficult if you want to do it right.

The problem turns out to be not creating the TForm descendent.  This is quite easy and is really no different from extending any other class.  Where the problem arises is in putting the form into Delphi’s object repository so that it can be added to a project just like any other TForm.  By that I mean, not just dropping the derived form into the repository because this allows the user to choose between Copy, Use and Inherit and, if you choose Inherit, it includes the unit containing the original form in the project.  I wanted to be able to use it like the Delphi TForm without all of the other crap that comes with just dropping the form into the repository.

Creating a TForm desendent that behaved the way I wanted it to at design time involved a couple of steps.  The first step, the one covered in this article, involved creating a custom module that could be added to Delphi.  Note that this is not the same as a custom component although there are alot of similarities.  The second step, to be covered in a future article, involved creating a form wizard.  This is the step that turned out the be a problem.  Not because the code is difficult, but because the Delphi Open Tools API (OTA) is so poorly documented.

A custom module consists of a design time and a run time package, just like a custom control  So the first step is to create your two packages.  You do this by selecting Package from the Delphi Projects page of the Add New Project dialog.  For the run time package, select the Runtime Only option and for the design time package select the Designtime Only option.  You will have to add Designide.dcp to the Requires section of the design time package.

Writing the run time package doesn’t provide any surprises.  Just create a new class that descends from TForm and write the code for the new properties and methods as you would for any other derived class.  Remember, if you want your new properties to appear in the Object Inspector, they properties must be published.

Writing the design time package is almost the same as writing the design time package for a custom control, but rather than using the RegisterComponents procedure to register your class, use the RegisterCustomModule procedure.  The RegisterCustomModule procedure looks like this:

RegisterCustomModule(ComponentBaseClass: TComponentClass; CustomModuleClass: TCustomModuleClass);

where ComponentBaseClass is your new derived class and CustomModuleClass is the form editor’s class.  Fortunately for us mortals, Delphi comes supplied with a default form editor class that we can use.  It is named TCustomModule and it can be found in the DesignEditors unit.  So the command to register your new TForm descendent looks like this:

RegisterCustomModule(TMyForm, TCustomModule);

Interestingly, you can use this same procedure to create TFrame descendents.

In Part 2 of this article I will address creating a form wizard so you can add your new form to Delphi’s Add New menu.

Leave a Reply