Recent

Author Topic: SendInput() being ignored  (Read 2537 times)

pinkVeil

  • Newbie
  • Posts: 4
SendInput() being ignored
« on: July 22, 2017, 08:58:49 am »
I am trying to simulate input using SendInput() function from WinAPI. It seem to be working fine when I hard code a couple of inputs and send them. But when I add INPUTs at run time and send them via the same function, nothing happens.

I add INPUTs at run time by adding them into a TList and then reading that list into an array of INPUTs, that array will then be given as one of the parameters to SendInput();

The weird thing is, is that SendInput() returns the correct Int value (the amount of successful inputs that were put into input streams), which means that evens are being inserted into input streams. But as I said, nothing seems to happen.

I'm new to WinAPI and I'm a Delphi rookie, so I'm stuck and asking for help.


Here are some code snippets that might be useful to you:
This is the OnTimer function that is being called over and over again to grab events from my TList of INPUTs and send them to input streams.
Code: Pascal  [Select][+][-]
  1. procedure TMainForm.AutoPressTimer(Sender: TObject);
  2. var
  3.   i,j,k: longInt;
  4.   action: TAutoAction;
  5.   amountOfInputsContiguos: longInt;
  6.   tempInputBufferArray: array of INPUT;
  7.   tempInput: ^INPUT;
  8. begin
  9.   if (isWaitingActionTimer) then
  10.   begin
  11.     exit;
  12.   end;
  13.   // execute all inputs in actionList
  14.   //showMessage('Amount of auto actions: ' + IntToStr(autoActions.Count));
  15.   tempInputBuffer.Clear;
  16.  
  17.   amountOfInputsContiguos := 0;
  18.   for i:=0 to autoActions.Count-1 do
  19.   begin
  20.     action := autoActions.Items[i];
  21.     tempInputBuffer.Add(@action.inputAction);
  22.     Inc(amountOfInputsContiguos);
  23.  
  24.     if (action.waitTimer.Interval <> 0) then // they are not contiguos, let's sendInput whatever's in the buffer
  25.     begin
  26.       //
  27.       setLength(tempInputBufferArray, amountOfInputsContiguos);
  28.       for j:=0 to amountOfInputsContiguos-1 do
  29.       begin
  30.         tempInput := tempInputBuffer[j];
  31.         tempInputBufferArray[j] := tempInput^;
  32.       end;
  33.  
  34.       SendInput(amountOfInputsContiguos, @tempInputBufferArray, sizeof(INPUT));
  35.       amountOfInputsContiguos := 0;
  36.       zeroMemory(tempInputBufferArray, amountOfInputsContiguos);
  37.       tempInputBuffer.Clear;
  38.  
  39.       action.waitTimer.Enabled:=true;
  40.       isWaitingActionTimer := true;
  41.       exit;
  42.     end
  43.     else
  44.     begin
  45.       // they are contiguios just put it in the queue
  46.  
  47.     end;
  48.   end;
  49.  
  50.   // finish off remaining input if there are any
  51.   if (amountOfInputsContiguos <> 0) then
  52.   begin
  53.     setLength(tempInputBufferArray, amountOfInputsContiguos);
  54.     for j:=0 to amountOfInputsContiguos-1 do
  55.     begin
  56.       tempInput := tempInputBuffer[j];
  57.       tempInputBufferArray[j] := tempInput^;
  58.     end;
  59.  
  60.     SendInput(amountOfInputsContiguos, @tempInputBufferArray, sizeof(INPUT));
  61.     amountOfInputsContiguos := 0;
  62.     zeroMemory(tempInputBufferArray, amountOfInputsContiguos);
  63.     tempInputBuffer.Clear;
  64.   end;
  65. end;
  66.  

This function populates my TList of INPUTs:
Code: Pascal  [Select][+][-]
  1. procedure TAddAutoActionForm.AddActionButtonClick(Sender: TObject);
  2. var
  3.   newInput: INPUT;
  4.   newWaitInterval: LONG;
  5. begin
  6.   if (KeyboardInputInfoBox.Visible) and ((KeyDetectedEdit.Caption = '') or (VKDetectedEdit.Caption = '') or (ScanCodeDetectedEdit.Caption = '')) then
  7.   begin
  8.     //
  9.     Application.MessageBox('Key detection failed! Try again!', 'Error', MB_ICONWARNING or MB_OK);
  10.     exit;
  11.   end;
  12.  
  13.   if (InputSelectionBox.Items[InputSelectionBox.ItemIndex] = 'Keyboard') then
  14.   begin
  15.     //
  16.     newInput.type_ := INPUT_KEYBOARD;
  17.     newInput.ki.dwExtraInfo := 0;
  18.     newInput.ki.dwFlags := KEYEVENTF_SCANCODE or KEYEVENTF_UNICODE;
  19.     if (InputTypeCombo1.Items[InputTypeCombo1.ItemIndex] = 'Release a button') then
  20.     begin
  21.       showMessage('Key up');
  22.       newInput.ki.dwFlags := newInput.ki.dwFlags or KEYEVENTF_KEYUP;
  23.     end
  24.     else
  25.     begin
  26.  
  27.       showMessage('Key down');
  28.     end;
  29.     newInput.ki.time := 0;
  30.     newInput.ki.wScan := StrToInt(ScanCodeDetectedEdit.Caption);
  31.     newInput.ki.wVk := StrToInt(VKDetectedEdit.Caption);
  32.   end
  33.   else
  34.   begin
  35.     //
  36.     newInput.type_ := INPUT_MOUSE;
  37.     newInput.mi.time:=0;
  38.     newInput.mi.dwFlags:=0;
  39.     if (InputTypeCombo.Items[InputTypeCombo.ItemIndex] = 'Release a button') then
  40.     begin
  41.       //
  42.       newInput.mi.dx:=0;
  43.       newInput.mi.dy:=0;
  44.  
  45.       if (InputButtonCombo.Items[InputButtonCombo.ItemIndex] = 'LMB') then
  46.       begin
  47.         showMessage('LMB UP');
  48.         newInput.mi.dwFlags:=MOUSEEVENTF_LEFTUP;
  49.       end
  50.       else if (InputButtonCombo.Items[InputButtonCombo.ItemIndex] = 'RMB') then
  51.       begin
  52.         showMessage('RMB UP');
  53.         newInput.mi.dwFlags:=MOUSEEVENTF_RIGHTUP;
  54.       end
  55.       else
  56.       begin
  57.         showMessage('MMB UP');
  58.         newInput.mi.dwFlags:=MOUSEEVENTF_MIDDLEUP;
  59.       end;
  60.     end
  61.     else if (InputTypeCombo.Items[InputTypeCombo.ItemIndex] = 'Press a button') then
  62.     begin
  63.       //
  64.       newInput.mi.dx:=0;
  65.       newInput.mi.dy:=0;
  66.  
  67.       if (InputButtonCombo.Items[InputButtonCombo.ItemIndex] = 'LMB') then
  68.       begin
  69.         showMessage('LMB DOWN');
  70.         newInput.mi.dwFlags:=MOUSEEVENTF_LEFTDOWN;
  71.       end
  72.       else if (InputButtonCombo.Items[InputButtonCombo.ItemIndex] = 'RMB') then
  73.       begin
  74.         showMessage('RMB DOWN');
  75.         newInput.mi.dwFlags:=MOUSEEVENTF_RIGHTDOWN;
  76.       end
  77.       else
  78.       begin
  79.         showMessage('MMB DOWN');
  80.         newInput.mi.dwFlags:=MOUSEEVENTF_MIDDLEDOWN;
  81.       end;
  82.     end
  83.     else
  84.     begin
  85.       // Move !
  86.       newInput.mi.dx := StrToInt(MovementXEdit.Caption) * (65536 div GetSystemMetrics(SM_CXSCREEN)); //x being coord in pixels
  87.       newInput.mi.dy :=  StrToInt(MovementYEdit.Caption) * (65536 div GetSystemMetrics(SM_CYSCREEN)); //y being coord in pixels
  88.       newInput.mi.dwFlags := MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE;
  89.     end;
  90.   end;
  91.  
  92.   newWaitInterval := StrToInt(DelayEdit.Caption);
  93.  
  94.   autoActions.Add(TAutoAction.Create(newInput, newWaitInterval));
  95. end;
  96.  

If you're really interested in helping me, here's the full project: https://drive.google.com/open?id=0B3BcZ_k2AnDZQ1FYRzlzZVBOS3M

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: SendInput() being ignored
« Reply #1 on: July 22, 2017, 11:16:41 am »
I am trying to simulate input using SendInput() function from WinAPI. It seem to be working fine when I hard code a couple of inputs and send them. But when I add INPUTs at run time and send them via the same function, nothing happens.
This example works. In new project with button and edit:
Code: Pascal  [Select][+][-]
  1. //...
  2. uses JwaWinUser, //...
  3. //...
  4.   private
  5.     FInputs: array of TInput;
  6. //...
  7. procedure TForm1.Button1Click(Sender: TObject);
  8. begin
  9.   Button1.Enabled := False;
  10.   Edit1.Visible := False;
  11.   FInputs := nil;
  12. end;
  13.  
  14. procedure TForm1.FormCreate(Sender: TObject);
  15. begin
  16.   KeyPreview := True;
  17.   Edit1.Caption := 'Press the button, then enter some text (the input is not displayed), and at the end, press Enter';
  18. end;
  19.  
  20. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  21. begin
  22.   if (Key = VK_RETURN) and Assigned(FInputs) then
  23.   begin
  24.     Key := 0;
  25.     Button1.Enabled := True;
  26.     Edit1.Visible := True;
  27.     ActiveControl := Edit1;
  28.     Button1.Caption := IntToStr(SendInput(Length(FInputs), @FInputs[0], SizeOf(FInputs[0])));
  29.   end;
  30. end;
  31.  
  32. procedure TForm1.FormUTF8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);
  33. var
  34.   R: TInput;
  35.   U: UnicodeString;
  36. begin
  37.   if not Button1.Enabled then
  38.   begin
  39.     {$WARN 4104 off : Implicit string type conversion from "$1" to "$2"}
  40.     U := UTF8Key;
  41.     {$WARN 4104 on}
  42.     if Length(U) = 1 then
  43.     begin
  44.       FillChar(R, SizeOf(R), 0);
  45.       R.type_ := INPUT_KEYBOARD;
  46.       R.ki.wScan := Word(U[1]);
  47.       R.ki.dwFlags := KEYEVENTF_UNICODE;
  48.       SetLength(FInputs, Length(FInputs) + 2);
  49.       FInputs[High(FInputs) - 1] := R;
  50.       R.ki.dwFlags := R.ki.dwFlags or KEYEVENTF_KEYUP;
  51.       FInputs[High(FInputs)] := R;
  52.     end;
  53.   end;
  54. end;

pinkVeil

  • Newbie
  • Posts: 4
Re: SendInput() being ignored
« Reply #2 on: July 23, 2017, 03:13:09 pm »
Thank you so much, this works perfectly!

 

TinyPortal © 2005-2018