因为从 System::TObject 继承的类都支持枚举类的成员的 RTTI 功能,所以,所有的控件都支持枚举成员,包括属性、事件、成员函数和成员变量。
这些 RTTI 功能的头文件为
#include <System.Rtti.hpp> |
需要的模板函数 EnumToStr 是为了以字符串的形式显示枚举值,而不是整数值:
template<class T>
UnicodeString EnumToStr(T t){ return Typinfo::GetEnumName(__delphirtti(T),(int)t); } |
枚举属性和事件,参数 lpObject:要枚举的控件 (所有从 TObject 继承的类都支持枚举属性和事件),
枚举到的内容,如果类型是 tkMethod 就是事件,其他类型是属性,因为事件是类型为 __closure 函数指针的属性。
void EnumPropertyList(TObject *lpObject) // 枚举属性和事件
{
TRttiContext context;
TRttiInstanceType *cls = dynamic_cast<TRttiInstanceType*>(context.GetType(lpObject->ClassType()));
if(cls)
{
System::DynamicArray<TRttiProperty*> PropArray = cls->GetProperties();
for(int i=0; i<PropArray.Length; i++)
{
TRttiProperty *lpProperty = PropArray[i];
UnicodeString sProp, sName, sKind, sValue;
sName = lpProperty->Name;
sKind = EnumToStr(lpProperty->PropertyType->TypeKind);
sProp = lpProperty->PropertyType->TypeKind == tkMethod ? L"事件" : L"属性";
try
{
TValue vVal = lpProperty->GetValue(lpObject);
sValue = vVal.ToString();
}
catch(Exception &e)
{
sValue = e.ClassName() + L": " + e.Message;
}
Form1->Memo1->Lines->Add(sProp + L": " + sName + L", 类型: " + sKind + L", 值: " + sValue);
}
}
} |
枚举成员函数,参数 lpObject:要枚举的控件 (所有从 TObject 继承的类都支持枚举成员函数)
void EnumMethodList(TObject *lpObject) // 枚举成员函数
{
TRttiContext context;
TRttiInstanceType *cls = dynamic_cast<TRttiInstanceType*>(context.GetType(lpObject->ClassType()));
if(cls)
{
System::DynamicArray<TRttiMethod*> MethodList = cls->GetMethods();
for(int i=0; i<MethodList.Length; i++)
{
Form1->Memo1->Lines->Add(L"成员函数: " + MethodList[i]->Name);
}
}
} |
枚举成员变量,参数 lpObject:要枚举的控件 (所有从 TObject 继承的类都支持枚举成员变量)
void EnumFieldList(TObject *lpObject) // 枚举成员变量
{
TRttiContext context;
TRttiInstanceType *cls = dynamic_cast<TRttiInstanceType*>(context.GetType(lpObject->ClassType()));
if(cls)
{
System::DynamicArray<TRttiField*> FieldList = cls->GetFields();
for(int i=0; i<FieldList.Length; i++)
{
TRttiField *lpField = FieldList[i];
UnicodeString sName, sKind, sValue;
sName = lpField->Name;
sKind = EnumToStr(lpField->FieldType->TypeKind);
try
{
TValue vVal = lpField->GetValue(lpObject);
sValue = vVal.ToString();
}
catch(Exception &e)
{
sValue = e.ClassName() + L": " + e.Message;
}
Form1->Memo1->Lines->Add(L"成员变量: " + sName + L", 类型: " + sKind + L", 值: " + sValue);
}
}
} |
在 Form 上放一个 Memo1 和三个按钮 Button1、Button2、Button3,三个按钮分别枚举 Memo1 的属性事件、成员函数和成员变量
void __fastcall TForm1::Button1Click(TObject *Sender)
{
EnumPropertyList(Button1); // 枚举控件 Button1 的属性和事件
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
EnumMethodList(Button1); // 枚举控件 Button1 的成员函数
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
EnumFieldList(Button1); // 枚举控件 Button1 的成员变量
}
//--------------------------------------------------------------------------- |
点击 Button1 枚举属性和事件的执行结果:
点击 Button2 枚举成员函数的执行结果:
点击 Button3 枚举成员变量的执行结果:
兼容性:
C++ Builder 2010 |
C++ Builder XE ~ XE8 |
C++ Builder 10.0 Seattle ~ 10.2.3 Tokyo |
不支持 |
暂未测试 |
支持 |
|