Deriving a Property-editor Class
Go Up to Adding Property Editors
Both the component library define several kinds of property editors, all of which descend from TPropertyEditor. When you create a property editor, your property-editor class can either descend directly from TPropertyEditor or indirectly through one of the property-editor classes described in the table below. The classes in the DesignEditors unit can be used for VCL applications.
All that is absolutely necessary for a property editor is that it descend from TBasePropertyEditor and that it support the IProperty interface. TPropertyEditor, however, provides a default implementation of the IProperty interface.
The list in the table below is not complete. The VCLEditors unit also defines some very specialized property editors used by unique properties, such as the component name. The listed property editors are the ones that are the most useful for user-defined properties.
Predefined property-editor types:
| Type | Properties edited |
|---|---|
|
TOrdinalProperty |
All ordinal-property editors (those for integer, character, and enumerated properties) descend from TOrdinalProperty. |
|
TIntegerProperty |
All integer types, including predefined and user-defined subranges. |
|
TCharProperty |
Char-type and subranges of Char, such as 'A'..'Z'. |
|
TEnumProperty |
Any enumerated type. |
|
TFloatProperty |
All floating-point numbers. |
|
TStringProperty |
Strings. |
|
TSetElementProperty |
Individual elements in sets, shown as Boolean values |
|
TSetProperty |
All sets. Sets are not directly editable, but can expand into a list of set-element properties. |
|
TClassProperty |
Classes. Displays the name of the class and allows expansion of the class's properties. |
|
TMethodProperty |
Method pointers, most notably events. |
|
TComponentProperty |
Components in the same form. The user cannot edit the component's properties, but can point to a specific component of a compatible type. |
|
TColorProperty |
Component colors. Shows color constants if applicable, otherwise displays hexadecimal value. The drop-down list contains the color constants. Double-click opens the color-selection dialog box. |
|
TFontNameProperty |
Font names. The drop-down list displays all currently installed fonts. |
|
TFontProperty |
Fonts. Allows expanding individual font properties and accessing the font dialog box. |
Matching unnamed enumerations
For unnamed enumerations, the IDE shows numbers instead of the names of the elements. This section shows the mapping technique for mapping names to numbers in the set so that the names display in the Object Inspector.
The following example is a code sample that shows how to match the unnamed enumerations to specific names using the property mapper functionality:
unit DemoComponent;
interface
uses
System.SysUtils, Vcl.Forms, System.Classes, Vcl.Controls, Vcl.Menus, TypInfo, Vcl.Graphics,
DesignIntf, DesignEditors, DesignConst, DesignMenus, VclEditors;
const
Bit0 = 0;
Bit1 = 1;
Bit2 = 2;
Bit3 = 3;
Bit4 = 4;
Bit5 = 5;
Bit6 = 6;
Bit7 = 7;
BitCount = 8;
type
TSomeBits = 0..SizeOf(Integer) * 8 - 1;
//OR
//TASetOfBits = Bit0..Bit7;
TPiecesOfEight = set of TSomeBits;
//IMPORTANT to use "VclEditors.TSetProperty"
//The DesignEditors.TSetProperty will have the old True/False dropdown editor
TPiecesOfEightProperty = class(VclEditors.TSetProperty)
public
function GetValue: string; override;
procedure GetProperties(Proc: TGetPropProc); override;
end;
TPiecesOfEightElementProperty = class(TSetElementProperty)
public
function GetName: string; override;
end;
TPiecesOfEightControl = class(TComponent)
private
FPiecesOfEightValues: TPiecesOfEight;
published
property PiecesOfEight: TPiecesOfEight read FPiecesOfEightValues write FPiecesOfEightValues;
end;
procedure Register;
implementation
const
cBitValues : array [Bit0..Bit7] of string = (
'Bit One' ,
'Bit Two' ,
'Bit Three' ,
'Bit Four' ,
'Bit Five' ,
'Bit Six' ,
'Bit Seven' ,
'Bit Eight'
);
procedure TPiecesOfEightProperty.GetProperties(Proc: TGetPropProc);
var
I: integer;
E: IProperty;
begin
with GetTypeData(GetTypeData(GetPropType)^.CompType^)^ do
begin
//for I := MinValue to Maxvalue do // is a smaller set is used.
for I := MinValue to BitCount-1 do
begin
E := TPiecesOfEightElementProperty.Create(Self, I);
Proc(E);
E := nil;
end;
end;
end;
function TPiecesOfEightProperty.GetValue: string;
var
I : integer;
S: TIntegerSet;
begin
Integer(S) := GetOrdValue;
Result := '';
for I := 0 to SizeOf(Integer) * 8 - 1 do
if I in S then
Result := Result + cBitValues[I+Low(TSomeBits) ] + ',';
if Result.EndsWith(',') then Delete(Result, Length(Result), 1);
Result := '[' + Result + ']';
end;
function TPiecesOfEightElementProperty.GetName: string;
begin
Result := cBitValues[Element];
end;
//For "sets", the VCLDesigner code always maps the property editor back to: VclEditors.TSetProperty.
//So we need to make OUR set's properties map to *our* editor implementation
function SetPiecesOfEightPropertyMapper(Obj: TPersistent; PropInfo: PPropInfo): TPropertyEditorClass;
begin
Result := nil;
if Assigned(Obj) and (Obj.ClassType <> TPiecesOfEightControl) then Exit;
if PropInfo.PropType^.Kind = tkSet then
if PropInfo.PropType^ = TypeInfo(TPiecesOfEight) then
Result := TPiecesOfEightProperty;
end;
procedure Register;
begin
RegisterComponents('Test Group', [TPiecesOfEightControl]);
RegisterPropertyMapper(SetPiecesOfEightPropertyMapper);
RegisterPropertyEditor(TypeInfo(TPiecesOfEight), TPiecesOfEightControl, 'PiecesOfEight', TPiecesOfEightProperty);
end;
end.