Delphi的属性是一个很有特色的功能,这一特性在C#里得到了很好的继承。 对于一个类来说,属性是对类中的数据进行有效修改和访问的特殊接口。在VCL中,被published 的属性还有一个特性,就是可以在界面设计过程中对属性进行设置. 属性的类型 数字、字符、布尔、枚举、TStrings、集合,类对象或者接口类型等 示例: TEnumTest=(etNone,etTestInt,etTestString); TTestcontrol=class(TCustomControl) private FInt : integer; FEnumTest :TEnumTest; FCaption :string; function GetInt :Integer; funtion GetEnumTest:TEnumTest; function Caption:String; procedure SetCatpion(AValue:String); procedure SetInt(AValue:Integer); procedure SetEnumTest(AValue:String); published property IntProp :Integer read GetInt write SetInt; property EnumTest:TEnumTest read GetEnumTest write SetEnumTest; property Caption:String read FCaption write SetCaption; end; read 和 write 指令指定了访问属性的有效方法,在这些方法里可以实现对属性的访问封装。 写VCL控件最重要的就是属性编写,属性编辑器又是其中的难点。 属性编辑器一般有数字、字符串、集合、类、Color、Font类型编辑器,Delphi内建基本编辑器声明有 TPropertyEditor 所有的属性编辑器都必须继承于此或他的派生类 TOrdinalProperty 这是几个有序属性编辑器的基类,如TIntegerProperty TCharProperty TEnumProperty TIntegerProperty 适用编辑整型属性 TCharProperty 适用编辑字符型属性 TEnumProperty 适用编辑枚举型属性 TBoolProperty 适用编辑布尔型属性 TFloatProperty 适用编辑浮点型属性 TStringProperty 适用编辑字符串型属性 TClassProperty 适用编辑对象类型 TComponentProperty 使用编辑引用一个组件属性 TSetProperty 适用编辑集合类型 上述可以查看DesignEditors.pas单元(Delphi7) 对于一些基本数据类型有时并不需要创建属性编辑器,因为数据类型本身也会数据进行检查, 在当你有特殊的检查时,你可以从上述基本编辑器派生出自己的属性编辑器 对话框型属性编辑器的编写 定义一个正对字符型属性编辑的对话框界面,在界面上放一个memo, 一个Label, 三个按钮 代码如下 unit uStringEditor; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons,DesignIntf,DesignEditors; type //对话框属窗体类 TMyStringEditDlg = class(TForm) Memo: TMemo; OkButton: TBitBtn; CancelButton: TBitBtn; Label1: TLabel; BitBtn1: TBitBtn; procedure MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormDestroy(Sender: TObject); procedure FormShow(Sender: TObject); procedure UpdateStatus(Sender: TObject); procedure BitBtn1Click(Sender: TObject); private { Private declarations } FModified: Boolean; protected function GetLines: TStrings; procedure SetLines(const Value: TStrings); function GetLinesControl: TWinControl; public { Public declarations } property Lines: TStrings read GetLines write SetLines; end; //对话框属性编辑器 TMyStringProperty = class(TStringProperty) protected function EditDialog: TMyStringEditDlg; virtual; public procedure Edit; override; function GetAttributes: TPropertyAttributes; override; end; var MyStringEditDlg: TMyStringEditDlg; implementation {$R *.dfm} const //v1.73 19/08/2000) CopyRightStr: PChar = 'String Editor v1.0 (12/06/2003)'+#13+#13+ 'Created By Donson Wan '#13+#13+ 'Compiled in '+ {$IFDEF VER80} 'Delphi 1.0' {$ENDIF} {$IFDEF VER90} 'Delphi 2.0' {$ENDIF} {$IFDEF VER100} 'Delphi 3.0' {$ENDIF} {$IFDEF VER120} 'Delphi 4.0' {$ENDIF} {$IFDEF VER130} 'Delphi 5.0' {$ENDIF} {$IFDEF VER140} 'Delphi 6.0' {$ENDIF} {$IFDEF VER150} 'Delphi 7.0' {$ENDIF} {$IFDEF VER93} 'C++Builder 1.0' {$ENDIF} {$IFDEF VER110} 'C++Builder 3.0' {$ENDIF} {$IFDEF VER125} 'C++Builder 4.0' {$ENDIF}; var StoredWidth, StoredHeight, StoredLeft, StoredTop: Integer; function TMyStringEditDlg.GetLines: TStrings; begin Result:=Memo.Lines; end;
function TMyStringEditDlg.GetLinesControl: TWinControl; begin end; procedure TMyStringEditDlg.MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_ESCAPE then CancelButton.Click; end; procedure TMyStringEditDlg.SetLines(const Value: TStrings); begin inherited; Memo.Lines.Assign(Value); end; procedure TMyStringEditDlg.FormDestroy(Sender: TObject); begin StoredWidth := Width; StoredHeight := Height; StoredLeft := Left; StoredTop := Top; end; procedure TMyStringEditDlg.FormShow(Sender: TObject); begin if StoredWidth <> 0 then Width := StoredWidth; if StoredHeight <> 0 then Height := StoredHeight; if StoredLeft <> 0 then Left := StoredLeft else Left := (Screen.Width - Width) div 2; if StoredTop <> 0 then Top := StoredTop else Top := (Screen.Height - Height) div 2; end; procedure TMyStringEditDlg.UpdateStatus(Sender: TObject); begin if Sender = Memo then FModified := True; end; { TMyStringProperty } procedure TMyStringProperty.Edit; begin inherited; with EditDialog do try Lines.Text := GetValue; FModified:=False; UpdateStatus(nil); //ActiveControl := GetLinesControl; case ShowModal of mrOk: begin SetValue(Lines.Text); //Designer.Modified; end; end; finally Free; end; end; function TMyStringProperty.EditDialog: TMyStringEditDlg; begin Result := TMyStringEditDlg.Create(Application); end; function TMyStringProperty.GetAttributes: TPropertyAttributes; begin Result := inherited GetAttributes + [paDialog] - [paSubProperties]; end; procedure TMyStringEditDlg.BitBtn1Click(Sender: TObject); begin MessageDlg(StrPas(CopyRightStr), mtInformation, [mbOk], 0); end; end. 可以用上述编辑器注册给TTestcontrol.Caption 属性 注册属性编辑器的声明为 RegisterPropertyEditor(PropertyType:PTypeInfo; ComponentClass: Tclass;Const PropertyName:String; EditorClass: TPropertyEditorClass); RegisterPropertyEditor(TypeInfo(string), TTestcontrol, 'Caption', TMyStringProperty); 如上就注册成功了, 参数1是Typeinfo(string)是取得属性运行时刻属性类型信息, 参数2是指定注册控件对象,如果不指定控件对象就注册给Delphi所有控件了, 这样你往界面上拉一个Label时, 原来不能写多行文本时现在也解决了,现在你可以在弹出属性编辑器里输,可以任意行:) 参数3是指定注册属性名 参数4就是你需要注册的属性编辑器类名了 另外还可以给你注册的属性加一个归类CategoryName,我们把上述Caption属性指定为MyCategory型属性,注册示例如 下:RegisterPropertiesInCategory('MyCategory', TTestcontrol, ['Caption']); 
|