我在Dephi 2007(32位)中编写Windows可执行文件,将键击发送到另一个应用程序。
在其他应用程序中按热键或热键组合会导致我的应用程序向该应用程序发送击键。如果热键组合 不 包含Ctrl,我的方法可以正常工作:即 F11 或 Shift + F11 正常工作,但 Ctrl + F11 导致我在处理应用程序中的热键后第一次调用SendInput失败。
我已尝试使用多个不同的目标应用程序以及64位Windows 7和32位Windows XP。在我尝试的所有情况下都会出现同样的失败模式。
在处理热键组合时,下面的代码尝试发送两个Shift + Tab键,然后是Tab键到目标应用程序。但是,当Ctrl是热键组合的一部分时,目标应用程序中永远不会看到第一个 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.
答案 0 :(得分:1)
我的猜测是,目标应用程序正在读取 Ctrl 键的状态,并将其检测到,实际上是响应 Shift + Ctrl < / kbd> + Tab ,而不是 Shift + Tab 。
当热键包含'ctrl'键时,在 Shift + 选项卡之前发送'ctrl'键。
begin
KeyInputCount := 0;
if CtrlInHotkey then // to be implemented
KeybdInput(VK_CONTROL, KEYEVENTF_KEYUP);
if bShifted then
KeybdInput(VK_SHIFT, 0);
...