简体   繁体   English

Delphi-对话框打开时键盘钩处于活动状态

[英]Delphi - keyboard hook active when dialog opened

On an application I have a keyboard hook which close a MDI child form when the Escape button is pressed. 在一个应用程序上,我有一个键盘钩,当按下Escape按钮时,该钩钩会关闭MDI子窗体。 The issue appear when a TOpenDialog class descendant is opened(with Execute ).Consider the following code (which is only for example) 当打开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; 控件:= Screen.ActiveControl;

  • is not taking the opendialog as the active control. 没有将opendialog作为活动控件。

So, even the dialog is still opened the keyboard hook is executed and the form get closed. 因此,即使对话框仍处于打开状态,也会执行键盘挂钩并关闭表单。

The fundamental problem is that you are (ab)using a keyboard hook. 根本问题是您正在(使用)键盘挂钩。 This is a global event and you need to detect more local keyboard events. 这是一个全局事件,您需要检测更多本地键盘事件。 You should arrange instead for your Delphi forms to listen for the ESC key being pressed. 您应该安排Delphi表单来监听被按下的ESC键。

Off the top of my head, I'm not sure whether the MDI form or the MDI children will receive the event, but whichever it is you need to handle it there. 我不知道是MDI表格还是MDI子级将接收该事件,但是您需要在那里处理它。 Likely you'll need to set KeyPreview to be True for this to work. 可能需要将KeyPreview设置为True才能起作用。

On a more general note, if a global approach was to be appropriate, a keyboard hook is still the wrong tool. 更笼统地说,如果要采用全局方法,则键盘挂钩仍然是错误的工具。 The tool you'd use would be the OnMessage event of the Application object. 您将使用的工具是Application对象的OnMessage事件。 This is wired into the application's main message queue, and any Delphi modal message pumps run from ShowModal calls. 这被连接到应用程序的主消息队列中,所有的Delphi模态消息泵都从ShowModal调用运行。 Putting handling there would mean that you would detect keyboard events destined for VCL forms, but you would not pick up keyboard events for non-VCL modal windows like file dialogs, Win32 message boxes etc. 将处理内容放在那里意味着您将检测到发往VCL表单的键盘事件,但不会为非VCL模态窗口(如文件对话框,Win32消息框等)拾取键盘事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM