Какой простой способ программной имитации пользовательского ввода?

#delphi #mouseevent #keypress #screensaver #delphi-2006

#delphi #mouseevent #нажатие клавиши #заставка #delphi-2006

Вопрос:

У меня есть диалоговое окно, которое появляется в результате ошибки. Я хочу, чтобы диалоговое окно оставалось открытым не менее 30 секунд и закрывалось через 30 секунд после получения последнего пользовательского ввода (мыши или клавиатуры).

Я могу реализовать это, проверив значение, возвращаемое GetLastInputInfo, и закрыв диалоговое окно, когда прошло более 30 секунд, но если диалоговое окно появляется, когда пользователь не был у мыши или клавиатуры в течение 30 секунд, тест GetLastInputInfo проходит немедленно, и диалоговое окно немедленно закрывается. Я мог бы сделать это с другим таймером, но я полагаю, что было бы намного проще имитировать небольшое перемещение мыши или выдачу (безвредного) нажатия клавиши непосредственно перед открытием диалогового окна. Это также имело бы преимущество, предположительно, в том, чтобы вывести систему из screensaver.

Какой самый простой фрагмент кода Delphi из 1 строки для достижения этой цели?

Комментарии:

1. Я бы посоветовал вам придерживаться simple. Используйте таймер, покажите обратный отсчет, закройте диалоговое окно. Не возитесь с мышью — у меня есть система, которая показывает дисплей с 9 утра до 5 вечера, и экран автоматически выключается в нерабочее время. Если вы «покачиваете» мышью, вы побеждаете мой инструмент. Почему вы вмешиваетесь в другие системы для такой простой задачи? (Только мои мысли — не стесняйтесь отклонять!)

Ответ №1:

самый простой — это использование keybd_event функции (одна строка кода)

 keybd_event(Ord('A'), 0, 0, 0);
  

Также вы можете использовать SendInput функцию, но требуется более одной строки 🙂

 Var
  pInputs : TInput;
begin
    pInputs.Itype := INPUT_KEYBOARD;
    pInputs.ki.wVk := Ord('A');
    pInputs.ki.dwFlags := KEYEVENTF_KEYUP;
    SendInput(1, pInputs, SizeOf(pInputs));
end;
  

Ответ №2:

Введите несколько байтовых символов с помощью keybd_event:

 procedure InsertText(text:string);
var i:integer;
    j:integer;
    ch:byte;
    str:string;
begin
  i:=1;
  while i<=Length(text) do
  begin
    ch:=byte(text[i]);
    if Windows.IsDBCSLeadByte(ch) then
       begin
         Inc(i);
         str:=inttostr(MakeWord(byte(text[i]), ch));
         keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), 0, 0);
         j:=1;
         while j<=Length(str) do
         begin
               keybd_event(96 strtoint(str[j]), MapVirtualKey(96 strtoint(str[j]), 0), 0, 0);
               keybd_event(96 strtoint(str[j]), MapVirtualKey(96 strtoint(str[j]), 0), 2, 0);
               j:=j 1;
         end;
         keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), KEYEVENTF_KEYUP, 0);
       end
    else begin
           keybd_event(VkKeyScan(text[i]),0,0,0);
           keybd_event(VkKeyScan(text[i]),0,2,0);
         end;
    Inc(i);
  end;
end;
  

Ответ №3:

https://github.com/WladiD/SendInputHelper автор: г-н Вальдемар Дерр.

Простой и универсальный, выберите 2.

Пример:

 uses
  ..., SendInputHelper;

procedure TForm1.Button1Click(Sender: TObject);
var
  SIH: TSendInputHelper;
begin
  SIH := TSendInputHelper.Create;
  try
    // Start command shell
    SIH.AddShortCut([ssWin], 'r'); // Win R
    SIH.AddDelay(100);
    SIH.AddText('cmd', True); // Second parameter True means AppendReturn
    SIH.AddDelay(500);

    SIH.AddText('ping google.de', True); // Perform a ping.

    SIH.Flush; // Isn't it easy?
  finally
    SIH.Free;
  end;
end;