我需要获取一个组件名称(TButton),它在设计时被分配,并且可以在Object Inspector中看到(例如Button1Click
在事件选项卡上的Button1.OnClick
事件中)。
我现在使用TypInfo单元通过PPropInfo
获取方法的信息,我得到OnClick
和TNotifyEvent
个字符串作为值,但我没有得到{ {1}}为字符串值。
我怎样才能得到它?
答案 0 :(得分:6)
string := MethodName(GetMethodProp(Button1, 'OnClick').Code);
请注意,该方法需要发布'。
答案 1 :(得分:4)
如果属性和指定方法都是published
,则可以使用:
uses
TypInfo;
function GetEventHandlerName(Obj: TObject; const EventName: String): String;
var
m: TMethod;
begin
m := GetMethodProp(Obj, EventName);
if (m.Data <> nil) and (m.Code <> nil) then
Result := TObject(m.Data).MethodName(m.Code)
else
Result := '';
end;
s := GetEventHandlerName(Button1, 'OnClick');
TypInfo
单位(GetMethodProp()
来自哪里)仅支持published
属性。
您必须指定拥有方法地址的对象,因为TObject.MethodName()
会迭代对象的VMT。该方法必须为published
,因为TObject.MethodName()
(存在以促进DFM流式传输)迭代VMT的一部分,该部分仅使用published
方法的地址填充。
如果您使用的是Delphi 2010或更高版本,则可以使用Extended RTTI,但不具有published
限制:
uses
Rtti;
function GetEventHandlerName(Obj: TObject; const EventName: String): String;
type
PMethod = ^TMethod;
var
ctx: TRttiContext;
v: TValue;
_type: TRttiType;
m: TMethod;
method: TRttiMethod;
s: string;
begin
Result := '';
ctx := TRttiContext.Create;
v := ctx.GetType(Obj.ClassType).GetProperty(EventName).GetValue(Obj);
if (v.Kind = tkMethod) and (not v.IsEmpty) then
begin
// v.AsType<TMethod>() raises an EInvalidCast exception
// and v.AsType<TNotifyEvent>() is not generic enough
// to handle any kind of event. Basically, the Generic
// parameter of AsType<T> must match the actual type
// that the event is declared as. You can use
// TValue.GetReferenceToRawData() to get a pointer to
// the underlying TMethod data...
m := PMethod(v.GetReferenceToRawData())^;
_type := ctx.GetType(TObject(m.Data).ClassType);
for method in _type.GetMethods do
begin
if method.CodeAddress = m.Code then
begin
Result := method.Name;
Exit;
end;
end;
end;
s := GetEventHandlerName(Button1, 'OnClick');