Using property editors allows the developer to make a component more user-friendly. The Object Inspector represents one of the key pieces of the user interface of the Delphi environment, and Delphi developers use it quite often. However, you can adopt a second approach to customize how a component interacts with Delphi: write a custom component editor.
Just as property editors extend the Object Inspector, component editors extend the Form Designer. When you right-click within a form at design time, you see some default menu items, plus the items added by the component editor of the selected component. Examples of these menu items are those used to activate the Menu Designer, the Fields Editor, the Visual Query Builder, and other editors in the environment. At times, displaying these special editors becomes the default action of a component when it is double-clicked.
Common uses of component editors include adding an About box with information about the developer of the component, adding the component name, and providing specific wizards to set up component properties. In particular, the original intent was to allow a wizard, or some direct code, to set multiple properties in one shot, rather than setting them all individually.
A component editor should generally inherit from the TComponentEditor class, which provides the base implementation of the IComponentEditor interface. The most important methods of this interface are as follows:
GetVerbCount returns the number of menu items to add to the Form Designer's shortcut menu when the component is selected.
GetVerb is called once for each new menu item and should return the text that will go in the shortcut menu for each.
ExecuteVerb is called when one of the new menu items is selected. The number of the item is passed as the method's parameter.
Edit is called when the user double-clicks the component in the Form Designer to activate the default action.
Once you get used to the idea that a "verb" is nothing but a new menu item with a corresponding action to execute, the names of the methods of this interface become quite intuitive. This interface is much simpler than those of property editors you've seen before.
Like property editors, component editors were modified from Delphi 5 to Delphi 6, and are now defined in the DesignEditors and DesignIntf units.
Now that I've introduced the key ideas about writing component editors, let's look at an example—an editor for the ListDialog component built earlier. In my component editor, I want to be able to show an About box, add a copyright notice to the menu (an improper but common use of component editors), and allow users to perform a special action—previewing the dialog box connected with the dialog component. I also want to change the default action to show the About box after a beep (which is not particularly useful but demonstrates the technique).
To implement this component editor, the program must override the four methods listed in the previous section:
uses DesignIntf; type TMdListCompEditor = class (TComponentEditor) function GetVerbCount: Integer; override; function GetVerb(Index: Integer): string; override; procedure ExecuteVerb(Index: Integer); override; procedure Edit; override; end;
The first method returns the number of menu items to add to the shortcut menu, in this case 3. This method is called only once: before displaying the menu. The second method is called once for each menu item, so in this case it is called three times:
function TMdListCompEditor.GetVerb (Index: Integer): string; begin case Index of 0: Result := ' MdListDialog (©Cantù)'; 1: Result := '&About this component...'; 2: Result := '&Preview...'; end; end;
This code adds the menu items to the form's shortcut menu, as you can see in Figure 9.14. Selecting any of these menu items activates the ExecuteVerb method of the component editor:
procedure TMdListCompEditor.ExecuteVerb (Index: Integer); begin case Index of 0: ; // nothing to do 1: MessageDlg ('This is a simple component editor'#13 + 'built by Marco Cantù'#13 + 'for the book "Mastering Delphi"', mtInformation, [mbOK], 0); 2: with Component as TMdListDialog do Execute; end; end;
I decided to handle the first two items in a single branch of the case statement, although I could have skipped the code for the copyright notice item. The other command changes calls the Execute method of the component you are editing, determined using the TComponentEditor class's Component property. Knowing the type of the component, you can easily access its methods after a dynamic typecast.
The last method refers to the component's default action and is activated by double-clicking the component in the Form Designer:
procedure TMdListCompEditor.Edit; begin // produce a beep and show the about box Beep; ExecuteVerb (0); end;
To make this editor available to the Delphi environment, you need to register it. Once more, you can add to its unit a Register procedure and call a specific registration procedure for component editors:
procedure Register; begin RegisterComponentEditor (TMdListDialog, TMdListCompEditor); end;
I've added this unit to the MdDesPk package, which includes all the design-time extensions from this chapter. After installing and activating this package, you can create a new project, place a list dialog component in it, and experiment with it.