Creating custom TSetProperty property editor

前端 未结 1 355
忘掉有多难
忘掉有多难 2021-01-13 00:41

I\'m trying to create a custom property editor for some custom component. The custom property editor is intended to edit some set property, like

type
  TButt         


        
1条回答
  •  暖寄归人
    2021-01-13 01:30

    Finally I got a solution... After testing everything I could imagine - without success - I started searching for something "new" in DesignEditors.pas and DesignIntf.pas units. Reading GetEditorClass() function, I discovered that it first checks for a PropertyMapper. A property mapper can be registered using RegisterPropertyMapper() function. Using it instead of RegisterPropertyEditor() works just as expected. Here is my modified, working code, also showing some interesting application for this: show or hide some options of my set-based property, based on some criteria:

    unit Button1;
    
    interface
    
    uses
      System.SysUtils, System.Classes, Vcl.Controls, Vcl.StdCtrls,
      DesignIntf, 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.
    

    0 讨论(0)
提交回复
热议问题