TWinControl的助手

时间:2017-05-09 09:14:44

标签: delphi

我喜欢"覆盖" TWinControl.CNKeyDown,使用Enter键作为Tab,而不修改原始VCL源。 我也这样做,使用SetFocus,女巫效果很好。

助手类型声明为:

type
   TWinControlEx = class helper for TWinControl
   private
       procedure SetFocus; reintroduce;
       procedure CNKeyDown(var Message: TWMKeyDown); reintroduce;
   end;

覆盖的方法如下:

if (Message.CharCode = 13) and (Pos('Cr_To_Tab',ImeName)>0) and (Pos('No_Cr_To_Tab',ImeName)=0) then
      begin
        if not ((GetKeyState(VK_CONTROL) and not $7FFF) <> 0) then
        begin
          Message.CharCode := 9;
        end;
      end;
   Message.CharCode := 9;
   inherited;

但似乎当我的代码运行时,它仍然使用原始版本。另一个令人沮丧的事情是,我无法调试问题,因为当我在CNKeyDown方法中放置一个断点时,它永远不会停止,并且IDE(RAD Studio 10.2)在其中放入一个十字架。

有人可以给我一些指示吗?

2 个答案:

答案 0 :(得分:3)

通常,您不必修改VCL源以扩展TWinControl的后代,因为它有一大堆virtual方法,可以使用{{1在后代类中扩展关键字。 override是一种虚拟方法。

我想知道,你是否真的需要重新实现SetFocus。您是否可以覆盖TWinControl.CNKeyDown

恰好是TWinControl.KeyDown也是一种虚拟方法 实际上,TWinControl.KeyDown被声明为TWinControl.KeyDown,但这是一个微不足道的事情,因为dynamic方法是semantically equivalent并且可以被覆盖为&#34; normal&#34; dynamic声明了方法。

关键字virtual仅在通过声明具有相同名称的方法在后代类中隐藏虚方法时使用。然后编译器会发出警告,可以使用reintroduce关键字来避免。

您的课程应如下所示:

接口

reintroduce

实施

TWinControlEx = class(TWinControl)
protected
  procedure KeyDown(var Key: Word; Shift: TShiftState); override;
public
  procedure SetFocus; override;
end;

答案 1 :(得分:3)

您无法使用类助手重新引入现有方法的新版本,就像您尝试的那样。

类助手不是解决方案。您需要改为:

  1. 从所需的原始类中导出新类,例如TEditoverride其适用的virtual / dynamic方法,例如WndProc()KeyDown()等,然后在运行时而不是原始类创建自定义类的实例。您可以在设计时在IDE中安装自定义类,也可以将您的类实现为Interposer,以便它仅在运行时覆盖原始类。有关详细信息,请参阅Two Approaches to Sub-classing Components Compared

  2. 根本不要派生新课程。只需在运行时子类化原始类的所需对象instanc的WindowProc属性。然后你可以在他们这样做之前处理他们的窗口消息。