Borland provides some help and examples on this important subject - if you know where to look.
C:\Program Files\Borland\Delphi5\Source\Property Editors
Basic TPropertyEditor Definitions
C:\Program Files\Borland\Delphi5\Source\Toolsapi\dsgnintf.pasIn Delphi 6, they are in
C:\Program Files\Borland\Delphi6\Source\ToolsAPI\DesignEditors.pasThese files contains very detailed help on the properties and methods related to designing your own property editors. However, there is no *.dcu file for these ... just the source.
According to Readme.txt (Delphi 5), dsgnintf.dcu is not provided and, even if you compile it yourself, you are not allowed to redistribute it. Therefore, property editors should not be defined in the same unit (*.pas file) as your run-time code. According to Borland, you are actually not allowed to combine them in the same package.
This is the uses clause from KADaoReg.pas - notice that the definition files are different depending on which Delphi version you are using.
{$IFDEF VER140} {$DEFINE D6UP} {$ENDIF} Uses Classes {$IFNDEF D6UP}, DsgnIntf {$ENDIF} {$IFDEF D6UP}, DesignIntf, DesignWindows, DesignEditors{$ENDIF};I prefer to use these compiler directives because they work in Delphi versions 5, 6, & 7.
{$IFDEF VER130} // Delphi 5 {$DEFINE mc_LT_D6} // Less than Delphi 6, "mc" is used to help avoid conflicts {$ENDIF} Uses Classes {$IFDEF mc_LT_D6}, DsgnIntf {$ENDIF} {$IFNDEF mc_LT_D6}, DesignIntf, DesignWindows, DesignEditors{$ENDIF};
Because part of the Delphi 6 source code necessary to compile DesignWindows and DesignEditors is not available (specifically ComponentDesigner.pas and proxies.pas), add designide.dcp to the *.dpk file's requires clause.
Simply adding
C:\Program Files\Borland\Delphi6\Source\ToolsAPIto Project / Options... / Directories/Conditionals / Search path. won't work - DesignWindows won't compile because ComponentDesigner.pas is not available and DesignEditors won't compile because proxies.pas is also not available.
What ever happened to Proxies.pas? completely describes the Property Editor differences between Delphi 5 and Delphi 6 and explains how editors should be written.
How to split a *.dpk file
I used File / New... / Package to create a new *.dpk file. When I tried to add mcFile_IO_PropEdit.pas it complained that a different version was already in the path. Solution - I added the version in the path (not the copy I wanted).
I saved it as dcl_mc50_PropEdit.dpk
When I pressed compile, I was prompted to add dcl_mc50.dpk (reasonable since the property editor is registered to work with one of its classes).
Next was an error because mcFile_IO_PropEdit.pas was also in dcl_mc50.dpk. So I deleted it and recompiled them both (in the "correct" order).
Finally, I installed dcl_mc50_PropEdit.dpk ... and it seems to work.
Example from KA Dao
TEngSystemDatabaseNameEditor = class(TStringProperty) Public Procedure Edit;override; Procedure SetValue(const Value: string); override; Function GetAttributes: TPropertyAttributes; override; End; TDBDatabaseNameEditor = class(TStringProperty) Public Procedure Edit;override; Procedure SetValue(const Value: string); override; Function GetAttributes: TPropertyAttributes; override; End; //************************************************************** Database Editor Function TDBDatabaseNameEditor.GetAttributes: TPropertyAttributes; Begin Result:= [paDialog]; // This displays the button with 3 dots End; Procedure TDBDatabaseNameEditor.SetValue(const Value: string); Begin if GetComponent(0) is TKADaoDatabase then Begin inherited SetValue(Value); Modified; End; End; procedure TDBDatabaseNameEditor.Edit; // Called when the button with 3 dots is pressed var FileName : String; DBase : TKADaoDatabase; Begin DBase:=TKADaoDatabase(GetComponent(0)); Filename := DBase.F_ChooseDatabase; // this function displays the dialog box if Filename <> '' then begin SetStrValue(Filename); Modified; // According to the help, this is not required with SetStrValue end; End; procedure Register; begin RegisterPropertyEditor(TypeInfo(String),TKADaoDatabase,'Database', TDBDatabaseNameEditor); end;
Accessing Related Properties
var File_IO : TmcCustomFile_IO; str : string; begin // This allows access other properties File_IO := TmcCustomFile_IO(GetComponent(0)); str := File_IO.anyPublicProperty; end;
Custom Component Editors
There are 2 ways that custom component editors can be called
Register your editor with
RegisterComponentEditor(ComponentClass : TComponentClass; ComponentEditor: TComponentEditorClass);
References