delphi - 处理包含 "Ctrl"的热键后 SendInput 失败

标签 delphi hotkeys sendinput registerhotkey

我正在 Dephi 2007(32 位)中编写一个 Windows 可执行文件,它将击键发送到另一个应用程序。

从其他应用程序中按热键或热键组合会导致我的应用程序将击键发送到该应用程序。如果热键组合包含 Ctrl:即 F11Shift+,我的方法就可以正常工作F11 工作正常,但 Ctrl+F11 导致我在处理应用程序中的热键后第一次调用 SendInput 失败。

我已经在多个不同的目标应用程序以及 64 位 Windows 7 和 32 位 Windows XP 中尝试了我的应用程序。在我尝试过的所有情况下都会出现同样的故障模式。

在处理热键组合时,下面的代码尝试向目标应用程序发送两个 Shift+Tab 键,后跟一个 Tab 键。但是,当 Ctrl 是热键组合的一部分时,目标应用程序中永远不会出现 first Shift+Tab 键。 (后续的键可以正常看到。)

我错过了什么?

编辑:我已经在“解决方案”中修改了下面的代码(根据我对 Sertac 的评论)...它现在工作正常,即使将 Ctrl 作为热键序列的一部分也是如此。

unit mainTEST;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus;

type
  T_Mainform = class(TForm)
  private
    procedure WMHotkey(var msg: TWMHotkey); message WM_HOTKEY;
    procedure DoRegisterHotkey;
    procedure SendTabKey(bShifted: boolean);
  public
    procedure AfterConstruction; override;
  end;

var
  _Mainform: T_Mainform;

implementation

{$R *.dfm}

const
  OurHotkeyID = 10;

procedure T_Mainform.AfterConstruction;
begin
  inherited;
  DoRegisterHotkey;
end;


procedure T_Mainform.DoRegisterHotkey;
const
  sHOTKEY = 'Shift+Ctrl+F11';         //Fails!
  //sHOTKEY = 'Shift+F11';              //Succeeds
//  sHOTKEY = 'F11';                    //Succeeds
  //sHOTKEY = 'Shift+Ctrl+F9';          //Fails!
  //sHOTKEY = 'Shift+F9';               //Succeeds
var
  AHotkey : TShortCut;
  hkModifiers: UINT;
  hkText: string;
  hkKey: Word;
  hkShiftState: TShiftState;
begin
  AHotkey := TextToShortcut(sHOTKEY);
  hkModifiers := 0;
  hkText := sHOTKEY;
  if Pos('Shift', hkText) > 0 then
    hkModifiers := hkModifiers or MOD_SHIFT;
  if Pos('Ctrl', hkText) > 0 then
    hkModifiers := hkModifiers or MOD_CONTROL;
  if Pos('Alt', hkText) > 0 then
    hkModifiers := hkModifiers or MOD_ALT;
  ShortCutToKey(AHotkey, hkKey, hkShiftState);

  if not RegisterHotkey(Handle, OurHotkeyID, hkModifiers, hkKey) then
    ShowMessageFmt( 'Unable to register hotkey %s.'#13#13+
        'LastError: %d', [GetLastError]);
end;


procedure T_Mainform.SendTabKey(bShifted: boolean);
var
  KeyInputs: array of TInput;
  KeyInputCount: Integer;
  //------------------------------
  procedure KeybdInput(VKey: Byte; Flags: DWORD);
  begin
    Inc(KeyInputCount);
    SetLength(KeyInputs, KeyInputCount);
    KeyInputs[KeyInputCount - 1].Itype := INPUT_KEYBOARD;
    with  KeyInputs[KeyInputCount - 1].ki do
    begin
      wVk := VKey;
      wScan := MapVirtualKey(wVk, 0);
      dwFlags := KEYEVENTF_EXTENDEDKEY;
      dwFlags := Flags or dwFlags;
      time := 0;
      dwExtraInfo := 0;
    end;
  end;
  //------------------------------
begin
  KeyInputCount := 0;

  if bShifted then
    KeybdInput(VK_SHIFT, 0);
  KeybdInput(VK_TAB, 0);
  KeybdInput(VK_TAB, KEYEVENTF_KEYUP);
  if bShifted then
    KeybdInput(VK_SHIFT, KEYEVENTF_KEYUP);
  SendInput(KeyInputCount, KeyInputs[0], SizeOf(KeyInputs[0]));
  Sleep(50);
end;


procedure T_Mainform.WMHotkey(var msg: TWMHotkey);
begin
  case msg.Hotkey of
    OurHotkeyID:
      if (Screen.ActiveForm = Self) or    //None of our modal dlgs is showing
          (GetLastActivePopup(Application.Handle) = Application.Handle)   //No system dlgs are modal (FileOpen, etc.)
          then begin

        Sleep(200);  //<== THE SOLUTION. Note: values of 150 or less failed!

        SendTabKey(True);       //True=Shift+Tab
        SendTabKey(True);
        Sleep(1000);            //...to observe UI effect
        SendTabKey(False);      //False=Tab
      end;
  end;
end;

end.

最佳答案

我的猜测是,目标应用程序正在读取 Ctrl 键的状态,并向下感应它,实际上是在响应 Shift+Ctrl+TabShift+Tab 相对。

当您的热键包含“ctrl”键时,在 Shift+Tab 之前发送“ctrl”键。

begin
  KeyInputCount := 0;

  if CtrlInHotkey then              // to be implemented
    KeybdInput(VK_CONTROL, KEYEVENTF_KEYUP);

  if bShifted then
    KeybdInput(VK_SHIFT, 0);
  ...

关于delphi - 处理包含 "Ctrl"的热键后 SendInput 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24542330/

相关文章:

listview - TListview FMX onclick 事件以及 Toggle Design

delphi - 从 Delphi 应用程序发送 WM_COPY。到 Windows 7 中的另一个进程

keystroke - SendInput 不适用于游戏

windows - 为 Windows 制作热键的最简单方法是什么?

firefox - 使用 Greasemonkey 在 Firefox 中取消页面前进/后退热键

c# - 使用 C# 的 SendInput 模拟按键事件

delphi - 为什么屏幕返回的分辨率低于我的 Windows 8 平板电脑设置的分辨率?

delphi - Delphi 2010 中返回泛型接口(interface)的泛型方法

delphi - 如何在不禁用 UAC 的情况下在 Windows 7 上运行 Delphi 7?

c# - 使用键盘快捷键触发 Silverlight Prism 命令