Delphi 如何为具有最小/最大值的整数编写属性编辑器?

Delphi 如何为具有最小/最大值的整数编写属性编辑器?,delphi,vcl,Delphi,Vcl,编辑:下面的原始问题,但我现在修改它,因为我有一些代码发布 我创建了一个editbox,它只接受整数作为输入。我没有使用TMaskEDit,因为我想从中派生出一系列其他函数(只接受float,以及具有min/max属性的float和integer) 这是我的密码。我认为问题在于我的属性编辑器SetValue()从未被调用,所以可能我没有正确注册它 unit IntegerEditBoxMinMax; // An edit box which only accepts integer valu

编辑:下面的原始问题,但我现在修改它,因为我有一些代码发布

我创建了一个editbox,它只接受整数作为输入。我没有使用TMaskEDit,因为我想从中派生出一系列其他函数(只接受float,以及具有min/max属性的float和integer)

这是我的密码。我认为问题在于我的属性编辑器SetValue()从未被调用,所以可能我没有正确注册它

unit IntegerEditBoxMinMax;
  // An edit box which only accepts integer values between the stated mix/max values

interface

uses
  SysUtils, Classes, Controls, StdCtrls, DesignEditors;

type

  TMinimumProperty = class(TIntegerProperty)
    procedure SetValue(const newValue: string); override;
  end;  

  TMaximumProperty = class(TIntegerProperty)
    procedure SetValue(const newValue: string); override;
  end;  

  TValueProperty = class(TIntegerProperty)
    procedure SetValue(const newValue: string); override;
  end; 


  TIntegerEditBoxMinMax = class(TCustomEdit)
    private
      FMinimum : Integer;
      FMaximum : Integer;
      FValue   : Integer;

    published  { Published declarations - available in the Object Inspector at design-time }
      property Minimum  : Integer read FMinimum write FMinimum;
      property Maximum  : Integer read FMaximum write FMaximum;
      property Value    : Integer read FValue   write FValue;

  end;  // of class TIntegerEditBoxMinMax()

procedure Register;

implementation

Uses TypInfo, Consts, DesignIntf, Dialogs;

  procedure Register;
  begin
    RegisterComponents('Standard', [TIntegerEditBoxMinMax]);
    RegisterPropertyEditor(TypeInfo(Integer), TIntegerEditBoxMinMax, 'Minumim', TMinimumProperty);
    RegisterPropertyEditor(TypeInfo(Integer), TIntegerEditBoxMinMax, 'Maximum', TMaximumProperty);
    RegisterPropertyEditor(TypeInfo(Integer), TIntegerEditBoxMinMax, 'Value',   TValueProperty);
  end;

  procedure TMinimumProperty.SetValue(const newValue: string);
    var L: Longint;
        min, max : Integer;
        propInfo: PPropInfo;
        exceptionString : String;
  begin
MessageDlg('editor !!', mtWarning, [mbOK], 0);   // This is never seen !!
    L := StrToInt(newValue);                { convert string to number }
    with GetTypeData(GetPropType())^ do     { this uses compiler data for type Integer }
      min  := GetOrdProp(GetComponent(0), 'Minimum');
      max  := GetOrdProp(GetComponent(0), 'Maximum');

      if min > max then
      begin
        exceptionString := 'Minimum value (%l) cannot be greater than maximum (%l)';
        raise Exception.CreateResFmt(@exceptionString, [min, max]);
      end;

      if L < min then
      begin
        PropInfo := GetPropInfo();
        SetOrdProp(Nil , propInfo, Int64(min));
        exceptionString := 'Value (%l) less than new minimum (%l); value set to minimum';
        raise Exception.CreateResFmt(@exceptionString, [L, min]);
      end;

    SetOrdValue(L);                                { if in range, go ahead and set value }
  end;  // of TMinimumProperty.SetValue()


  procedure TMaximumProperty.SetValue(const newValue: string);
    var L: Longint;
        min, max : Integer;
        propInfo: PPropInfo;
        exceptionString : String;
  begin
    L := StrToInt(newValue);                { convert string to number }
    with GetTypeData(GetPropType())^ do     { this uses compiler data for type Integer }
      min  := GetOrdProp(Nil, 'Minimum');
      max  := GetOrdProp(Nil, 'Maximum');

      if max < min then
      begin
        exceptionString := 'Maximum value (%l) cannot be less than minimum (%l)';
        raise Exception.CreateResFmt(@exceptionString, [max, min]);
      end;

      if L > max then
      begin
        PropInfo := GetPropInfo();
        SetOrdProp(Nil , propInfo, Int64(max));
        exceptionString := 'Value (%l) more than new maximum (%l); value set to maximum';
        raise Exception.CreateResFmt(@exceptionString, [L, max]);
      end;

    SetOrdValue(L);      { if in range, go ahead and set value }
  end;  // of TMaximumProperty.SetValue()


  procedure TValueProperty.SetValue(const newValue: string);
    var L: Longint;
        min, max: Integer;
  begin
    L := StrToInt(newValue);             { convert string to number }
    // see also http://www.freepascal.org/docs-html/rtl/typinfo/getobjectprop.html
    // for other useful functions
    with GetTypeData(GetPropType())^ do  { this uses compiler data for type Integer }
    begin
      min := GetOrdProp(Nil, 'Minimum');
      max := GetOrdProp(Nil, 'Maximum');
      // for Float, etc, see http://www.blong.com/Conferences/BorConUK98/DelphiRTTI/CB140.htm

      if (L < min) or (L > max) then              { make sure it's in range... }
        raise Exception.CreateResFmt(@SOutOfRange, [min, max]);   { ...otherwise, raise exception }

      SetOrdValue(L);    { if in range, go ahead and set value }
    end;
  end;  // of TMinimumProperty.SetValue()


end.
看来我有两个选择,而且两个都被卡住了:-/

1) 找到一种方法来发布那些MinValue和MaxValue属性(可能更干净) 2) 发布2个新属性,Minimujm和Maximum,并了解如何在TIntegerProperty.SetValu()中引用它们


非常感谢您的帮助,因为这是我第一次访问属性编辑器(如果它有助于影响此问题的答案,我的下一个属性将是一个接受带a点的十进制输入的属性)

如果MinValue和MaxValue已经是组件/控件的属性,但当前为公共且未发布。您只需在“已发布”部分重新声明它们,但只需按名称:

published
  property MinValue;
  property MaxValue;
这将只更改这些属性的可见性,如果支持它们的类型,则应使它们显示在对象检查器中。看一看很多的T。。。对TCustom。。。类对,其中T。。。类通常只重新声明已发布的属性,以使它们显示在对象检查器中

编辑(回应评论)

好的,等等,如果你想有一些控制,比如说一个带有SomeFactor整数属性的TMyEdit,对象检查器中的条目不仅会显示SomeFactor的值,还会显示SomeFactor允许的最小值和最大值,你需要一个代码属性编辑器来显示它自己的形式

当然,您可以将MinValue和MaxValue添加到TIntegerProperty的子代,并在GetValue和SetValue方法的重写中使用它们(这就是它们毕竟是虚拟的原因),然后注册此TMinMaxIntegerProperty以供SomeFactor属性使用。但是,这不会使MinValue和MaxValue显示在对象检查器中,因为TIntegerProperty基本上只编辑/显示SomeFactor的实际值。要实现所需的功能,必须对自定义属性编辑器的子体进行编码,例如,显示要编辑和格式化字符串的表单的子体。我使用的组件中有很多示例,但是我当然不能在这里发布它们的代码

如果您想要的只是一个带有SomeFactor integer属性的TMyEdit,并且希望向TMyEdit控件添加SomeFactorMirValue和SomeFactorMaxValue,那么您可以通过FPropList项的实例引用访问GetValue/SetValue方法中的那些。有关详细信息,请参阅TIntegerProperty编辑器中使用的SetOrdValue实现。它使用SetOrdProp(来自TypInfo)设置实例上的值,该值应该是对持有SomeFactor属性的TMyEdit控件的引用。通过一些转换,您应该能够使用SomeFactorMaxValue和SomeFactorMaxValue属性


注意:不确定FPropList如何获取其条目。但它通过构造函数获得其计数。你可能需要自己在这里做进一步的调查。(由于某些原因,Ctrl单击和code insight决定在我的D2009中罢工。)

+1以获取帮助。当我尝试编译时,编译器抱怨它们不是基类的成员-那么它们来自哪里??顺便说一句,我现在意识到引用的链接只是从帮助文件中逐字复制的,如果选择“find”和“GetTypeData”Hmmm,那么MinVal和MaxVal来自GetTypeData(GetPropType),也就是说它们是整数的最小值和最大值。所以,我想这是选项2-我必须声明我自己的最小和最大属性。。。但是如何从SetValue()中访问它们呢?非常棒的更新!(希望我能再次+1)我会更新这个问题,以显示到目前为止我拥有的代码。也许你可以看看?如果你继续评论,我将继续+1,直到它开始工作。感谢1000000的帮助,到目前为止,您将不得不充实许多对TypInfo函数的调用。将
Nil
传递给
GetOrdProp
SetOrdProp
函数将导致访问冲突。我还看到许多其他TypInfo函数,您还没有为它们编码参数。除此之外,你的代码似乎在正确的轨道上。(+1)我将奖励你答案,因为你做了这么多的工作,谢谢。我已经对代码做了很多修改,并且正在取得进展。如果我需要更多的帮助,那么我将发布另一个问题。
published  { available in the Object Inspector at design-time }
  property Minimum : Longint read  MinValue write  MinValue;
  property Minimum : Longint read FMinValue write FMinValue;
published
  property MinValue;
  property MaxValue;