需要在 Delphi 的 运行 时间分别获取事件参数及其各自的类型
Need to get event parameters along with their respective types separately at run time in Delphi
我正在使用 Delphi XE5。
我使用下面的代码在 excel 文件中存储 属性 和提供的 Delphi VCL 组件的事件名称。
procedure TForm1.Button1Click(Sender: TObject);
var
PropInfo: PPropInfo;
MyPTypeInfo : PTypeInfo;
MyPPropList : PPropList;
Count, I : Integer;
PropOrEvent, PropValue : String;
FileName : String;
begin
FileName := 'C:\MyFile_Delphi.xlsx';
ListBox1.Items.Clear;
GetPropList(Button1, MyPPropList);
try
Count := GetPropList(Button1, MyPPropList);
for I := 0 to Count - 1 do
begin
PropInfo := MyPPropList^[I];
if PropInfo^.PropType^.Kind in tkMethods then
PropOrEvent := 'Event'
else
PropOrEvent := 'Property';
PropValue := VarToStr(GetPropValue(Button1, PropInfo^.Name));
ListBox1.Items.Add(PropOrEvent + ' - ' + PropInfo^.Name);
end;
finally
ListBox1.Items.SaveToFile(FileName);
FreeMem(MyPPropList);
end;
end;
但是我还需要每个事件参数名称及其各自的类型,例如:
procedure TForm1.FormConstrainedResize(Sender: TObject; var MinWidth, MinHeight,
MaxWidth, MaxHeight: Integer);
begin
end;
当我同时获得此事件名称时,我需要获得如下结果:
Sender: TObject
MinWidth: Integer
MinHeight: Integer
MaxWidth: Integer
MaxHeight: Integer
可能需要通过 运行 再循环一次。
如何获取?
提前致谢。
您所要求的可以通过 RTTI 完成。通过 System.TypInfo
单元的旧式 RTTI 和通过 System.Rtti
单元的新式扩展 RTTI 都包含足够的信息来执行此操作。
例如,使用旧式 RTTI:
uses
System.TypeInfo;
procedure TForm1.Button1Click(Sender: TObject);
type
PPPTypeInfo := ^PPTypeInfo;
var
PropInfo: PPropInfo;
MyPTypeInfo, MyParamPTypeInfo : PTypeInfo;
MyPTypeData: PTypeData;
MyPPropList : PPropList;
Count, I : Integer;
J: Byte;
PropOrEvent, PropValue : String;
FileName : String;
Ptr: PByte;
ParamName: String;
TypeName: String;
begin
FileName := 'C:\MyFile_Delphi.xlsx';
ListBox1.Items.Clear;
Count := GetPropList(Button1, MyPPropList);
try
for I := 0 to Count - 1 do
begin
PropInfo := MyPPropList^[I];
if PropInfo^.PropType^.Kind in tkMethods then
PropOrEvent := 'Event'
else
PropOrEvent := 'Property';
ListBox1.Items.Add(PropOrEvent + ' - ' + PropInfo^.Name);
//...
if PropInfo^.PropType^.Kind in tkMethods then
begin
MyPTypeData := GetTypeData(PropInfo^.PropType^);
{
tkMethod: (
MethodKind: TMethodKind; // only mkFunction or mkProcedure
ParamCount: Byte;
ParamList: array[1..ParamCount] of
record
Flags: TParamFlags;
ParamName: ShortString;
TypeName: ShortString;
end;
ResultType: ShortString; // only if MethodKind = mkFunction
ResultTypeRef: PPTypeInfo; // only if MethodKind = mkFunction
CC: TCallConv;
ParamTypeRefs: array[1..ParamCount] of PPTypeInfo;
MethSig: PProcedureSignature;
MethAttrData: TAttrData);
}
Ptr := PByte(@MyPTypeData^.ParamList);
if MyPTypeData^.ParamCount > 0 then
begin
for J := 0 to MyPTypeData^.ParamCount-1 do
begin
Inc(Ptr, SizeOf(TParamFlags));
ParamName := PShortString(Ptr)^;
Inc(Ptr, 1 + Integer(Ptr^));
TypeName := PShortString(Ptr)^;
Inc(Ptr, 1 + Integer(Ptr^));
// use ParamName and TypeName as needed...
end;
end;
if MyPTypeData^.MethodKind = mkFunction then
begin
Inc(Ptr, 1 + Integer(Ptr^));
Inc(Ptr, SizeOf(PPTypeInfo));
end;
Inc(Ptr, SizeOf(TCallConv));
if MyPTypeData^.ParamCount > 0 then
begin
for J := 0 to MyPTypeData^.ParamCount-1 do
begin
MyParamPTypeInfo := PPPTypeInfo(Ptr)^;
// use MyParamPTypeInfo as needed...
Inc(Ptr, SizeOf(PPTypeInfo));
end;
end;
end;
end;
finally
FreeMem(MyPPropList);
end;
ListBox1.Items.SaveToFile(FileName);
end;
使用扩展 RTTI:
uses
System.TypInfo, System.Rtti;
procedure TForm1.Button1Click(Sender: TObject);
var
Ctx: TRttiContext;
MyProp: TRttiProperty;
MyParam: TRttiParameter;
PropOrEvent, PropValue : String;
FileName : String;
begin
FileName := 'C:\MyFile_Delphi.xlsx';
ListBox1.Items.Clear;
for MyProp in Ctx.GetType(Button1.ClassType).GetProperties do
begin
if MyProp.PropertyType.TypeKind in tkMethods then
PropOrEvent := 'Event'
else
PropOrEvent := 'Property';
ListBox1.Items.Add(PropOrEvent + ' - ' + MyProp.Name);
//...
if MyProp.PropertyType.TypeKind in tkMethods then
begin
for MyParam in (MyProp.PropertyType as TRttiMethodType).GetParameters do
begin
// use MyParam.Name and MyParam.ParamType as needed...
end;
end;
end;
ListBox1.Items.SaveToFile(FileName);
end;
我正在使用 Delphi XE5。
我使用下面的代码在 excel 文件中存储 属性 和提供的 Delphi VCL 组件的事件名称。
procedure TForm1.Button1Click(Sender: TObject);
var
PropInfo: PPropInfo;
MyPTypeInfo : PTypeInfo;
MyPPropList : PPropList;
Count, I : Integer;
PropOrEvent, PropValue : String;
FileName : String;
begin
FileName := 'C:\MyFile_Delphi.xlsx';
ListBox1.Items.Clear;
GetPropList(Button1, MyPPropList);
try
Count := GetPropList(Button1, MyPPropList);
for I := 0 to Count - 1 do
begin
PropInfo := MyPPropList^[I];
if PropInfo^.PropType^.Kind in tkMethods then
PropOrEvent := 'Event'
else
PropOrEvent := 'Property';
PropValue := VarToStr(GetPropValue(Button1, PropInfo^.Name));
ListBox1.Items.Add(PropOrEvent + ' - ' + PropInfo^.Name);
end;
finally
ListBox1.Items.SaveToFile(FileName);
FreeMem(MyPPropList);
end;
end;
但是我还需要每个事件参数名称及其各自的类型,例如:
procedure TForm1.FormConstrainedResize(Sender: TObject; var MinWidth, MinHeight,
MaxWidth, MaxHeight: Integer);
begin
end;
当我同时获得此事件名称时,我需要获得如下结果:
Sender: TObject
MinWidth: Integer
MinHeight: Integer
MaxWidth: Integer
MaxHeight: Integer
可能需要通过 运行 再循环一次。
如何获取?
提前致谢。
您所要求的可以通过 RTTI 完成。通过 System.TypInfo
单元的旧式 RTTI 和通过 System.Rtti
单元的新式扩展 RTTI 都包含足够的信息来执行此操作。
例如,使用旧式 RTTI:
uses
System.TypeInfo;
procedure TForm1.Button1Click(Sender: TObject);
type
PPPTypeInfo := ^PPTypeInfo;
var
PropInfo: PPropInfo;
MyPTypeInfo, MyParamPTypeInfo : PTypeInfo;
MyPTypeData: PTypeData;
MyPPropList : PPropList;
Count, I : Integer;
J: Byte;
PropOrEvent, PropValue : String;
FileName : String;
Ptr: PByte;
ParamName: String;
TypeName: String;
begin
FileName := 'C:\MyFile_Delphi.xlsx';
ListBox1.Items.Clear;
Count := GetPropList(Button1, MyPPropList);
try
for I := 0 to Count - 1 do
begin
PropInfo := MyPPropList^[I];
if PropInfo^.PropType^.Kind in tkMethods then
PropOrEvent := 'Event'
else
PropOrEvent := 'Property';
ListBox1.Items.Add(PropOrEvent + ' - ' + PropInfo^.Name);
//...
if PropInfo^.PropType^.Kind in tkMethods then
begin
MyPTypeData := GetTypeData(PropInfo^.PropType^);
{
tkMethod: (
MethodKind: TMethodKind; // only mkFunction or mkProcedure
ParamCount: Byte;
ParamList: array[1..ParamCount] of
record
Flags: TParamFlags;
ParamName: ShortString;
TypeName: ShortString;
end;
ResultType: ShortString; // only if MethodKind = mkFunction
ResultTypeRef: PPTypeInfo; // only if MethodKind = mkFunction
CC: TCallConv;
ParamTypeRefs: array[1..ParamCount] of PPTypeInfo;
MethSig: PProcedureSignature;
MethAttrData: TAttrData);
}
Ptr := PByte(@MyPTypeData^.ParamList);
if MyPTypeData^.ParamCount > 0 then
begin
for J := 0 to MyPTypeData^.ParamCount-1 do
begin
Inc(Ptr, SizeOf(TParamFlags));
ParamName := PShortString(Ptr)^;
Inc(Ptr, 1 + Integer(Ptr^));
TypeName := PShortString(Ptr)^;
Inc(Ptr, 1 + Integer(Ptr^));
// use ParamName and TypeName as needed...
end;
end;
if MyPTypeData^.MethodKind = mkFunction then
begin
Inc(Ptr, 1 + Integer(Ptr^));
Inc(Ptr, SizeOf(PPTypeInfo));
end;
Inc(Ptr, SizeOf(TCallConv));
if MyPTypeData^.ParamCount > 0 then
begin
for J := 0 to MyPTypeData^.ParamCount-1 do
begin
MyParamPTypeInfo := PPPTypeInfo(Ptr)^;
// use MyParamPTypeInfo as needed...
Inc(Ptr, SizeOf(PPTypeInfo));
end;
end;
end;
end;
finally
FreeMem(MyPPropList);
end;
ListBox1.Items.SaveToFile(FileName);
end;
使用扩展 RTTI:
uses
System.TypInfo, System.Rtti;
procedure TForm1.Button1Click(Sender: TObject);
var
Ctx: TRttiContext;
MyProp: TRttiProperty;
MyParam: TRttiParameter;
PropOrEvent, PropValue : String;
FileName : String;
begin
FileName := 'C:\MyFile_Delphi.xlsx';
ListBox1.Items.Clear;
for MyProp in Ctx.GetType(Button1.ClassType).GetProperties do
begin
if MyProp.PropertyType.TypeKind in tkMethods then
PropOrEvent := 'Event'
else
PropOrEvent := 'Property';
ListBox1.Items.Add(PropOrEvent + ' - ' + MyProp.Name);
//...
if MyProp.PropertyType.TypeKind in tkMethods then
begin
for MyParam in (MyProp.PropertyType as TRttiMethodType).GetParameters do
begin
// use MyParam.Name and MyParam.ParamType as needed...
end;
end;
end;
ListBox1.Items.SaveToFile(FileName);
end;