Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi-打开对话框时键盘挂钩处于活动状态_Delphi_Delphi Xe - Fatal编程技术网

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

Delphi-打开对话框时键盘挂钩处于活动状态,delphi,delphi-xe,Delphi,Delphi Xe,在一个应用程序中,我有一个键盘挂钩,当按下Escape按钮时,它会关闭MDI子窗体。当打开一个TopeCudio类子对象时,会出现这个问题。请考虑下面的代码(仅作为例子) 控件:=Screen.ActiveControl 未将opendialog作为活动控件 因此,即使对话框仍然打开,键盘钩子也会被执行,表单也会被关闭 根本的问题是你正在使用键盘挂钩。这是一个全局事件,您需要检测更多的本地键盘事件。您应该安排Delphi表单监听ESC键被按下 恕我直言,我不确定MDI表单或MDI子级是否会收

在一个应用程序中,我有一个键盘挂钩,当按下Escape按钮时,它会关闭MDI子窗体。当打开一个TopeCudio类子对象时,会出现这个问题。请考虑下面的代码(仅作为例子)

控件:=Screen.ActiveControl

  • 未将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.