前一篇文章讲了如何取得枚举类型中的元素名,现在讲讲取得类的成员信息,VCL的RTTI(runtime type identification运行时类型标识)封装C++的RTTI,并加入了一些新特性,这就是VCL的强大之处。
废话不多说,下面这个函数把AClass(函数参数)的所有成员,包括属性、变量、函数和事件相关信息添加到TStrings中(以下函数定义在Typinfo.pas中):
void __fastcall TForm1::GetClassProperties(TMetaClass *AClass,TStrings *AStrings)
{
PTypeInfo tInfo = PTypeInfo(AClass->ClassInfo()); //取得类的类型信息
short pCount = GetTypeData(tInfo)->PropCount; //类的成员个数
if (pCount == 0) return;
// PPropList类型为PPropInfo类型数组的指针的指针
//PPropList pList = (PPropList)malloc(pCount * sizeof(Pointer)); //C样式的动态分配
PPropList pList = new PPropInfo[pCount]; //C++样式数组动态分配
//也可以定义为TPropList pList;如果这样定义按理说下行GetPropInfos应该使用&pList作为第二参数
//但这样将在BCB6中编译失败,而在BCB2006+中是正确的,并且BCB2006+中将不能用第一种PPropList的声明方法了方法了。
GetPropInfos(tInfo,pList); //取得属性信息,存入pList
AnsiString pString;
for (int i = 0;i < pCount;i++)
{
PTypeInfo pti = *(pList[i]->PropType); //类成员的类型信息
/*
TTypeKind元素远不只下面这几个,你当然可以用switch分辨成员的种类(如果你不嫌麻烦的话);
但是刚学会取得enum元素有什么理由不用呢?
switch (pti->Kind)
{
case tkClass: pString = "[Class]";
break;
case tkMethod: pString = "[Method]";
break;
case tkSet: pString = "[Set]";
break;
case tkEnumeration: pString = "[Enum]";
break;
default: pString = "[OtherField]";
break;
}
*/
// 如下,不过先要在类中添加__published的属性tKind(必须在__published段)
// class TForm1 : public TForm
// {
// private:
// Typinfo::TTypeKind FtKind;
// __published:
// __property Typinfo::TTypeKind tKind = { read = FtKind };
// };
//
//
// 下面__typeinfo()的参数应该是包含TTypeKind属性的类,而不是AClass 。
PPropInfo pInfo= GetPropInfo(__typeinfo(TForm1),"tKind");
pString = GetEnumName(*(pInfo->PropType),pti->Kind); //成员种类,定义于TTypeKind
pString += " : " + pList[i]->Name; //成员名
pString += " : " + pti->Name; //成员类型
AStrings->Add(pString);
}
delete [] pList; //删除数组
//free(pList); //C样式的删除数组
}
这样使用此函数:
GetClassProperties(__classid(TForm1),ListBox1->Items);
这样可以取得TForm1中所有的成员信息。