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.
procedure TMainForm.AutoPressTimer(Sender: TObject);
var
i,j,k: longInt;
action: TAutoAction;
amountOfInputsContiguos: longInt;
tempInputBufferArray: array of INPUT;
tempInput: ^INPUT;
begin
if (isWaitingActionTimer) then
begin
exit;
end;
// execute all inputs in actionList
//showMessage('Amount of auto actions: ' + IntToStr(autoActions.Count));
tempInputBuffer.Clear;
amountOfInputsContiguos := 0;
for i:=0 to autoActions.Count-1 do
begin
action := autoActions.Items[i];
tempInputBuffer.Add(@action.inputAction);
Inc(amountOfInputsContiguos);
if (action.waitTimer.Interval <> 0) then // they are not contiguos, let's sendInput whatever's in the buffer
begin
//
setLength(tempInputBufferArray, amountOfInputsContiguos);
for j:=0 to amountOfInputsContiguos-1 do
begin
tempInput := tempInputBuffer[j];
tempInputBufferArray[j] := tempInput^;
end;
SendInput(amountOfInputsContiguos, @tempInputBufferArray, sizeof(INPUT));
amountOfInputsContiguos := 0;
zeroMemory(tempInputBufferArray, amountOfInputsContiguos);
tempInputBuffer.Clear;
action.waitTimer.Enabled:=true;
isWaitingActionTimer := true;
exit;
end
else
begin
// they are contiguios just put it in the queue
end;
end;
// finish off remaining input if there are any
if (amountOfInputsContiguos <> 0) then
begin
setLength(tempInputBufferArray, amountOfInputsContiguos);
for j:=0 to amountOfInputsContiguos-1 do
begin
tempInput := tempInputBuffer[j];
tempInputBufferArray[j] := tempInput^;
end;
SendInput(amountOfInputsContiguos, @tempInputBufferArray, sizeof(INPUT));
amountOfInputsContiguos := 0;
zeroMemory(tempInputBufferArray, amountOfInputsContiguos);
tempInputBuffer.Clear;
end;
end;
This function populates my TList of INPUTs:
procedure TAddAutoActionForm.AddActionButtonClick(Sender: TObject);
var
newInput: INPUT;
newWaitInterval: LONG;
begin
if (KeyboardInputInfoBox.Visible) and ((KeyDetectedEdit.Caption = '') or (VKDetectedEdit.Caption = '') or (ScanCodeDetectedEdit.Caption = '')) then
begin
//
Application.MessageBox('Key detection failed! Try again!', 'Error', MB_ICONWARNING or MB_OK);
exit;
end;
if (InputSelectionBox.Items[InputSelectionBox.ItemIndex] = 'Keyboard') then
begin
//
newInput.type_ := INPUT_KEYBOARD;
newInput.ki.dwExtraInfo := 0;
newInput.ki.dwFlags := KEYEVENTF_SCANCODE or KEYEVENTF_UNICODE;
if (InputTypeCombo1.Items[InputTypeCombo1.ItemIndex] = 'Release a button') then
begin
showMessage('Key up');
newInput.ki.dwFlags := newInput.ki.dwFlags or KEYEVENTF_KEYUP;
end
else
begin
showMessage('Key down');
end;
newInput.ki.time := 0;
newInput.ki.wScan := StrToInt(ScanCodeDetectedEdit.Caption);
newInput.ki.wVk := StrToInt(VKDetectedEdit.Caption);
end
else
begin
//
newInput.type_ := INPUT_MOUSE;
newInput.mi.time:=0;
newInput.mi.dwFlags:=0;
if (InputTypeCombo.Items[InputTypeCombo.ItemIndex] = 'Release a button') then
begin
//
newInput.mi.dx:=0;
newInput.mi.dy:=0;
if (InputButtonCombo.Items[InputButtonCombo.ItemIndex] = 'LMB') then
begin
showMessage('LMB UP');
newInput.mi.dwFlags:=MOUSEEVENTF_LEFTUP;
end
else if (InputButtonCombo.Items[InputButtonCombo.ItemIndex] = 'RMB') then
begin
showMessage('RMB UP');
newInput.mi.dwFlags:=MOUSEEVENTF_RIGHTUP;
end
else
begin
showMessage('MMB UP');
newInput.mi.dwFlags:=MOUSEEVENTF_MIDDLEUP;
end;
end
else if (InputTypeCombo.Items[InputTypeCombo.ItemIndex] = 'Press a button') then
begin
//
newInput.mi.dx:=0;
newInput.mi.dy:=0;
if (InputButtonCombo.Items[InputButtonCombo.ItemIndex] = 'LMB') then
begin
showMessage('LMB DOWN');
newInput.mi.dwFlags:=MOUSEEVENTF_LEFTDOWN;
end
else if (InputButtonCombo.Items[InputButtonCombo.ItemIndex] = 'RMB') then
begin
showMessage('RMB DOWN');
newInput.mi.dwFlags:=MOUSEEVENTF_RIGHTDOWN;
end
else
begin
showMessage('MMB DOWN');
newInput.mi.dwFlags:=MOUSEEVENTF_MIDDLEDOWN;
end;
end
else
begin
// Move !
newInput.mi.dx := StrToInt(MovementXEdit.Caption) * (65536 div GetSystemMetrics(SM_CXSCREEN)); //x being coord in pixels
newInput.mi.dy := StrToInt(MovementYEdit.Caption) * (65536 div GetSystemMetrics(SM_CYSCREEN)); //y being coord in pixels
newInput.mi.dwFlags := MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE;
end;
end;
newWaitInterval := StrToInt(DelayEdit.Caption);
autoActions.Add(TAutoAction.Create(newInput, newWaitInterval));
end;
If you're really interested in helping me, here's the full project:
https://drive.google.com/open?id=0B3BcZ_k2AnDZQ1FYRzlzZVBOS3M