在应用程序上,我有一个键盘钩子,当按下Escape按钮时它会关闭MDI子窗体。打开TOpenDialog类后代时会出现此问题(使用Execute)。请考虑以下代码(仅作为示例)
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.
Control:= Screen.ActiveControl;
因此,即使对话框仍然打开,执行键盘钩子并关闭表单。
答案 0 :(得分:6)
根本问题是你(ab)使用键盘钩子。这是一个全局事件,您需要检测更多本地键盘事件。你应该安排你的Delphi表单来监听被按下的 ESC 键。
在我的脑海中,我不确定MDI表格或MDI儿童是否会收到该活动,但无论您需要在那里处理它。可能您需要将KeyPreview
设置为True
才能使其生效。
更一般地说,如果要采用全局方法,键盘钩子仍然是错误的工具。您使用的工具是OnMessage
对象的Application
事件。这连接到应用程序的主消息队列,任何Delphi模式消息泵都从ShowModal
调用运行。将处理放在那里意味着您将检测发往VCL表单的键盘事件,但是您不会为非VCL模式窗口(如文件对话框,Win32消息框等)拾取键盘事件。