加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 创建自定义TSetProperty属性编辑器

发布时间:2020-12-15 09:48:57 所属栏目:大数据 来源:网络整理
导读:我正在尝试为某个自定义组件创建自定义属性编辑器.自定义属性编辑器用于编辑某些set属性,例如 type TButtonOption = (boOption1,boOption2,boOption3); TButtonOptions = set of TButtonOption; 我的属性编辑器来自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做,但结果是一样的.
>我在自定义属性编辑器的所有重写方法中添加了ShowMessage()调用,并且这些方法永远不会被调用.
>我已经调试了包并且RegisterPropertyEditor()执行了.尽管如此,重写方法中的自定义代码永远不会执行.
>我已经看到其他第三方组件使用在较旧的Delphi IDE中运行的此类属性编辑器(TSetProperty后代),我在代码中找不到任何相关的差异.也许Delphi XE2需要其他东西?

所以问题是:
为什么我的自定义属性编辑器没有注册/工作?

注意:此问题至少发生在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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读