如何访问私有成员变量和函数 (修正版)

这篇文章介绍一些 Delphi 穿透 OOP 约束的技巧。
访问保护的 (protected) 变量
如果是某个类的保护变量,可以在任何地方,通过如下方法访问:
type
  TSomeClassAccess = 
class (TSomeClass);

begin
  TSomeClassAccess(Object1).protected_Bool := False;
  TSomeClassAccess(Object1).protected_Int  := 
0 ;
  ...
end ;

 
访问私有的 (private) 变量
如果是某个类的私有变量,我们需要计算该变量在 VMT 中的偏移量。同时由于类声明可能在不同的 Delphi 版本中也有所不同,所以最好事先先检查一下源码。例:访问 TMenuItem 的第二个内部成员变量 FHandle
type
  THackMenuItem = 
class (TComponent)
  
protected  //<-- change to protected 
    FxxxxCaption: AnsiString;
    FHandle: HMENU;
//<-- the property you want to access
begin
  THackMenuItem(AMenuItem).FHandle := 0;
  ...
end ;

 
访问部分私有的 (private) 函数
访问私有函数要相对困难许多。据我所知只有 定义时声明为 virtual override dynamic message 私有函数才可以被访问或替换。其实现 原理和访问私有变量相似:先计算该函数在 VMT/DMT 中的偏移量 然后把该内存地址替换成新函数的内存地址。具体做法可以参考 TntControls TntSystem.pas 安装系统补丁 或者是 Fastcode 控件包。
友情提醒: (1) 通常私有函数中会涉及到一些访问其它的私有函数 / 变量。往往为了访问一个私有函数,还需要修改更多个私有函数 / 变量。相对比较复杂,也不很可靠。 (2) 内存地址修改不当会引发于一些软件的冲突,如 AQTime
注:如果变量定义时未设置关键字 strict ,同一个单元里面的所有类的内部变量 / 函数可以直接相互访问。这个是 Delphi 开的一个不大不小的后门。
 
增加私有的 (private) 函数 (a)
我们真的需要吗?有时候要!比如我在写一个 Dunit 单元测试的时候,需要接受 WM_COPYDATA 消息。但是这个消息是发送给 GUITestRunner 的,我必须打入 GUITestRunner 才可以得到相应消息。实现方法和访问私有函数类似,我们计算 VMT/DMT 的长度,在尾端增加一个新的函数指针。我在网上找到一篇文章说的比较详细,请 点击这里查看。这个方法有个限制:这个修改不是编译期完成的,你必须在类实例化之后,才进行修改。如果这个类被频繁使用,这个做法显然有些麻烦。如果能把这段修改代码放如类的构析函数中,问题就迎刃而解了。我在假想:我们是否可以使用介绍3中引入的方法,实现这个……

增加私有的 (private) 函数 (b)
还有一种更干净的修改方法,我们定义一个同名的类来欺骗编译器。例:我们创建一个新的单元,名为 GUITestRunnerPatch.pas
type
  THackGUITestRunner = 
class (GUITestRunner.TGUITestRunner)
  
private
    procedure WMCopyData(var Msg: TWMCopyData);
message WM_COPYDATA; //<-- the method you want to append
   end;

在需要使用 GUITestRunner 的地方 加上新的 GUITestRunnerPatch。注意:一定要在其之后,否则编译器不会调用你修改过的这个类,而是调用了原先的那个。
 
总结:
在进入 Delphi 的内部世界时,我们要尽可能的考虑代码的移植性和通用性,要以少量修改换回最佳效果。如果上面介绍的修修补补不能解决你的问题,当然你也可以直接修改 Delphi 的控件源码。修改之后,勾选编译选项里面的 „ Use Debug DCUs “,并编译程序,再将编译得到的 dcu 文件保存到编译目录下面。我一般创建 2 个目录: PatchedVCLs PreCompiled 放修改过的源码,和编译之后的版本。然后把这个 2 个目录定义到环境变量里面,这样只要在每个项目的路径设置中添加这些变量,就可以使用改动过的代码了。如果本文不正确的地方,欢迎拍砖。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值