Image of Navigational Map linked to Home / Contents / Search How to write Delphi Wizards

TFileOpenDialogExpert
Image of Line Break

Well, with the TIToolServices class we sure have a lot of information and power at our disposal, don't we!? Let's try to do something easy that doesn't get us into trouble right away. The API that I'm looking for that will allow me to open any file as a new project seems to be OpenProject, which takes a fully qualified filename as only argument.

The engine for the first version of the TFileOpenExpert is as follows:

TFileOpenExpert
GetStyle:esStandard
GetIDString:DrBob.TFileOpenExpert.standard
GetName:FileOpen Wizard
GetAuthor (win32):Bob Swart (aka Dr.Bob)
GetMenuText:&FileOpen Wizard...
GetState:[esEnabled]
GetGlyph:0
GetPage (win32): 
GetComment: 

So, all we need to do in the Execute procedure, is somehow get the fully qualified filename, and call ToolServices.OpenProject with it. The easiest way seems to be using a TOpenDialog, which we can create and execute on the fly, so the code of Execute looks as follows now:

  procedure TFileOpenExpert.Execute;
  begin
    with TOpenDialog.Create(nil) do
    begin
      if Execute then
        ToolServices.OpenProject(FileName);
      Free
    end
  end {Execute};

Well, it's almost what we want. We forgot to initialise the filter of the TOpenDialog, so we need to do that as well. Other than that, we can indeed open up new projects, but we don't close the files of any previous projects that were loaded. So, we need to call SaveProject and CloseProject prior to calling our OpenProject.

  procedure TFileOpenExpert.Execute;
  begin
    with TOpenDialog.Create(nil) do
    begin
      Title := GetName; { name of Wizard as OpenDialog caption }
      Filter := 'All Files (*.*)|*.*';
      Options := Options + [ofShowHelp, ofPathMustExist, ofFileMustExist];
      HelpContext := 0;
      if Execute then
      begin
        ToolServices.SaveProject;
        ToolServices.CloseProject;
        ToolServices.OpenProject(FileName)
      end;
      Free
    end
  end {Execute};

This time it works as we want; we get a TOpenDialog in which we can select any file we'd want. And once we've selected one and hit that OK button, the current project is saved and closed before the selected file is opened as our new project.
Note that Delphi sometimes gives an error message when you open just any file as your new project, when the header (the first few lines) doesn't contain a "uses" clause (which my AUTOEXEC.BAT seldom does).

Standard FileOpen Wizard

The FileOpenExpert from last section looks like any TOpenDialog in action; not really breathtaking, but still we have our first Standard FileOpen Wizard:

If we install this TFileOpenExpert in COMPLIB.DCL or DCLUSR30.DPL like just another component, we get to see it in the Help menu topics. Like the TGenericExpert and the TSysInfoExpert, we've now created another Delphi Standard Expert; one that can be really useful at times:

Project FileOpen Wizard

Now that we've seen a Standard Expert, let's go and try to make it a Project Wizard. After all, the FileOpen Wizard is opening the selected file as a new project, so it actually is already a Project Expert (or at least acts that way).
Remember the Database Form Expert of Delphi? This one can be found in the gallery as a Form Expert and in the Help menu as a Standard Expert. It seems to be both.
I would like to be able to use my FileOpen Expert not only as a Standard Expert but also as a Project Expert. In that case we have to modify the Wizard functions to include both the esStandard and esProject styles (the result is in the next listing). We have to override a fourth method to make it all work: the GetIDString needs to return a truly unique ID string for both the Standard and the Project Expert. Even though the two are essentially the same, we need to return two special IDs. If you don't, DELPHI will just GPF when you try to install the Wizards (with no real clue as to where it when wrong). Which leads back to rule #1 for every serious Component Builder: always have a backup of COMPLIB.DCL or DCLUSR30.DPL at hand when you start to play with components and Wizards. If you don't you might corrupt it beyond repair (at which time you'll have to reinstall the original from your CD-ROM - unless you had made that copy at a safe place).

The base class for our TFileOpenExpert is still the standard expert, while the TFileOpenProjectExpert is derived from it.

TFileOpenExpert
GetStyle:esStandard
GetIDString:DrBob.TFileOpenExpert.standard
GetName:FileOpen Wizard
GetAuthor (win32):Bob Swart (aka Dr.Bob)
GetMenuText:&FileOpen Wizard...
GetState:[esEnabled]
GetGlyph:0
GetPage (win32): 
GetComment: 

We need a new way to express the fact that the TFileOpenProjectExpert is derived from the TFileOpenExpert, and only needs to override a few of the methods. I've decided to use the notation below:

TFileOpenProjectExpert = class(TFileOpenExpert)
GetStyle:esProject
GetIDString:DrBob.TFileOpenExpert.project
GetGlyph:LoadBitMap(HInstance, MakeIntResource('FILEOPEN')) or
LoadIcon(HInstance, MakeIntResource('FILEOPEN'))
GetPage (win32):Project
GetComment:This Project Experts opens any file as new project in the IDE

In order to be able to use the LoadBitMap statement, we must link a resource file with $R compiler directive (like {$R FILEOPEN.RES}) to our project, which contains a 60 x 40 x 16 colour bitmap for Delphi 1.0 or a 32 x 32 x 16 colour icon for the 32-bits versions of the Wizard. Since 16-bit and 32-bit resources are different, we need a construct like the following:

{$IFDEF WIN32}
{$R FILEOPEN.R32}
{$ELSE}
{$R FILEOPEN.R16}
{$ENDIF}

Also note that we don't need to override the Execute method again, since the Execute of TFileOpenExpert is of course the same as the one for TFileOpenProjectExpert.
We do need to change something else, though, we need to register them both:

  procedure Register;
  begin
    RegisterLibraryExpert(TFileOpenExpert.Create);
    RegisterLibraryExpert(TProjectOpenExpert.Create)
  end {Register};

Now, if we install the Wizards with Options | Install, we get both a Standard FileOpen Wizard in the Help menu and the Project FileOpen Wizard in the Gallery. If we enable the gallery from the environments options, we can open any source file every time we start a new project!


Image of Arrow linked to Next Article Image of Arrow linked to Next Article
Image of Line Break
[HOME] [TABLE OF CONTENTS] [SEARCH]