Delphi 是否可以获得组件';方法值(表示名称)?
我需要获取一个组件的名称(TButton),该组件在设计时被分配,并在对象检查器中显示(例如Delphi 是否可以获得组件';方法值(表示名称)?,delphi,Delphi,我需要获取一个组件的名称(TButton),该组件在设计时被分配,并在对象检查器中显示(例如按钮1在按钮1处单击。在事件选项卡上单击事件) 我现在使用TypInfo单元通过PPropInfo获取方法信息,并将OnClick和TNotifyEvent字符串作为值,但没有将按钮1click作为字符串值 我怎样才能得到它 string := MethodName(GetMethodProp(Button1, 'OnClick').Code); 请注意,该方法需要“发布” 请注意,需要“发布”该方法。
按钮1在按钮1处单击。在事件选项卡上单击事件)
我现在使用TypInfo单元通过PPropInfo
获取方法信息,并将OnClick
和TNotifyEvent
字符串作为值,但没有将按钮1click
作为字符串值
我怎样才能得到它
string := MethodName(GetMethodProp(Button1, 'OnClick').Code);
请注意,该方法需要“发布”
请注意,需要“发布”该方法。如果属性和分配的方法都已发布
,则可以使用以下方法:
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;
TypInfo
单元(其中GetMethodProp()
来自)仅支持published
属性
您必须指定拥有方法地址的对象,因为TObject.MethodName()
迭代对象的VMT。并且该方法必须是已发布的
,因为TObject.MethodName()
(其存在是为了方便DFM流式传输)迭代VMT的一部分,该部分仅填充已发布的
方法的地址
如果您使用的是Delphi 2010或更高版本,则可以改用扩展RTTI,该RTTI没有发布的限制:
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;
如果属性和指定的方法都已发布
,
,则可以使用:
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;
TypInfo
单元(其中GetMethodProp()
来自)仅支持published
属性
您必须指定拥有方法地址的对象,因为TObject.MethodName()
迭代对象的VMT。并且该方法必须是已发布的
,因为TObject.MethodName()
(其存在是为了方便DFM流式传输)迭代VMT的一部分,该部分仅填充已发布的
方法的地址
如果您使用的是Delphi 2010或更高版本,则可以改用扩展RTTI,该RTTI没有发布的限制:
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;
这还假设该方法是由表单实现的+1GetMethodProp()
返回一个TMethod
。TMethod.Data
字段指向传递给方法的Self
参数的对象。在99%的情况下,您可以将TMethod.Data
类型转换为TObject
,然后使用该对象调用TObject.MethodName()
,将TMethod.code
作为地址,因为地址将属于该对象的类。这在所有情况下都应该有效,即使在运行时在代码中分配了事件。@RemyLebeau如果没有在那里分配方法或AV,它是否可以工作?顺便说一句-谢谢!明天上班时我会试试;)已经检查过了!一切正常!如果未分配任何内容,则不存在AV-仅存在“”(空字符串)。@notricky:它必须在源代码中发布
,在运行时不能更改为发布
。有关更多详细信息,请参阅。这还假设该方法由表单实现+1GetMethodProp()
返回一个TMethod
。TMethod.Data
字段指向传递给方法的Self
参数的对象。在99%的情况下,您可以将TMethod.Data
类型转换为TObject
,然后使用该对象调用TObject.MethodName()
,将TMethod.code
作为地址,因为地址将属于该对象的类。这在所有情况下都应该有效,即使在运行时在代码中分配了事件。@RemyLebeau如果没有在那里分配方法或AV,它是否可以工作?顺便说一句-谢谢!明天上班时我会试试;)已经检查过了!一切正常!如果未分配任何内容,则不存在AV-仅存在“”(空字符串)。@notricky:它必须在源代码中发布
,在运行时不能更改为发布
。有关更多详细信息,请参阅。TObject的演员阵容过于武断。Data
指针可以引用类而不是实例。或者确实是一个记录或一个TP对象。知道它是多么伟大@大卫·费弗南处理这个问题的方法是什么?@notricky这真的是你的问题吗?您不会从TP对象中获得任何RTTI,但谁会关心它们呢?至于记录或类类型,不确定如何识别它们。知道你为什么问这个问题会很有趣。@DavidHeffernan,这很公平。我正在编写一个SmallClass
,在这里我传递自身和外部组件Component
有自己的方法,我需要找到这些方法并用这些方法重新分配,这些方法位于self
的实例中。当Component
和self
都有相同的方法名时,应该会发生这种情况:Component.OnClick-'ComponentClick'
和self.ComponentClick
。因此,我不仅需要从Component
中发布的属性中获取信息,还需要从self
中获取信息。我真的不明白为什么需要使用内省,但在任何情况下,除了方法指针的原始数据之外,我看不到任何需要了解的信息。我认为这两个答案,在回答你的问题时,都比你需要的复杂。换言之,我认为你问错了问题。TObject的演员阵容是自以为是的。Data
指针可以引用类而不是实例。或者确实是一个记录或一个TP对象。知道它是多么伟大@大卫·费弗南处理这个问题的方法是什么?@notricky这真的是你的问题吗?您不会从TP对象中获得任何RTTI,但谁会关心它们呢?至于记录或类类型,不确定如何识别它们。知道你为什么问这个问题会很有趣。@DavidHeffernan,这很公平。我正在编写一个SmallClass
,在这里我传递自身和外部组件<代码>组件
有自己的方法,我需要找到并重新分配这些方法