delphi – 创建自定义TSetProperty属性编辑器
我正在尝试为某个自定义组件创建自定义属性编辑器.自定义属性编辑器用于编辑某些set属性,例如
type TButtonOption = (boOption1,boOption2,boOption3); TButtonOptions = set of TButtonOption; 我的属性编辑器来自TSetProperty类.问题是:我的自定义属性编辑器没有注册,Delphi IDE似乎使用自己的默认设置属性编辑器,因为属性编辑器方法内的ShowMessage()调用永远不会执行!我从头开始创建了一个示例包/组件,尽可能简单,显示了这个问题.这是代码: unit Button1; interface uses System.SysUtils,System.Classes,Vcl.Controls,Vcl.StdCtrls,DesignIntf,DesignEditors; type TButtonOption = (boOption1,boOption3); TButtonOptions = set of TButtonOption; TButtonEx = class(TButton) private FOptions: TButtonOptions; function GetOptions: TButtonOptions; procedure SetOptions(Value: TButtonOptions); published property Options: TButtonOptions read GetOptions write SetOptions default []; end; TMySetProperty = class(TSetProperty) public function GetAttributes: TPropertyAttributes; override; procedure GetProperties(Proc: TGetPropProc); override; function GetValue: string; override; end; procedure Register; implementation uses Dialogs; // TButtonEx - sample component function TButtonEx.GetOptions: TButtonOptions; begin Result := FOptions; end; procedure TButtonEx.SetOptions(Value: TButtonOptions); begin if FOptions <> Value then begin FOptions := Value; end; end; // register stuff procedure Register; begin RegisterComponents('Samples',[TButtonEx]); RegisterPropertyEditor(TypeInfo(TButtonOptions),nil,'',TMySetProperty); end; function TMySetProperty.GetAttributes: TPropertyAttributes; begin ShowMessage('GetAttributes'); Result := inherited GetAttributes; end; procedure TMySetProperty.GetProperties(Proc: TGetPropProc); begin ShowMessage('GetProperties'); inherited; end; function TMySetProperty.GetValue: string; begin ShowMessage('GetValue'); Result := inherited GetValue; end; end. 请注意: >我正在为具有TButtonOptions属性的所有组件注册新的属性编辑器(TMySetProperty).我也尝试过只为TButtonEx做,但结果是一样的. 所以问题是: 注意:此问题至少发生在Delphi XE2,XE3,XE4和XE5中.其他IDE未经过测试,但可能具有相同的行为. 解决方法
最后我得到了一个解决方案……在测试了我能想象到的一切 – 没有成功 – 我开始在DesignEditors.pas和DesignIntf??.pas单元中搜索“new”.读取GetEditorClass()函数,我发现它首先检查一个PropertyMapper.可以使用RegisterPropertyMapper()函数注册属性映射器.使用它而不是RegisterPropertyEditor()可以正常工作.这是我修改后的工作代码,也显示了一些有趣的应用程序:根据一些标准显示或隐藏基于集合的属性的一些选项:
unit Button1; interface uses System.SysUtils,DesignEditors; type TButtonOption = (boOptionA,boOptionB,boOptionC); TButtonOptions = set of TButtonOption; type TButtonEx = class(TButton) private FOptions: TButtonOptions; function GetOptions: TButtonOptions; procedure SetOptions(Value: TButtonOptions); published property Options: TButtonOptions read GetOptions write SetOptions default []; end; TMySetProperty = class(TSetProperty) private FProc: TGetPropProc; procedure InternalGetProperty(const Prop: IProperty); public procedure GetProperties(Proc: TGetPropProc); override; end; procedure Register; implementation uses TypInfo; // TButtonEx - sample component function TButtonEx.GetOptions: TButtonOptions; begin Result := FOptions; end; procedure TButtonEx.SetOptions(Value: TButtonOptions); begin if FOptions <> Value then begin FOptions := Value; end; end; // Returns TMySetProperty as the property editor used for Options in TButtonEx class function MyCustomPropMapper(Obj: TPersistent; PropInfo: PPropInfo): TPropertyEditorClass; begin Result := nil; if Assigned(Obj) and (Obj is TButtonEx) and SameText(String(PropInfo.Name),'Options') then begin Result := TMySetProperty; end; end; procedure Register; begin RegisterComponents('Samples',[TButtonEx]); // RegisterPropertyEditor does not work for set-based properties. // We use RegisterPropertyMapper instead RegisterPropertyMapper(MyCustomPropMapper); end; procedure TMySetProperty.GetProperties(Proc: TGetPropProc); begin // Save the original method received FProc := Proc; // Call inherited,but passing our internal method as parameter inherited GetProperties(InternalGetProperty); end; procedure TMySetProperty.InternalGetProperty(const Prop: IProperty); var i: Integer; begin if not Assigned(FProc) then begin // just in case Exit; end; // Now the interesting stuff. I just want to show boOptionA and boOptionB in Object inspector // So I call the original Proc in those cases only // boOptionC still exists,but won't be visible in object inspector for i := 0 to PropCount - 1 do begin if SameText(Prop.GetName,'boOptionA') or SameText(Prop.GetName,'boOptionB') then begin FProc(Prop); // call original method end; end; end; end. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |