如何使用最小/最大值对整数的属性编辑器进行编码?

时间:2010-08-21 03:19:46

标签: delphi vcl

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

我创建了一个只接受整数作为输入的编辑框。我没有使用TMaskEDit,因为我想从中派生出一堆其他的(只接受浮点数,并且浮点数和带有最小/最大属性的整数)。

这是我的代码。我认为问题是我的属性编辑器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.

原始问题:

This link给出了一个关于整数属性的属性编辑器的一个很好的例子。

如何更改此方法...

procedure TIntegerProperty.SetValue(const Value: string);
var
  L: Longint;
begin
  L := StrToInt(Value);                      { convert string to number }
  with GetTypeData(GetPropType)^ do  { this uses compiler data for type Integer }
    if (L < MinValue) or (L > MaxValue) then { make sure it is in range }
      { otherwise, raise exception }
      raise EPropertyError.Create(FmtLoadStr(SOutOfRange, [MinValue, MaxValue]));
  SetOrdValue(L);                       { if in range, go ahead and set value }
end;

...我想要的是男性一个新的属性,比如TIntegerMinMaxProperty,派生自TIntegerProperty,其中组件编辑器也显示整数的最小和最大允许值。

我正在考虑添加两个新的Integer属性,名为Minimum&amp;最大,但看起来我可以使用现有的MinValue&amp; MaxValue如果我只能发布它们,但我不知道如何...这些都不是

published  { available in the Object Inspector at design-time }
  property Minimum : Longint read  MinValue write  MinValue;
  property Minimum : Longint read FMinValue write FMinValue;

所以看起来我有两种选择并且两者都被困在了: - /

1)找到一种方法来发布那些MinValue&amp; MaxValue属性(可能更干净) 2)发布2个新房产,Minimujm&amp;最大值并计算如何在TIntegerProperty.SetValu()

中引用它们

并且感激不尽,因为这是我第一次进入属性编辑器(如果它有助于影响对此的答案,我的下一个属性将是一个接受十进制输入,有一个点)

1 个答案:

答案 0 :(得分:2)

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

published
  property MinValue;
  property MaxValue;

这将仅更改这些属性的可见性,并且如果支持其类型,则应使它们显示在对象检查器中。看看许多T ...与TCustom ...类对,其中T ...类通常只重新声明已发布的属性,以使它们显示在Object Inspector中。

修改(回复评论)

好的,如果你想要一些控制,请坚持下去,说一个TMyEdit说一个SomeFactor Integer属性,Object Inspector中的条目不仅会显示SomeFactor的值,还会显示允许的最小值和最大值对于SomeFactor,你需要一个代码属性编辑器来显示它自己的形式。

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

如果您想要的只是具有SomeFactor整数属性的TMyEdit,并且想要向您的TMyEdit控件添加SomeFactorMinValue和SomeFactorMaxValue,则可以通过FPropList条目的Instance引用访问GetValue / SetValue方法中的那些。请参阅TIntegerProperty编辑器中用于获取信息的SetOrdValue实现。它使用SetOrdProp(来自TypInfo)来设置Instance的值,该值应该是对包含SomeFactor属性的TMyEdit控件的引用。通过一些转换,您应该可以使用SomeFactorMinValue和SomeFactorMaxValue属性。

注意:不确定FPropList如何获取其条目。它通过构造函数得到了它的计数。你可能需要自己做一些进一步的调查。 (出于某种原因,Ctrl-click和代码洞察决定在我的D2009中继续罢工。)