我喜欢"覆盖" 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)在其中放入一个十字架。
有人可以给我一些指示吗?
答案 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)
您无法使用类助手重新引入现有方法的新版本,就像您尝试的那样。
类助手不是解决方案。您需要改为:
从所需的原始类中导出新类,例如TEdit
和override
其适用的virtual
/ dynamic
方法,例如WndProc()
,KeyDown()
等,然后在运行时而不是原始类创建自定义类的实例。您可以在设计时在IDE中安装自定义类,也可以将您的类实现为Interposer,以便它仅在运行时覆盖原始类。有关详细信息,请参阅Two Approaches to Sub-classing Components Compared。
根本不要派生新课程。只需在运行时子类化原始类的所需对象instanc的WindowProc
属性。然后你可以在他们这样做之前处理他们的窗口消息。