是否有可能获得组件'方法值(表示名称)?

时间:2014-06-06 16:37:21

标签: delphi

我需要获取一个组件名称(TButton),它在设计时被分配,并且可以在Object Inspector中看到(例如Button1Click在事件选项卡上的Button1.OnClick事件中)。

我现在使用TypInfo单元通过PPropInfo获取方法的信息,我得到OnClickTNotifyEvent个字符串作为值,但我没有得到{ {1}}为字符串值。

我怎样才能得到它?

2 个答案:

答案 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');