在我的
我在想这是否是正确/唯一的方法。
TComponent
中,有一个地方我想监听按键事件并拦截 ESC
键,在我的组件中处理它,消耗/“吃掉”这个按键,这样例如所有者窗体就不会在那个阶段处理它。就像在 TDragObject
中,当你开始拖动并通过按下 ESC
键取消它时一样。
问题是 TDragObject
有一个叫做 AllocateHWnd
的方法,由其所有者窗体通过 CN_KEYDOWN
进行通知。但没有人通知我的组件。
我需要替换表单的 WindowProc
吗?如果是,那么如何正确地进行“按照书本上说”的操作呢?
为了100%的清晰:
TMyComponent = class(TComponent)
我做了一个小测试,似乎它可以工作:
TMyComponent = class(TComponent)
private
FOldWindowProc: TWndMethod;
FParentForm: TCustomForm;
procedure FormWindowProc(var Message: TMessage);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
...
constructor TMyComponent.Create(AOwner: TComponent);
begin
if not (AOwner is TWinControl) then
raise Exception.Create('TMyComponent.Create: Owner must be a TWinControl');
inherited Create(AOwner);
// hook parent form
FParentForm := GetParentForm(TWinControl(Owner));
if Assigned(FParentForm) then
begin
FOldWindowProc := FParentForm.WindowProc;
FParentForm.WindowProc := FormWindowProc;
end;
end;
destructor TMyComponent.Destroy;
begin
// unhook parent form
if Assigned(FParentForm) then
FParentForm.WindowProc := FOldWindowProc;
inherited;
end;
procedure TMyComponent.FormWindowProc(var Message: TMessage);
begin
FOldWindowProc(Message);
if Message.Msg = CM_CHILDKEY then // CM_CHILDKEY -> CM_DIALOGKEY -> CM_DIALOGCHAR
begin
OutputDebugString('CM_CHILDKEY');
if Message.WParam = VK_ESCAPE then
begin
Beep;
// do my stuff...
Message.Result := 1; // consume keystroke
end;
end;
end;
我在想这是否是正确/唯一的方法。
WM_GETDLGCODE
处理程序和DLGC_WANTALLKEYS
;没时间测试。 - Cosmin PrundSetWindowsHookEx
),或者拥有自己的消息循环...讨论“正确”的方法,我想,需要了解确切的场景。 - Sertac Akyuz