I want to send Alt Mouse Click to some programs.
It works in most programs, it needs a small delay for some, but doesn't work at all in one of them.
The mouse click is working, but the Alt key isn't. If I hold Alt manually and trigger a Mouse Click with SendInput()
, it works. So I assume that the Alt key press is not being sent/handled correctly?
This is the code I'm using:
void SendAltClick()
{
INPUT inputs[4] = {};
ZeroMemory(&inputs, sizeof(INPUT));
// Alt down
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = VK_MENU;
// Left down
inputs[1].type = INPUT_MOUSE;
inputs[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
// Left up
inputs[2].type = INPUT_MOUSE;
inputs[2].mi.dwFlags = MOUSEEVENTF_LEFTUP;
// Alt up
inputs[3].type = INPUT_KEYBOARD;
inputs[3].ki.wVk = VK_MENU;
inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
}
All calls to SendInput()
return 1.
I've also tried Ctrl/Shift Click, and they work as expected.
Why doesn't it behave the same way with all programs? Why does it need a small delay for some of them? Why doesn't it work at all with one of them?
I can only reproduce with some specific programs. I don't know if I should post the specific details here, since they contain names to commercial products.
EDIT: I went back to the documentation and found the following note at the end of the remarks section, could it be related? How?
An accessibility application can use SendInput to inject keystrokes corresponding to application launch shortcut keys that are handled by the shell. This functionality is not guaranteed to work for other types of applications.
CodePudding user response:
It works in most programs, it needs a small delay for some, but doesn't work at all in one of them.
"Most programs" check the Alt key state from inside the mouse message handler with correct synchronization. There are two correct ways:
- Look at the modifier flags in the message parameters (only applicable to Control and Shift, NOT Alt)
GetKeyState()
"Needs a small delay for some" -- these programs check the Alt key state unsynchronized with the message delivery, probably with
GetAsyncKeyState()
but it could also mean the mouse message handler sets a flag and then some later code calls GetKeyState()
"doesn't work at all in one of them"
This program doesn't use the OS input queue (and its abstraction of keyboard state) at all for the behavior you are after, it reads the Alt key from the true keyboard, for example using Raw Input, DirectInput or the HID API. Usually you only see these techniques in games.
To make this "reads the true keyboard" program behave as if the Alt key is pressed, you'll need a USB keyboard simulator/driver sending real HID profile USB events, where the Raw Input portion of the OS will see them. And the program will still be able to detect a difference between "Alt key on keyboard #1" vs "Alt key on keyboard #2"
CodePudding user response:
Going along with what YangXiaoPo-MSFT said, why don't you just create a Array of INPUT unions and send all of them at once?
INPUT[4] input = { };
// Move mouse to pos
SetCursorPos(pos.x, pos.y);
ZeroMemory(&input, sizeof(INPUT) * 4ul);
// Alt down
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = VK_MENU;
// Left down
input[1].type = INPUT_MOUSE;
input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
// Left up
input[2].type = INPUT_MOUSE;
input[2].mi.dwFlags = MOUSEEVENTF_LEFTUP;
// Alt up
input[3].type = INPUT_KEYBOARD;
input[3].ki.wVk = VK_MENU;
input[3].ki.dwFlags = KEYEVENTF_KEYUP;
// Sending the inputs all at once
SendInput(4u, &input, sizeof(INPUT) * 4);
Secondly, you said the program that didn't work had a child window, Did you make sure you were targeting the correct HANDLE
of that window?