Delphi 检测另一进程中按下的密钥

Delphi 检测另一进程中按下的密钥,delphi,process,keyboard,Delphi,Process,Keyboard,我有一个Delphi 2007 Win32可执行文件,可以向其他应用程序发送击键。我的应用程序通过热键(如F11或Shift+F11)从这些目标应用程序中调用 我希望用户能够按住一个键中止击键发送(比如,如果他们意识到他们在错误的位置调用了我的应用程序)。我认为Shift、Ctrl和Alt都是很好的选择,因为单靠这些按键不太可能破坏目标应用程序中的任何东西。(例如,转义是一个错误的选择,因为它可能导致目标应用程序关闭一个或多个窗口。) 我在下面编写了函数,并按如下方式定期调用它,同时发送击键以检

我有一个Delphi 2007 Win32可执行文件,可以向其他应用程序发送击键。我的应用程序通过热键(如F11或Shift+F11)从这些目标应用程序中调用

我希望用户能够按住一个键中止击键发送(比如,如果他们意识到他们在错误的位置调用了我的应用程序)。我认为Shift、Ctrl和Alt都是很好的选择,因为单靠这些按键不太可能破坏目标应用程序中的任何东西。(例如,转义是一个错误的选择,因为它可能导致目标应用程序关闭一个或多个窗口。)

我在下面编写了函数,并按如下方式定期调用它,同时发送击键以检测按下的键

if wsAnyKeysDownInWindow( TgtWindow, [VK_Escape, VK_Menu{Alt}, VK_Control, VK_Shift] ) then 
  Abort;
问题是,我的应用程序会发送诸如Shift+Tab和Ctrl+Home这样的按键组合,这(我认为)会使这种方法失败——它总是检测到Shift和/或Ctrl的向下状态。(我还尝试了一个类似的函数,在开始发送击键之前调用SetKeyboardState,以设置键状态的高阶(向下)位,但没有帮助。)

除了挂住键盘,有人想到一个可行的方法吗

function wsAnyKeysDownInWindow(Handle: HWnd; VKeys: array of byte): boolean;
{ Checks whether each of the VKeys set of virtual keys is down in Handle,
  a window created by another process. }
var
  OtherThreadID : integer;
  State: TKeyboardState;
  AKey: byte;
begin
  Result := False;
  if not IsWindow(Handle) then
    exit;
  OtherThreadID := GetWindowThreadProcessID( Handle, nil);
  if AttachThreadInput( GetCurrentThreadID, OtherThreadID, True ) then try
    GetKeyboardState(State);
    for AKey in VKeys do
      if (State[AKey] and 128) <> 0 then begin  //If high-order bit is set, key is down
        Result := True;
        exit;
      end;
  finally
    AttachThreadInput( GetCurrentThreadID, OtherThreadID, False );
  end;
end;
函数wsAnyKeysDownInWindow(句柄:HWnd;VKeys:字节数组):布尔;
{检查虚拟密钥集的每个VKeys是否在句柄中关闭,
由另一进程创建的窗口。}
变量
OtherThreadID:整数;
状态:TKeyboardState;
AKey:字节;
开始
结果:=假;
如果不是IsWindow(句柄),则
出口
OtherThreadID:=GetWindowThreadProcessID(句柄,无);
如果AttachThreadInput(GetCurrentThreadID,OtherThreadID,True),请重试
GetKeyboardState(状态);
对于VKeys中的AKey
如果(状态[AKey]和128)为0,则开始//如果设置了高阶位,则键为向下
结果:=真;
出口
结束;
最后
AttachThreadInput(GetCurrentThreadID,OtherThreadID,False);
结束;
结束;

为此,请考虑使用
滚动锁。它很少被使用(我只想到Excel),如果键被发送或未被发送,您甚至可以看到指示器


顺便说一句,
Alt
不是一个好的选择,还有另一个原因-它调用应用程序中的主菜单(当然,如果有主菜单)。

SetKeyboardState
不能跨线程/进程工作,但您可以尝试搜索
AttachThreadInput
。Sertac:这就是我使用SetKeyboardState的方式——我调用了AttachThreadInput,然后GetKeyboardState获取目标进程的当前状态,重置状态数组中选定虚拟键的高阶(向下)位,然后调用SetKeyboardState。但我后来对上面所示函数的调用发现键处于关闭状态…我认为这是我发送的击键。(在发送击键之前,我还尝试了PeekMessage()循环,以从队列中删除任何多余的击键,但这也不起作用。)滚动锁可能没问题,但大多数用户无法直观地知道它在键盘上的位置!我希望支持一个不那么晦涩的键。是的,我意识到Alt是一个糟糕的选择,因为你给出的原因。我不认为Scroll Lock是模糊的。不太“模糊”的键是那些经常使用的键,所以这就排除了它们。滚动锁的另一个好处是
打开
/
关闭
键,通常有一个LED指示灯,可以直观地指示状态。