Delphi - 打开对话框时激活键盘钩子

时间:2013-09-03 13:42:35

标签: delphi delphi-xe

在应用程序上,我有一个键盘钩子,当按下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;

  • 没有将opendialog作为主动控件。

因此,即使对话框仍然打开,执行键盘钩子并关闭表单。

1 个答案:

答案 0 :(得分:6)

根本问题是你(ab)使用键盘钩子。这是一个全局事件,您需要检测更多本地键盘事件。你应该安排你的Delphi表单来监听被按下的 ESC 键。

在我的脑海中,我不确定MDI表格或MDI儿童是否会收到该活动,但无论您需要在那里处理它。可能您需要将KeyPreview设置为True才能使其生效。

更一般地说,如果要采用全局方法,键盘钩子仍然是错误的工具。您使用的工具是OnMessage对象的Application事件。这连接到应用程序的主消息队列,任何Delphi模式消息泵都从ShowModal调用运行。将处理放在那里意味着您将检测发往VCL表单的键盘事件,但是您不会为非VCL模式窗口(如文件对话框,Win32消息框等)拾取键盘事件。