四组件属性编辑器和组件编辑器 通过上面的努力我们的组件似乎已经比较完美了可我们也忽略了一些重要的细节和一些有趣的事情这一篇我们将研究两个很有用的组件特性 在之前开发组件核心功能时我们曾设置了两个属性BeginTime和WakeTime他们都是字符串型的属性然而他们所要表示的却是时间类型这样就很有可能使组件使用者错误的编辑属性并导致转化字符串到时间时出错(当然这里只是为了文章的讲解我们故意把它设置为了字符串类型)虽然通过浏览原代码你知道我们也做了一些代码级别的防出错处理使当输入错误时属性自动变成::然而这对组件使用者来讲仍然显的很不友好所以我们需要为这两个属性定制编辑器我们的编辑器将弹出一个窗口里面有一个TdateTimePicker用来选择时间在delphi中有许多这样的例子例如大家都知道的lines属性当你单击它右放的省略号时为自动弹出一个文本编辑器来编辑lines这大大降低了组件使用者范错误的可能性 在定制完属性编辑器以后我们将为组件本身加入一写有趣的元素——组件编辑器这也是在delphi中经常出现的例如有些组件当你双击它时它并不会进入代码编写状态而是弹出它自己的编辑器虽然我们的组件似乎并不需要这种特性但为了演示它我们也将它考虑近来我们给我们的组件编写了一个版权信息和一个关于对话框当组件使用者双击它时弹出关于信息(当然这仅仅是种演示)上面提到的两种特性由于它们只是会在设计时起作用所以你完全可以在新的组件包中编写并注册它们并将这个组件包设置为Designtime Only为了方便起见我们就直接把它们和组件的单元编写在一起注意以下出现的一些类和方法都需要引用单元DesignEditors(delphi)或DsgnIntf(delphi)与前面说的一样它们都属于delphi的open tools api所以如果你没有这写单元请按照前文的方法安装它们 首先来编写属性编辑器由于BeginTime和WakeTime是字符串类型所以我们必须从默认的字符串属性编辑器类TstringProperty继承并覆盖它的一写方法(这里只介绍几个重要的方法事实上所有的属性编辑器都从TpropertyEditor继承而来然而我们不用直接继承这个基类)其中一个重要的方法是GetAttributes他将返回一些代表编辑器功能的值这些值将会在代码的注释中说明(如果你的属性编辑器还需要一个下拉列表你还需要另外一个重要的方法GetValues具体请查看delphi帮助)另外为了使属性编辑器为弹出的对话框我们需要覆盖Edit方法为了可以以可视化的方式设计对话框我们可以建立一个普通工程在设计好后将窗体的类声明复制到我们的组件单元并将窗体的dfm文件拷贝到我们的组件包目录并在代码中加入编译器开关{$R *dfm}以下是窗体的类声明这个窗体没有任何的代码需要编写 TTimeEditFrm = class(TForm) DateTimePicker: TDateTimePicker; Button: TButton; Button: TButton; private { Private declarations } public { Public declarations } end; 以下是属性编辑器的代码 TClockProperty=class(TStringProperty) public function GetAttributes:TPropertyAttributes;override; procedure Edit;override; end; 实现部分 procedure TClockPropertyEdit; var TimeEditFrm:TTimeEditFrm; begin TimeEditFrm:=TTimeEditFrmCreate(Application); try TimeEditFrmDateTimePickerTime:=StrToTime(GetValue); if TimeEditFrmShowModal=mrOK then SetValue(TimeToStr(TimeEditFrmDateTimePickerTime)); //GetValue和SetValue是TStringProperty的基类方法他直接读取和设置字符串的值 finally TimeEditFrmFree; end; end; function TClockPropertyGetAttributes: TPropertyAttributes; begin result:=[paDialogpaMultiselect]; //paDialog表示属性编辑器将显示一个对话框paMulitiselect允许多个组件选择属性 //除此之外如果你想让属性编辑器显示下拉列表你还需要paValueList具体请查看帮助 end; 最后我们用RegisterPropertyEditor方法注册属性编辑器: procedure Register; begin …… RegisterPropertyEditor(TypeInfo(string)TClockBeginTimeTClockProperty); RegisterPropertyEditor(TypeInfo(string)TClockWakeTimeTClockProperty); end; 重新编译更新组件后我们就可以测试了可以看到组件编辑器工作得很好 接下来我们来实现组件编辑器 组件编辑器需要继承TcomponentEditor并覆盖一些重要的方法GetVerbCount返回设计时组件右键自定义菜单的数目GetVerb为每一个自定义菜单添加文字ExecuteVerb为每一个菜单项添加事件Edit为组件的缺省操作指定事件(即在设计时双击组件)以下是代码 TClockEditor=class(TComponentEditor) public function GetVerbCount:integer;override; function GetVerb(index:integer):string;override; procedure ExecuteVerb(index:integer);override; procedure Edit;override; end; 实现部分 procedure TClockEditorEdit; begin ExecuteVerb(); //默认显示关于 end; procedure TClockEditorExecuteVerb(index: integer); begin case index of //第一个显示名字的菜单什么都不做显示 :showmessage(hkbarton@); end; end; function TClockEditorGetVerb(index: integer): string; begin case index of :result:=hkbarton; :result:=About Clock; end; end; function TClockEditorGetVerbCount: integer; begin result:=;//我们显示两条菜单一个我的名字一个关于 end; 同样最后我们注册组件编辑器 procedure Register; begin …… RegisterComponentEditor(TClockTClockEditor); end; 同样可以看到组件编辑器的测试情况 文章写到这里也该结束了虽然写了那么多然而在组件开发中这仍是一小部分内容本文只是抛砖引玉的作用希望对正要进入组件开发的朋友一些启示为了方便你阅读本文如果你想要本文所开发的这个组件的全部原文件请和我联系 Email:hkbarton@sohucom hekphi@hotmailcom QQ |