Delphi 的RTTI机制浅探2

转自http://blog.sina.com.cn/s/blog_53d1e9210100ukdx.html

本文上篇基本上是 RTTI 入门介绍,续篇介绍了所有 TypInfo.pas 中的函数,附加了Classes.pas、Graphics.pas、Controls.pas 中的几个 RTTI相关函数。对于关键函数的代码提供汇编注释。希望本文覆盖了 Delphi 中 80% 的 RTTI函数。时间仓促,错误难免,敬请批评指正。


目 录
===============================================================================
⊙ GetTypeData 函数
⊙ GetPropInfo 函数
⊙ FindPropInfo 函数
⊙ GetPropInfos 函数
⊙ SortPropList 函数
⊙ GetPropList 函数
------------------------------------------------------
⊙ GetObjectPropClass 函数
⊙ PropType / PropIsType 函数
⊙ IsPublishedProp 函数
⊙ IsStoredProp 函数
⊙ FreeAndNilProperties 函数
⊙ SetToString / StringToSet 函数
⊙ GetEnumName / GetEnumValue / GetEnumNameValue 函数
------------------------------------------------------
⊙ GetOrdProp 函数详解
⊙ SetOrdProp 函数
⊙ GetEnumProp / SetEnumProp 函数
⊙ GetSetProp / SetSetProp 函数
⊙ GetObjectProp / SetObjectProp 函数
⊙ GetStrProp / SetStrProp 函数
⊙ GetFloatProp / SetFloatProp 函数
⊙ GetPropValue / SetPropValue 函数
⊙ TPublishableVariantType class
------------------------------------------------------
⊙ RegisterClass / FindClass 系列函数 (Classes.pas)
⊙ IdentToInt / IntToIdent 系列函数 (Classes.pas)
===============================================================================


正 文
===============================================================================
⊙ GetTypeData 函数
===============================================================================
GetTypeData 函数根据 TTypeInfo 指针获得 TTypeData 的地址。

function GetTypeData(TypeInfo: PTypeInfo): PTypeData;
asm
       XOR    EDX,EDX                       ; EDX 清零
       MOV    DL,[EAX].TTypeInfo.Name.Byte[0]   ; 获得 Name字符串长度
       LEA    EAX,[EAX].TTypeInfo.Name[EDX+1]   ; 获得 TTypeData的地址
end;

===============================================================================
⊙ GetPropInfo 函数
===============================================================================
GetPropInfo 函数用于获得属性的 RTTI 指针PPropInfo。它有四种重载形式,后面三种重载的实现都是调用第一种形式。AKinds 参数用于限制属性的类型,如果得到的PPropInfo 不属于指定的类型,则返回 nil。

  function GetPropInfo(TypeInfo: PTypeInfo; constPropName: string): PPropInfo;

  function GetPropInfo(Instance: TObject; constPropName: string;
    AKinds: TTypeKinds = []):PPropInfo;
  function GetPropInfo(AClass: TClass; constPropName: string;
    AKinds: TTypeKinds = []):PPropInfo;
  function GetPropInfo(TypeInfo: PTypeInfo; constPropName: string;
    AKinds: TTypeKinds):PPropInfo;

===============================================================================
⊙ FindPropInfo 函数
===============================================================================
FindPropInfo 函数根据属性名称获得属性的 RTTI 指针,它只是在 GetPropInfo函数的基础上加上了错误检查功能,如果没有属性 RTTI 信息,则触发 EPropertyError 异常。

function FindPropInfo(Instance: TObject; const PropName: string):PPropInfo;
function FindPropInfo(AClass: TClass; const PropName: string):PPropInfo;

===============================================================================
⊙ GetPropInfos 函数
===============================================================================
GetPropInfos 函数的功能是把一个类(class)所有属性 RTTI 指针 PPropInfo 填充至传入的参数PPropList 数组中。

注意:这个函数不负责分配该数组的内容,使用前必须根据属性的数量分配足够的空间。该数组结束后必须清除分配的内容。

  procedure GetPropInfos(TypeInfo: PTypeInfo;PropList: PPropList);

注:使用 GetPropList 实现相同的功能更方便。

===============================================================================
⊙ SortPropList 函数
===============================================================================
SortPropList 可以对 GetPropInfos 函数填充的属性信息指针数组按属性名称排序。

  procedure SortPropList(PropList: PPropList;PropCount: Integer);

在 VCL 中 SortPropList 只被 GetPropList 函数使用。

===============================================================================
⊙ GetPropList 函数
===============================================================================
GetPropList 函数同 GetPropInfos 一样,填充 PPropList 数组。GetPropList 实际上是调用GetPropInfos 进行填充工作,最后返回已填充的属性的数量。

  function GetPropList(TypeInfo: PTypeInfo;TypeKinds: TTypeKinds;
    PropList: PPropList;SortList: Boolean): Integer;

  function GetPropList(TypeInfo: PTypeInfo; outPropList: PPropList): Integer;
  function GetPropList(AObject: TObject; outPropList: PPropList): Integer;

注意:GetPropList 的内存分配有点混乱,上面第一个 GetPropList 必须自己分配 PPrpList数组的内存,后面二个 GetPropList 会自动分配 PPropList 数组的内存。造成这种情况的原因是:第一个GetPropList 可以设置 TypeKinds参数限制只返回指定类型的属性,这样就不能直接得到可能返回的属性数量。TypeKinds 参数可以设置为tkAny,表示返回所有数据类型的属性。

第一个 GetPropList 函数可以设置 SortList 参数对属性名称进行排序。它实际上是调用第二个 GetPropList并调用 SortPropList 函数执行排序。

注意:PPropList 不再使用的时候,要记得使用 FreeMem 函数清除数组内存(根据返回值是否大于1)。

===============================================================================
⊙ GetObjectPropClass 函数
===============================================================================
GetObjectPropClass 函数用于返回对象类型的属性所属的类(class)。

  function GetObjectPropClass(Instance: TObject;PropInfo: PPropInfo): TClass;
  function GetObjectPropClass(Instance: TObject;const PropName: string): TClass;
  function GetObjectPropClass(PropInfo:PPropInfo): TClass;

这个函数被 SetObjectProp 函数使用,用于参数检验。

===============================================================================
⊙ PropType / PropIsType 函数
===============================================================================
PropType 函数用于获得属性的数据类型。

  function PropType(Instance: TObject; constPropName: string): TTypeKind;
  function PropType(AClass: TClass; constPropName: string): TTypeKind;

PropIsType 判断属性是否属于某种数据类型。它调用 PropType 实现功能。

  function PropIsType(Instance: TObject; constPropName: string;
    TypeKind: TTypeKind):Boolean;
  function PropIsType(AClass: TClass; constPropName: string;
    TypeKind: TTypeKind):Boolean;

===============================================================================
⊙ IsPublishedProp 函数
===============================================================================
IsPublishedProp 函数用于判断属性是否是 published 属性,它通过检查该属性 RTTI 指针是否等于 nil来实现功能。

  function IsPublishedProp(Instance: TObject;const PropName: string): Boolean;
  function IsPublishedProp(AClass: TClass; constPropName: string): Boolean;

IsPublishedProp 函数没有被 VCL 使用。

===============================================================================
⊙ IsStoredProp 函数
===============================================================================
IsStoredProp 函数使用属性信息中的 TPropInfo.StoredProp 函数指针来调用属性定义时用 stored关键字定义的函数的结果。

这个函数被用于 Delphi 持续机制,TWriter.WriteProperties 方法调用 IsStoredProp判断是否需要把该属性的值写入流中。

  function IsStoredProp(Instance: TObject;PropInfo: PPropInfo): Boolean;
  function IsStoredProp(Instance: TObject; constPropName: string): Boolean;

===============================================================================
⊙ FreeAndNilProperties 函数
===============================================================================
FreeAndNilProperties 函数用于清除一个对象的所有 published 的对象类型的属性的对象。这个函数调用GetObjectProp 执行获得对象属性的对象句柄,并调用对象的 Free 方法清除这个对象,然后调用 SetObjectProp设置该属性为 nil。

  procedure FreeAndNilProperties(AObject:TObject);

我不知道这个函数能用在哪里,至少 VCL 中没有使用这个函数。

===============================================================================
⊙ SetToString / StringToSet 函数
===============================================================================
SetToString 和 StringToSet 是两个 RTTI辅助函数,它们把集合值转换为字符串,或者把字符串转换为集合值。

  function SetToString(PropInfo: PPropInfo; Value:Integer;
    Brackets: Boolean = False):string;

  function StringToSet(PropInfo: PPropInfo; constValue: string): Integer;

注意:这里的集合值最多只能包含 32 个元素(4 bytes),这是集合 RTTI 的限制。

===============================================================================
⊙ GetEnumName / GetEnumValue / GetEnumNameValue 函数
===============================================================================
GetEnumName 函数根据枚举整数值返回枚举字符串。它可以返回以下三种枚举名称:

  Integer:直接返回 IntToStr(Integer)
  Boolean:返回 True/False
  Enum   :返回 TTypeData^.NameList中存储的枚举名称

  function GetEnumName(TypeInfo: PTypeInfo; Value:Integer): string;

GetEnumValue 函数根据枚举字符串返回枚举整数值。它与 GetEnumName 类似,可以返回三种枚举的整数值,但对于Enum 类型,它调用了 GetEnumNameValue 函数。

  function GetEnumValue(TypeInfo: PTypeInfo; constName: string): Integer;

GetEnumNameValue 函数与 GetEnumValue函数功能差不多,但它是个汇编函数,只能返回纯枚举类型的值。其工作原理也是匹配 TTypeData^.NameList 值。

  function GetEnumNameValue(TypeInfo: PTypeInfo;const Name: string): Integer;

注意:GetEnumNameValue 隐藏在 Implementation 段,不能直接使用,它是为 GetEnumValue函数服务的。

===============================================================================
⊙ GetOrdProp 函数详解
===============================================================================
GetOrdProp 是 Delphi RTTI 中使用频繁的函数。GetOrdProp 根据对象句柄和对象属性的 TPropInfo指针获得对象的属性值。它的返回值是 Longint,需要强制转换成相应的属性类型才能使用。

  function GetOrdProp(Instance: TObject; PropInfo:PPropInfo): Longint;

GetOrdProp 调用 TPropInfo.GetProc 函数指针得到属性的返回值。它的工作过程是:

  如果该属性的类型是 class 类型,那么返回值是 4 个字节(对象句柄)。
    否则通过 TTypeData.OrdType得到返回值的类型,存储在 BL 中。
    { TOrdType = (otSByte,otUByte, otSWord, otUWord, otSLong, otULong); }
  检查 TPropInfo.GetProc 的第一个字节(注意是 GetProc指针的第一个字节):
    如果 GetProc[0] = $FF,说明GetProc 是 field offset;
    如果 GetProc[0] = $FE,说明GetProc 是 virtual method offset;
    如果 GetProc[0]< $FE,说明 GetProc 是 static method;
  然后根据不同的 GetProc 类型解析后,调用 GetProc。
  根据 BL 中存储的类型符号信息修正返回值(EAX)的符号信息。
  根据 BL 中存储的类型的大小裁剪返回值 EAX 为 EAX/AX/AL。
  EAX(AX/AL) 即是返回的属性值。

GetOrdProp 的汇编代码及注释如下:

function GetOrdProp(Instance: TObject; PropInfo: PPropInfo):Longint;
asm
       PUSH   EBX
       PUSH   EDI
       MOV    EDI,[EDX].TPropInfo.PropType       ; EDI <-PPTypeInfo
       MOV    EDI,[EDI]                       ; EDI <- PTypeInfo
       MOV    BL,otSLong                      ; BL  <-otSLong
       CMP    [EDI].TTypeInfo.Kind,tkClass       ; if Prop is Class
       JE     @@isClass                       ; jmp @@isClass
       XOR    ECX,ECX                         ; ECX <-0
       MOV    CL,[EDI].TTypeInfo.Name.Byte[0]    ; CL  <- NameStrLength
       MOV    BL,[EDI].TTypeInfo.Name[ECX+1].TTypeData.OrdType
                                            ; BL <- Prop OrdType
@@isClass:
       MOV    ECX,[EDX].TPropInfo.GetProc        ; ECX <-GetProc Addr
       CMP    [EDX].TPropInfo.GetProc.Byte[3],$FE ; cmp HiByte(GetProc),$FE
       MOV    EDX,[EDX].TPropInfo.Index          ; EDX<- Prop Index
       JB     @@isStaticMethod                 ; if below$FE
       JA     @@isField                       ; if is $FF

       {      the GetProc is a virtual method }  ; if is $FE
       MOVSX   ECX,CX               { signextend slot offs }
       ADD    ECX,[EAX]             { vmt   + slotoffs     }
       CALL    dwordptr [ECX]        { call vmt[slot]       }
       JMP    @@final
@@isStaticMethod:
       CALL    ECX               ; callGetProc directly
       JMP    @@final
@@isField:
       AND    ECX,$00FFFFFF       ; clear HiByte(GetProc)
       ADD    ECX,EAX            ; ECX <- Field Addr
       MOV    AL,[ECX]            ; AL <- Field Addr[0]
       CMP    BL,otSWord          ; if OrdType <otSWord
       JB     @@final            ; Exit
       MOV    AX,[ECX]            ; else AX<- Field[0..1]
       CMP    BL,otSLong          ; if OrdType <otSLong
       JB     @@final            ; Exit
       MOV    EAX,[ECX]           ; else EAX<- Field[0..3]
@@final:
       CMP    BL,otSLong          ; if OrdType>= otSLong
       JAE     @@exit            ; Exit
       CMP    BL,otSWord          ; if OrdType>= otSWord
       JAE     @@word            ; jmp @@word
       CMP    BL,otSByte          ; if OrdType = otSByte
       MOVSX   EAX,AL            ; AL <- Sign(EAX)
       JE     @@exit             ; Exit
       AND    EAX,$FF            ; clear HiWord(EAX)
       JMP     @@exit            ; Exit
@@word:
       MOVSX   EAX,AX            ; AX <= Sign(EAX)
       JE     @@exit             ; if OrdType = otSWord thenExit
       AND    EAX,$FFFF           ; clearHiWord(EAX)
@@exit:
       POP    EDI
       POP    EBX
end;

TypInfo.pas 中重载了 GetOrdProp 函数,将 PPropInfo 参数替换为PropName,方便程序员调用,它其实也是调用了上面介绍的 GetOrdProp 函数。

function GetOrdProp(Instance: TObject; const PropName: string):Longint;
begin
  Result := GetOrdProp(Instance,FindPropInfo(Instance, PropName));
end;

下面是使用 GetOrdProp 的例子:

  Self.Width := Self.Width - GetOrdProp(Self,'Height');

上面的语句相当于:

  Self.Width := Self.Width - Self.Height;

* 后文介绍的 Get___Prop 系列函数或者调用本函数,或者它的实现方法与本函数类似。

===============================================================================
⊙ SetOrdProp 函数
===============================================================================
SetOrdProp 函数是 GetOrdProp 的逆过程,它调用 TPropInfo.SetProc函数指针设置对象的属性值。SetProc 指针的第一个字节的意义同 GetProc 一样,也是表示该 SetProc是字段偏移、虚方法偏移和静态方法。

  procedure SetOrdProp(Instance: TObject;PropInfo: PPropInfo; Value: Longint);

SetOrdProc 也根据属性名称重载了:

  procedure SetOrdProp(Instance: TObject; constPropName: string; Value: Longint);

由于 SetOrdProp 的汇编代码与 GetOrdProp 的几乎一样,在此就不再列出。作为练习,试用一下:

  SetOrdProp(Self, 'Height', Self.Height +10);

该语句的功能相当于:

  Self.Height := Self.Height + 10;

* 后文介绍的 Set___Prop 系列函数或者调用本函数,或者它的实现方法与本函数类似。

===============================================================================
⊙ GetEnumProp / SetEnumProp 函数
===============================================================================
GetEnumProp 函数获取枚举类型属性的枚举字符串,它调用 GetEnumName 转换 GetOrdProp的返回值。

  function GetEnumProp(Instance: TObject;PropInfo: PPropInfo): string;
  function GetEnumProp(Instance: TObject; constPropName: string): string;

SetEnumProp 函数使用枚举字符串设置枚举类型属性值,它调用 GetEnumValue 转换枚举字符串后再调用SetOrdProp 设置属性值。

  procedure SetEnumProp(Instance: TObject;PropInfo: PPropInfo;
    const Value: string);
  procedure SetEnumProp(Instance: TObject; constPropName: string;
    const Value: string);

===============================================================================
⊙ GetSetProp / SetSetProp 函数
===============================================================================
GetSetProp 函数用于获取集合类型属性的字符串值,它也是调用 GetOrdProp 获得属性值,然后调用SetToString 函数把数值转换成字符串。

注意:GetOrdProp 函数返回值是 Integer,那么它是如何表示可以存储 256 个元素的集合类型呢?答案是:如果是published 集合属性,那么该集合最大只能是 4 个字节,也就是最多只能存储 32 个元素。

  function GetSetProp(Instance: TObject; PropInfo:PPropInfo;
    Brackets: Boolean):string;
  function GetSetProp(Instance: TObject; constPropName: string;
    Brackets: Boolean = False):string;

SetSetProp 函数用于通过字符串设置集合类型属性的值。它先调用 StringToSet 函数把字符串转换为整数值,然后使用SetOrdProp 函数设置属性值。

  procedure SetSetProp(Instance: TObject;PropInfo: PPropInfo;
    const Value: string);
  procedure SetSetProp(Instance: TObject; constPropName: string;
    const Value: string);

试验:  SetSetProp(Self, 'BorderIcons','[biSystemMenu]');


===============================================================================
⊙ GetObjectProp / SetObjectProp 函数
===============================================================================
对象实际上是指针,也就是整数值,所以 GetObjectProp 直接调用 GetOrdProp 就可以了。

MinClass 参数指定得到的 Object 必须属于某个 class ,如果不是则返回 nil 。

  function GetObjectProp(Instance: TObject;PropInfo: PPropInfo;
    MinClass: TClass = nil):TObject;
  function GetObjectProp(Instance: TObject; constPropName: string;
    MinClass: TClass = nil):TObject;

SetObjectProp 用于设置属性的对象句柄。ValidateClass参数表示是否需要检查传入的对象类型与属性信息的类信息是否兼容。

  procedure SetObjectProp(Instance: TObject;PropInfo: PPropInfo;
    Value: TObject;ValidateClass: Boolean = True);
  procedure SetObjectProp(Instance: TObject; constPropName: string;
    Value: TObject);

例子:
  var
    MyFont: TFont;
  begin
    MyFont := TFont.Create;
    MyFont.Height := 20;
    SetObjectProp(Self, 'Font',MyFont);
  end;

===============================================================================
⊙ GetStrProp / SetStrProp 函数
===============================================================================
GetStrProp 函数用于获得字符串类型的属性值。

  function GetStrProp(Instance: TObject; PropInfo:PPropInfo): string;
  function GetStrProp(Instance: TObject; constPropName: string): string;

由于 Delphi 支持三种类型的字符串,GetStrProp 根据字符串的类型,分别调用三个获得字符串属性值的函数:

  case PropInfo^.PropType^.Kind of
    tkString:GetShortStrPropAsLongStr(Instance, PropInfo, Result);
    tkLString:GetLongStrProp(Instance, PropInfo, Result);
    tkWString:GetWideStrPropAsLongStr(Instance, PropInfo, Result);
  end;

其中 GetShortStrPropAsLongStr 又调用了GetShortStrProp;GetWideStrPropAsLongStr 又调用了GetWideStrProp,进行字符串间的类型转换。

SetStrProp 函数用于设置字符串类型的属性值。它的实现方法与 GetStrProp 类似。

  procedure SetStrProp(Instance: TObject;PropInfo: PPropInfo;
    const Value: string);
  procedure SetStrProp(Instance: TObject; constPropName: string;
    const Value: string);

===============================================================================
⊙ GetFloatProp / SetFloatProp 函数
===============================================================================
GetFloatProp 用于获得浮点型属性值。它将 Single(4 bytes)、Double(8 bytes)、Comp(8bytes)、Currency(8 bytes) 类型的浮点数属性转换为 Extented(10 bytes) 类型返回。

  function GetFloatProp(Instance: TObject;PropInfo: PPropInfo): Extended;
  function GetFloatProp(Instance: TObject; constPropName: string): Extended;

SetFloatProp 用于设置浮点型属性值。它的实现方法与 GetFloatProp 类似。

  procedure SetFloatProp(Instance: TObject;PropInfo: PPropInfo;
    const Value: Extended);
  procedure SetFloatProp(Instance: TObject; constPropName: string;
    const Value: Extended);

===============================================================================
⊙ GetVariantProp / SetVariantProp
===============================================================================
GetVariantProp 函数用于获得 Variant 类型的属性值。

  function GetVariantProp(Instance: TObject;PropInfo: PPropInfo): Variant;
  function GetVariantProp(Instance: TObject; constPropName: string): Variant;

SetVariantProp 函数用于设置 Variant 类型的属性值。

  procedure SetVariantProp(Instance: TObject;PropInfo: PPropInfo;
    const Value: Variant);
  procedure SetVariantProp(Instance: TObject;const PropName: string;
    const Value: Variant);

===============================================================================
⊙ GetMethodProp / SetMethodProp
===============================================================================
GetMethodProp 函数用于获得 Method 类型的属性值。

  function GetMethodProp(Instance: TObject;PropInfo: PPropInfo): TMethod;
  function GetMethodProp(Instance: TObject; constPropName: string): TMethod;

SetMethodProp 函数用于设置 Method 类型的属性值。

  procedure SetMethodProp(Instance: TObject; constPropName: string;
    const Value: TMethod);
  procedure SetMethodProp(Instance: TObject;PropInfo: PPropInfo;
    const Value: TMethod);

===============================================================================
⊙ GetInt64Prop / SetInt64Prop
===============================================================================
SetInt64Prop 函数用于设置 Int64 类型的属性值。不同于一般整数用 EAX 返回,Int64 类型的返回值由EDX:EAX 返回,所以有必要单独定义 Int64 的获取和设置方法。

  function GetInt64Prop(Instance: TObject;PropInfo: PPropInfo): Int64;
  function GetInt64Prop(Instance: TObject; constPropName: string): Int64;

SetInt64Prop 函数用于设置 Int64 类型的属性值。

  procedure SetInt64Prop(Instance: TObject;PropInfo: PPropInfo;
    const Value: Int64);
  procedure SetInt64Prop(Instance: TObject; constPropName: string;
    const Value: Int64);

===============================================================================
⊙ GetInterfaceProp / SetInterfaceProp 函数
===============================================================================
GetInterfaceProp 函数用于获得 Interface 类型的属性值。

  function GetInterfaceProp(Instance: TObject;PropInfo: PPropInfo): IInterface;
  function GetInterfaceProp(Instance: TObject;const PropName: string): IInterface;

SetInterfaceProp 函数用于设置 Interface 类型的属性值。

  procedure SetInterfaceProp(Instance: TObject;PropInfo: PPropInfo;
    const Value:IInterface);
  procedure SetInterfaceProp(Instance: TObject;const PropName: string;
    const Value:IInterface);

* 不太熟悉 Interface,以后再看实现过程。

===============================================================================
⊙ GetPropValue / SetPropValue 函数
===============================================================================
GetPropValue 函数用于获得任何类型的属性值,它返回 Variant 类型。

注意,这个函数没有重载函数,只能使用属性名称字符串为参数。

GetPropValue 先调用 GetPropInfo 函数获得属性的类型,然后根据属性的数据类型选择调用以上介绍的GetOrdProp、GetEnumProp、GetSetProp、GetStrProp 等函数实现具体的功能。

GetPropValue 的参数 PreferStrings 如果设置为True,那么对于枚举、集合类型,将返回字符串值,否则返回整数值。GetPropValue还可以返回动态数组类型的属性值。(目前对动态数组不太熟悉,先记下来。)

  function GetPropValue(Instance: TObject; constPropName: string;
    PreferStrings: Boolean):Variant;

SetPropValue 函数用于设置任何类型的属性值。SetPropValue 的实现与 GetPropValue 类似。并且SetPropValue 内部分析 Value 参数是否是字符串来设置枚举和集合类型的属性,所以不需要 PreferStrings参数。SetPropValue 也可以设置动态数组属性,它使用了 SetOrdProp函数实现这一功能,看来动态数组在内存中的表现是一个指针。

  procedure SetPropValue(Instance: TObject; constPropName: string;
    const Value: Variant);

===============================================================================
⊙ TPublishableVariantType class
===============================================================================
在 TypInfo.pas 的代码注释中说 TPublishableVariantType 是用来代替TCustomVariantType 以便更容易在 RTTI 中使用自定义的 Variant 类型。

* 现在对这两个类型都不太了解,先记在这里以后再学。

===============================================================================
⊙ RegisterClass / FindClass 系列函数 (Classes.pas)
===============================================================================
Delphi 提供了一种机制,可以使用类(class)的名称获得类(class VMTptr)。缺省情况下这些类必须是从TPersistent 类继承下来的。使用这项功能之前必须在先把类信息注册到全局对象 RegGroup 中。

RegisterClass 函数用于注册类信息至 RegGroup 中,注意该函数名称和 Win32 API中注册窗口类的函数同名。如果类已经被注册过了,RegisterClass将直接返回。如果有一个不同的类以相同的名称注册了,RegisterClass 将触发异常(EFilerError)。

  procedure RegisterClass(AClass:TPersistentClass);

RegisterClasses 函数可以方便地注册一批类:

  procedure RegisterClasses(AClasses: array ofTPersistentClass);

RegisterClassAlias 函数可以为类以其它的名称注册,以避免名称冲突。

  procedure RegisterClassAlias(AClass:TPersistentClass; const Alias: string);

GetClass 函数根据类名称字符串获得类(class),如果没找到,将返回 nil:

  function GetClass(const AClassName: string):TPersistentClass;

FindClass 函数包装了 GetClass,不同的是如果没找到该类,则触发异常(EClassNotFound):

  function FindClass(const ClassName: string):TPersistentClass;

UnRegisterClass 系列函数执行 RegisterClass 相反的工作:

  procedure UnRegisterClass(AClass:TPersistentClass);
  procedure UnRegisterClasses(AClasses: array ofTPersistentClass);
  procedure UnRegisterModuleClasses(Module:HMODULE);

缺省的 RegGroup 用于组织从 TPersistent 继承下来的类,下面五个函数可以设置自己的 RegGroup:

  procedure StartClassGroup(AClass:TPersistentClass);
  procedure GroupDescendentsWith(AClass,AClassGroup: TPersistentClass);
  function ActivateClassGroup(AClass:TPersistentClass): TPersistentClass;
  function ClassGroupOf(AClass: TPersistentClass):TPersistentClass; overload;
  function ClassGroupOf(Instance: TPersistent):TPersistentClass; overload;

===============================================================================
⊙ IdentToInt / IntToIdent 系列函数 (Classes.pas)
===============================================================================
IdentToInt 和 IntToIdent函数用于实现字符串值和数值之间的转换。它的原理很简单,就是通过数组一一映射查找。不过一般不用直接使用这两个函数,而是使用 Delphi中已经包装好的函数。这些函数的返回值都是 Boolean,表示转换是否成功。

  function IdentToInt(const Ident: string; varInt: Longint;
    const Map: array ofTIdentMapEntry): Boolean;
  function IntToIdent(Int: Longint; var Ident:string;
    const Map: array ofTIdentMapEntry): Boolean;

  { Graphics.pas }
  function CharsetToIdent(Charset: Longint; varIdent: string): Boolean;
  function IdentToCharset(const Ident: string; varCharset: Longint): Boolean;

  function ColorToIdent(Color: Longint; var Ident:string): Boolean;
  function IdentToColor(const Ident: string; varColor: Longint): Boolean;

  { Controls.pas }
  function CursorToIdent(Cursor: Longint; varIdent: string): Boolean;
  function IdentToCursor(const Ident: string; varCursor: Longint): Boolean;

例子:
  var
    NewColor: Integer;
  begin
    if IdentToColor('clWindow',NewColor) then
      Self.Color:= NewColor;
  end;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值