SendInput против keybd_event

MSDN утверждает, что keybd_event был заменен SendInput. Во время перезаписи я переключился на использование SendInput..., что было нормально, кроме при попытке отправить комбинацию клавиш Alt. В 64-разрядной системе Win7 (еще нигде не пробовал) отправка клавиши Alt вызывает длительную задержку, прежде чем нажатие клавиши станет очевидным в целевом приложении.

Есть идеи, почему? Или что я сделал не так? А пока я вернулся к keybd_event — второй версии ниже.

//Keyboard input from this version appears only after a ~4-5 second
//time lag...
procedure SendAltM;
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
  KeybdInput(VK_MENU, 0);                 // Alt
  KeybdInput(Ord('M'), 0);                 
  KeybdInput(Ord('M'), KEYEVENTF_KEYUP);   
  KeybdInput(VK_MENU, KEYEVENTF_KEYUP);   // Alt
  SendInput(KeyInputCount, KeyInputs[0], SizeOf(KeyInputs[0]));
end;


//Keyboard input from this version appears immediately...
procedure SendAltM;
begin
  keybd_event( VK_MENU, MapVirtualkey( VK_MENU, 0 ), 0, 0);
  keybd_event( Ord('M'), MapVirtualKey( Ord('M'),0), 0, 0);
  keybd_event( Ord('M'), MapVirtualKey( Ord('M'),0), KEYEVENTF_KEYUP, 0);
  keybd_event( VK_MENU, MapVirtualkey( VK_MENU, 0 ), KEYEVENTF_KEYUP, 0);
end;

person Mark Wilsdorf    schedule 06.09.2013    source источник
comment
Большая проблема с keybd_event заключается в том, что ваши события могут быть совмещены с реальными. Так что SendInput это работа. Не знаю, почему у тебя проблемы. Все же.   -  person David Heffernan    schedule 06.09.2013


Ответы (2)


Проблема 1

Вы не инициализировали KeyInputCount. Таким образом, его значение не определено. Установите его на ноль перед вызовом KeybdInput в первый раз. Или просто избавьтесь от него и используйте вместо него Length(KeyInputs).

Проблема 2

Ваша настройка dwFlags неверна. Не включайте KEYEVENTF_EXTENDEDKEY. Вы не включили его в код, вызывающий keybd_event, и не должны включать его для SendInput.

Исправленный код

Эта версия работает.

procedure SendAltM;
var
  KeyInputs: array of TInput;
  //--------------------------------------------
  procedure KeybdInput(VKey: Byte; Flags: DWORD);
  begin
    SetLength(KeyInputs, Length(KeyInputs)+1);
    KeyInputs[high(KeyInputs)].Itype := INPUT_KEYBOARD;
    with  KeyInputs[high(KeyInputs)].ki do
    begin
      wVk := VKey;
      wScan := MapVirtualKey(wVk, 0);
      dwFlags := Flags;
    end;
  end;
begin
  KeybdInput(VK_MENU, 0);                 // Alt
  KeybdInput(Ord('M'), 0);
  KeybdInput(Ord('M'), KEYEVENTF_KEYUP);
  KeybdInput(VK_MENU, KEYEVENTF_KEYUP);   // Alt
  SendInput(Length(KeyInputs), KeyInputs[0], SizeOf(KeyInputs[0]));
end;
person David Heffernan    schedule 06.09.2013
comment
Неинициализированный счетчик объясняет задержку. ОС потребовала бы бог знает сколько времени на обработку всех поддельных нулевых событий мыши в массиве, прежде чем, наконец, добраться до четырех действительных событий клавиатуры в конце. - person Rob Kennedy; 06.09.2013
comment
@Rob Думаю, основная проблема - это ошибочный флаг. - person David Heffernan; 06.09.2013
comment
Спасибо, Дэвид и @Rob. Я не знаю, была ли проблема неинициализированным KeyInputCount или флагом; просто рад, что понял это. О, и так легко увидеть, что KeyInputCount был неинициализирован... теперь, когда кто-то другой указал на это! - person Mark Wilsdorf; 07.09.2013

таким образом вы можете использовать keybd_event:

keybd_event( VK_MENU, MapVirtualkey( VK_MENU, 0 ), KEYEVENTF_EXTENDEDKEY or 0, 0);
  keybd_event( Ord('M'), MapVirtualKey( Ord('M'),0), KEYEVENTF_EXTENDEDKEY or 0, 0);
  keybd_event( Ord('M'), MapVirtualKey( Ord('M'),0), KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
  keybd_event( VK_MENU, MapVirtualkey( VK_MENU, 0 ), KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
person Bertalan    schedule 17.02.2016