修改 VCL 组件代码

4

我需要修改一个组件的功能。当你收到“无法覆盖此内容”的消息或者需要更改私有方法中的代码(“基类中不存在该方法”消息),使得无法继承组件时,你应该怎么办?

2个回答

4
涉及修改私有方法或其中行为时,有一些(主要是hacky)选项:

  • 修改原始源代码,重新编译单元并使用更改后的dcu,如此处所建议的。虽然我从未尝试过,但我认为当您的代码使用新的dcu而其他VCL代码不使用时,这可能会给您带来很大的头痛。
  • 通常组件行为由众多窗口消息控制-查看是否可以通过修改对某些消息的反应来实现更改;即使声明为私有,您也可以重写处理消息的方法(带有message关键字的方法),还可以替换WndProc。
  • 您可以使用像这个这样的hack,它涉及转换。
  • 您可以使用类似于此处所述的策略。

或者你可以选择另一个组件。


1
对于你的第一个观点:我宁愿复制该单元,重命名我更改的类,并删除我不需要的所有内容(必要时,“包括”原始单元以定义常量、使用的类型等)。这样可以避免大部分麻烦。永远不要修改原始源代码,那是维护的噩梦。 - Rudy Velthuis
我同意。这更多是指“修改、编译、使用dcu、撤消修改”的意思。但你的方法听起来更好。只需复制单元并根据需要进行更改即可。缺点仍然是,对于经常更新的第三方组件,它也需要一些维护。但如果是VCL,则下一个bugfix/更新将是Delphi的下一个版本,所以不用担心。 - Heinrich Ulbricht

4
如果我遇到这个问题,
  • 首先我会尝试继承组件或其CustomXXX祖先来解决问题。如果不行,
  • 我会深入研究,即尝试截取传入的消息。这可以动态完成。如果发现太深了,因为必须构建在此之上的代码太多,或者如果我仍然需要访问无法访问的项目,
  • 我会尝试使用黑客技巧。其中一个技巧是将组件和相关代码复制到一个具有不同名称的新单元中,重命名组件并修改需要修改的内容。
  • 有时我只需要重新制作一个或两个方法就可以实现新的行为。

永远不要忘记为单元提供不同的名称,也为组件提供不同的名称(可能继承自原始组件或其祖先,以便它们保持在同一层次结构中)。千万不要修改原始源代码,然后重新编译VCL。这是维护的噩梦。

我不是interposer类的粉丝,即与原始类相同但具有不同行为的类,继承自原始类。他们的功能取决于在uses子句中的包含顺序,这似乎对我来说有些脆弱。我不建议这样做。

但是,我所做的很大程度上取决于问题。我认为不能(或不应该)给出覆盖所有情况的普遍建议。

但是我的主要建议是:不要修改原始单元,始终将新代码放在一个新单元中并使用新类名称。这样,原始版本和修改版本可以在IDE中平稳共存。


2
只要运行时包被禁用,并且您不需要对“interface”部分进行任何更改,那么您就不需要重命名单元或其类。只需复制本地项目的单元,将副本添加到项目中,然后根据需要修改其“implementation”部分即可。它将在编译期间覆盖VCL的本机代码。 - Remy Lebeau
1
更改单位和类名称需要更改引用它们的代码。通常会保留原始名称,以便不必更改现有代码,特别是如果意图是更改/修复内部行为(即修复RTL / VCL错误)。 - Remy Lebeau
1
我会站在Remy这边。在测试时(尽管我从未在部署中这样做),我只需将VCL源单元复制到本地目录,进行编辑和重新编译。在我看来,如果只是修改了相同的类,则重命名类就是维护噩梦。如果“错误”/功能在以后的Delphi版本中得到修复,那么您所需要做的就是归档该单元,然后回到原始的VCL。如果重命名单元和类,则无法实现此操作。而且,从未来版本中合并新的单元版本更容易。 - Misha
这里的建议实际上是不切实际的,显然是由缺乏理解问题所需的现实世界经验的人提出的。但我的主要建议是:不要修改原始单元,总是将新代码放在一个新单元中并使用新类名。这样,原始版本和修改版本可以在IDE中和平共存。很多时候,这正是你不想做的事情。如果原始代码已经损坏并且根本无法工作,为什么我们还要继续使用它呢? - David Heffernan
就我看来,我假设您只是使用此技巧来解决原始RTL/VCL/提供的代码中的错误。如果不是这种情况,那么无论如何,这都是错误的方法,依我之见。 - Rudy Velthuis
显示剩余16条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接