问题
Hopefully this is a quick one, and "Easy if you know how"...
I'm writing some kind of Serialization/Scripting class to generate forms on the fly, I tried setting a TColor the other day and got an error
clBtnFace is not a valid integer value
or something like that and found that the constants used in properties are registered so that they can be converted to integer, and so I added code to fetch the converter and use it.
Now today I have a similar issue with the ModalResult property but I can't work out how the DFM deserializer handles this property? Any ideas how it converts mrOK
into an integer?
Edit
There isn't much of an example to give:
PropInfo := GetPropInfo(Instance, PropertyName);
SetPropValue(Instance, PropInfo, PropertyValue);
Where in this case Instance is a TButton, PropertyName is 'ModalResult' and PropertyValue is 'mrOK'
回答1:
It doesn't need to:
const
{ Dialog Box Command IDs }
{$EXTERNALSYM IDOK}
IDOK = 1; ID_OK = IDOK;
const
mrNone = 0;
mrOk = idOk;
type
TModalResult = Low(Integer)..High(Integer);
TModalResult is in someway a subrange of Integer and mrOK is just an Integer constant.
回答2:
Don't really want to answer my own question but since no one else has....
There is no converter for ModalResults, Delphi stores the Integer representation in the DFM as VilleK says in the comment to the question. As a solution I've registered a new converter
const
ModalResults: array[0..10] of TIdentMapEntry = (
(Value: mrNone; Name: 'mrNone'),
(Value: mrOk; Name: 'mrOk'),
(Value: mrCancel; Name: 'mrCancel'),
(Value: mrAbort; Name: 'mrAbort'),
(Value: mrRetry; Name: 'mrRetry'),
(Value: mrIgnore; Name: 'mrIgnore'),
(Value: mrYes; Name: 'mrYes'),
(Value: mrNo; Name: 'mrNo'),
(Value: mrAll; Name: 'mrAll'),
(Value: mrNoToAll; Name: 'mrNoToAll'),
(Value: mrYesToAll; Name: 'mrYesToAll'));
function ModalResultToIdent(ModalResult: Longint; var Ident: string): Boolean;
begin
Result := IntToIdent(ModalResult, Ident, ModalResults);
end;
function IdentToModalResult(const Ident: string; var ModalResult: Longint): Boolean;
begin
Result := IdentToInt(Ident, ModalResult, ModalResults);
end;
initialization
RegisterIntegerConsts(TypeInfo(TModalResult), IdentToModalResult, ModalResultToIdent);
回答3:
Both of your examples you have given are sub ranges of numeric values. As such RTTI only really knows of the underlying Integer. Other examples include TCursor
, TFontCharset
and TTabOrder
.
If you have a type like this:
TEnum = (exOne,exTwo,exThree);
You can use RTTI to get and set 'exOne'
, 'exTwo'
and 'exThree'
as Strings.
This can be done through these methods in TypInfo.pas
function GetEnumName(TypeInfo: PTypeInfo; Value: Integer): string;
function GetEnumValue(TypeInfo: PTypeInfo; const Name: string): Integer;
If you want to use the constants that are defined for colors or ModalResults you must build your won dictionary of constant name to value, that you could then implement into your own serialization routines.
TColor implements a static dictionary called Colors, which could be used if you only use the 52 colors that it supports.
Colors: array[0..51] of TIdentMapEntry = (
(Value: clBlack; Name: 'clBlack'),
...
(Value: clWindowText; Name: 'clWindowText'));
You can then do the following to get the color name.
var
ColorName : String;
begin
// Color Value must be between 0 and 51 otherwise index out of bounds
ColorName := Colors[ColorValue];
end;
You then could loop through the items in the Colors Array to determine the value for a given name.
来源:https://stackoverflow.com/questions/3388014/how-does-delphi-convert-modalresult-properties