Delphi-打开对话框时键盘挂钩处于活动状态
在一个应用程序中,我有一个键盘挂钩,当按下Escape按钮时,它会关闭MDI子窗体。当打开一个TopeCudio类子对象时,会出现这个问题。请考虑下面的代码(仅作为例子) 控件:=Screen.ActiveControlDelphi-打开对话框时键盘挂钩处于活动状态,delphi,delphi-xe,Delphi,Delphi Xe,在一个应用程序中,我有一个键盘挂钩,当按下Escape按钮时,它会关闭MDI子窗体。当打开一个TopeCudio类子对象时,会出现这个问题。请考虑下面的代码(仅作为例子) 控件:=Screen.ActiveControl 未将opendialog作为活动控件 因此,即使对话框仍然打开,键盘钩子也会被执行,表单也会被关闭 根本的问题是你正在使用键盘挂钩。这是一个全局事件,您需要检测更多的本地键盘事件。您应该安排Delphi表单监听ESC键被按下 恕我直言,我不确定MDI表单或MDI子级是否会收
- 未将opendialog作为活动控件
因此,即使对话框仍然打开,键盘钩子也会被执行,表单也会被关闭 根本的问题是你正在使用键盘挂钩。这是一个全局事件,您需要检测更多的本地键盘事件。您应该安排Delphi表单监听ESC键被按下 恕我直言,我不确定MDI表单或MDI子级是否会收到该事件,但不管是哪一个,您都需要在那里处理它。您可能需要将
KeyPreview
设置为True
,才能正常工作
更一般地说,如果采用全局方法是合适的,那么键盘挂钩仍然是错误的工具。您将使用的工具是
应用程序
对象的OnMessage
事件。这被连接到应用程序的主消息队列中,任何Delphi模式消息泵都从showmodel
调用运行。将处理放在那里意味着您将检测到发送给VCL窗体的键盘事件,但不会为非VCL模式窗口(如文件对话框、Win32消息框等)拾取键盘事件。我假设您的问题是*为什么会这样?“这是因为“打开”对话框不是vcl控件。即使TOpenDialog不是vcl控件,它也是TComponent的后代。是的……这就是同事使用您的帐户时发生的情况。谢谢大家!!如果GetWindowTask返回当前的线程id,这看起来像是一个线程挂钩,但这很小。@SertacAkyuz我指的不是技术意义上的全局vs线程,正如SetWindowHookEx
所使用的那样。我在这里更松散地使用全局,影响整个应用程序。
unit Unit4;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm4 = class(TForm)
OpenDialog1: TOpenDialog;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
function KeyboardProc(code: integer; wp: WPARAM; lp: LPARAM): LResult stdcall;
function CanDoCloseOnEscape: boolean;
var
Form4: TForm4;
KeybHook : HHook;
implementation
{$R *.dfm}
function CanDoCloseOnEscape: boolean;
var
Control: TWinControl;
Form: TForm;
begin
Control := Screen.ActiveControl;
Form := Screen.ActiveForm;
Result := true;
end;
function KeyboardProc(code: integer; wp: WPARAM; lp: LPARAM): LResult stdcall;
begin
case wp of
VK_ESCAPE:
if CanDoCloseOnEscape then
begin
PostMessage(Screen.ActiveForm.Handle, WM_Close, 0, 0);
exit;
end;
end;
end;
procedure TForm4.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
ShowMessage('executed');
end;
end;
initialization
KeybHook := SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hInstance,GetWindowTask(application.Handle));
finalization
UnhookWindowsHookEx(KeybHook);
end.