您现在的位置:首页 >> 基础算法 >> window基础 >> 内容

Delphi XE的RTTI增强动态Hook某些内部事件

时间:2011/9/3 15:28:02 点击:

  核心提示:我这里的主要目的是挂钩某些内部私有事件,然后增加上一些自己的处理过程,这里我以TMenuItem的私有内部事件FOnChange作为例程。这个私有事件在菜单内部绑定,我们平常状态下,在外部无法更改!但...

我这里的主要目的是挂钩某些内部私有事件,然后增加上一些自己的处理过程,这里我以TMenuItem的私有内部事件FOnChange作为例程。这个私有事件在菜单内部绑定,我们平常状态下,在外部无法更改!但是XE之后这个问题不在存在,使用它的全新RTTI,可以很容易的获得一个类对象的基本上所有的类的字段以及方法和属性等。

begin
  rttiContext := TRttiContext.Create;
  rtype := rttiContext.GetType(TMenuItem);
  rField := rType.GetField('FOnChange');
  if rField <> nil then
  begin
     V := rField.GetValue(MainMenu1.Items);
     OldMenuItemChangeCode := TValueData(V).FAsMethod.Code;
     OldSelfData := TValuedata(V).FAsMethod.Data;
TValueData(V).FAsMethod.Code := @TForm1.MenuItemChange;//菜单项目变化
     TValueData(V).FAsMethod.Data := self;
     rField.SetValue(self.MainMenu1.Items,v);
  end;

上面的代码就设置了MainMenu的items的私有事件变量FOnChange的新指向地址为本窗体的实现代码了,OldMenuItemChangeCode,OldSelfData是保存私有事件的原有方法指针和传递的Self指针对象。用来在我们替换后的对象中进行调用,不然原过程就不会被调用了。然后我们再来看看,新的FonChange的实现过程

procedure TForm1.MenuItemChange(Sender: TObject; Source: TMenuItem;
  Rebuild: Boolean);
var
  m: procedure(selfData: TObject;Sender: TObject; Source: TMenuItem;
  Rebuild: Boolean);
begin
  if Assigned(OldMenuItemChangeCode) then
  begin
    m := OldMenuItemChangeCode;
    m(OldSelfData,Sender,Source,Rebuild);
  end;
  ShowMessage('菜单修改事件挂钩');
end;

这个代码中最主要的就是如何来调用原来的FOnChange的执行过程了,熟悉Delphi的人应该都知道了Delphi的对象过程中可以使用Self表示当前对象,而这个对象在对象过程中的传递是通过EAX传递的,而此时我们的新过程不是在MainMenu.Items的对象内部调用执行的,所以,我们需要显示的传递SelfData作为源对象中的Self对象指针,所以我申明了一个指针过程如下:

m: procedure(selfData: TObject;Sender: TObject; Source: TMenuItem;
  Rebuild: Boolean);

作者原文:http://www.cnblogs.com/DxSoft/archive/2011/01/04/1925907.html

作者:不得闲 来源:转载
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
  • 盒子文章(www.2ccc.com) © 2024 版权所有 All Rights Reserved.
  • 沪ICP备05001939号