Edit: original question below, but I revise it now that I have some code to post....
I am created an editbox which only accepts an integer as input. I didn't use a TMaskEDit because I want to derive a bunch of others from it (only accepts float, and both float & integer with min/max properties).
Here's my code. I think the problem is that my property editor SetValue() is never being called, so maybe I haven't registered it correctly?
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.
Original question:
This link gives a pretty good example of a property editor for an integer property.
How can I change this method ...
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;
... what I want is to male a new property, say TIntegerMinMaxProperty
, derived from TIntegerProperty
where the component editor also shows minimum and maximum permitted values for the integer.
I was thinking of adding two new Integer properties, called Minimum & Maximum, but it looks like I could maybe use the existing MinValue & MaxValue if I could only publish them, but I don't see how ... neither of these compile
published { available in the Object Inspector at design-time }
property Minimum : Longint read MinValue write MinValue;
property Minimum : Longint read FMinValue write FMinValue;
So it looks like I have two options and am stuck at both :-/
1) find a way to publish those MinValue & MaxValue properties (which is probably cleaner) 2) publish 2 new properties, Minimujm & Maximum and figure how to refer to them in TIntegerProperty.SetValu()
And help gratefully appreciated as this is my first sortie into property editors (in case it helps influence the answer to this, my next property will be one that accepts decimal input, with a a point)