访问私有成员变量和函数的步骤
一说到修改 Delphi 源码或者访问对象的私有成员函数,很多人马上可以说出种种危害来否定我。这种做法我也提倡,但是有时候如果可以灵活运用,可以解决由于 Delphi 因为封装不正确而带来的问题。我在这里分享一些技巧:
1. 访问私有成员变量
如果是 protected 的变量,可以用如下方法访问:
type
TSomeClassAccess=class(TSomeClass);
begin
TSomeClassAccess(Object1).protected_Bool:=False;
TSomeClassAccess(Object1).protected_Int:=0;
...
end;
如果是 private 的变量,那么就要当心了。因为涉及到偏移量。还要考虑不同 Delphi 版本的控件的内部成员可能也有变化。最简单的例子是:访问 TMenuItem 的第二个内部成员变量 FHandle
type
THackMenuItem=class(TComponent)
protected//<--changetoprotected
FxxxxCaption:AnsiString;
FHandle:HMENU; //<--thepropertyyouwanttoaccess
end;
begin
THackMenuItem(AMenuItem).FHandle:=0;
...
end;
2. 访问私有成员函数
这个目前普遍的做法是偷梁换柱。就是把自己的函数地址替换成待修改函数的内存地址。不过其中涉及到了内存修改、地址偏移量……,具体做法可以参考 TntControls 中 TntSystem.pas 安装系统补丁,或者是 Fastcode 控件包。当然这个替换是会出现副作用的:例如 AQTime 就无法测试安装过 TntSystem 补丁的程序。
3. 直接修改代码的实现
如果是运行库中的具体实现要修改,可以直接动源码,因为改动是implementation 的部分,不会影响到其它的调用该单元的部分。(注意:interface 和 implementation 的内容不能直接修改,否则无法编译通过。)修改之后,勾选编译选项里面的 „Use Debug DCUs“,并编译程序,再将编译得到的 dcu 文件保存到编译目录下面。我一般创建2个目录:PatchedVCLs 和 PreCompiled 放修改过的源码,和编译之后的版本。然后把这个2个目录定义到环境变量里面,这样只要在每个项目的路径设置中添加这些变量,就可以使用改动过的代码了。
4. 间接修改代码的实现
如果要在修改定义部分怎么办?方法3是肯定行不通了。因为所有引用到这个单元的单元也需要重新编译,但不是所有 Delphi 源码你都可以重新编译的。这种情况就伤脑筋了。我目前只可以修改很小一部分的。基本思路是在自己的程序里面定义需访问对象的扩展类和具体实现。然后释放原先对象实例,并以新扩展类重新创建实例。请参考 打入消息循环的另类方法。
总结:
以上四种方法是我在修改 Delphi 库或者第三方控件时候所用到的。在修改源码的时候,尽量要考虑到代码的移植性。要做到最少量的修改,得到最好的效果。并且需要考虑修改的代码是否可以在不 同的 Delphi 版本中使用。我在实际项目中,修改了6、7个源码。(有时间的话,我会一一列出,有需要的可以问我索龋)同时也欢迎交流更多的修改方法,以及 Delphi 不正确封装的补叮
题外话:
刚刚来自 CodeGear 的消息,Delphi 下个版本会引入了新的技术,直接修改声明部分的代码将变的可能。
本文地址:http://www.45fan.com/a/question/68938.html