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

TCompilerOutputExpert
Image of Line Break

Now, it's time to write an esAddIn Wizard, just like the two examples above, but this time we respond to the OnClick event by creating and showing the Compiler Output Wizard, like we did earlier in this paper. Since we'll be porting this last Wizard of this paper from Delphi 3 to Delphi 2 and C++Builder, let's include the entire code to look closely at the potential porting issues involved:

library AddIn;
uses
  ShareMem, VirtIntf, ExptIntf, ToolIntf, Menus, Forms, Classes, Dcc32Out;

{ EXPERT TYPE DEFINITION }

Type
  TBDcc32OutputExpert = class(TIExpert)
  public
    constructor Create; virtual;
    destructor Destroy; override;

    function GetStyle: TExpertStyle; override;
    function GetIDString: String; override;
    function GetName: String; override;
    function GetAuthor: String; override;

  protected
    procedure OnClick(Sender: TIMenuItemIntf); virtual;

  private
    MenuItem: TIMenuItemIntf;
  end {TBDcc32OutputExpert};

{ EXPERT SUPPORT FUNCTION }

procedure HandleException;
begin
  if Assigned(ToolServices) then
    ToolServices.RaiseException(ReleaseException)
end {HandleException};

{ EXPERT IMPLEMENTATION }

function TBDcc32OutputExpert.GetStyle: TExpertStyle;
begin
  Result := esAddIn
end {GetStyle};

function TBDcc32OutputExpert.GetIDString: String;
begin
  try
    Result := 'DrBob.TCompilerOutputExpert'
  except
    HandleException
  end
end {GetIDString};

function TBDcc32OutputExpert.GetName: String;
begin
  try
    Result := 'Compiler Output Wizard'
  except
    HandleException
  end
end {GetName};

function TBDcc32OutputExpert.GetAuthor: String;
begin
  try
    Result := 'Bob Swart (aka Dr.Bob)' { although not needed for esAddIn }
  except
    HandleException
  end
end {GetAuthor};


constructor TBDcc32OutputExpert.Create;
var Main: TIMainMenuIntf;
    ProjectBuildItem: TIMenuItemIntf;
    Project: TIMenuItemIntf;
begin
  inherited Create;
  MenuItem := nil;
  if ToolServices <> nil then
  try
    Main := ToolServices.GetMainMenu;
    if Main <> nil then { we've got the main menu }
    try
      ProjectBuildItem := Main.FindMenuItem('ProjectBuildItem');
      if ProjectBuildItem <> nil then
      try
        Project := ProjectBuildItem.GetParent;
        if Project <> nil then
        try
          MenuItem := Project.InsertItem(ProjectBuildItem.GetIndex+1,
                                       '&Dr.Bob''s Compiler Output Wizard...',
                                        'DrBob','',
                                         ShortCut(Ord('D'),[ssCtrl]),0,0,
                                        [mfEnabled, mfVisible], OnClick);
        finally
          Project.DestroyMenuItem
end finally ProjectBuildItem.DestroyMenuItem
end finally Main.Free end except HandleException end end {Create}; destructor TBDcc32OutputExpert.Destroy; begin try if MenuItem <> nil then MenuItem.DestroyMenuItem; inherited Destroy except HandleException end end {Destroy}; procedure TBDcc32OutputExpert.OnClick(Sender: TIMenuItemIntf); begin try with TDCC32OutputForm.Create(Application) do try ShowModal finally Free end except HandleException end end {OnClick}; { DLL EXPERT INTERFACE } procedure DoneExpert; begin // cleanup end {DoneExpert}; function InitExpert(ToolServices: TIToolServices; RegisterProc: TExpertRegisterProc; var Terminate: TExpertTerminateProc): Boolean; stdcall; begin Result := True; try ExptIntf.ToolServices := ToolServices; { Save! } if ToolServices <> nil then Application.Handle := ToolServices.GetParentHandle; Terminate := DoneExpert; Result := RegisterProc(TBDcc32OutputExpert.Create); except HandleException end end {InitExpert}; exports InitExpert name 'INITEXPERT0016', { Delphi 2.0x & C++Builder } InitExpert name 'INITEXPERT0017'; { Delphi 3 } begin end.

Notice the fact that InitExpert got exported twice? One as name 'INITEXPERT0016' and once as name 'INITEXPERT0017'. The former is the name that's used by Delphi 2.0x and C++Builder, while the latter is the name used by Delphi 3. If we don't export the InitExpert function by the right name, then Delphi will just disregard the Wizard and tells us that it's the wrong version. So, by exporting InitExpert twice under both names (or maybe even as 'INITEXPERT0018' to prepare for Delphi 4), we've taken the first obstacle. But don't party yet; there are more to come...


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