I need to show the windows switcher with SendInput. Another question I asked explains the reason of doing this. Shortly speaking, when I am holding Alt Tab to switch to other apps, my app may fire a key stroke using SendInput, which will interrupt current switcher, and this is why I need to refire a Alt Tab. Currently I am working on posting another tab key stroke (I am still holding alt when switching) or the entirely alt down + tab down & up. But with alt holding, a single tab stroke sent by SendInput will not trigger the switcher. And the entire combined key does not work neither. Here's some test code.
#include <windows.h>
#include <WinUser.h>
#include <iostream>
int main(void) {
Sleep(1000 * 3);
INPUT tabinput[2];
tabinput[0].type = INPUT_KEYBOARD;
tabinput[0].ki = {0x09, 0}; // KEY_TAB = 0x09
tabinput[1].type = INPUT_KEYBOARD;
tabinput[1].ki = {0x09, 0, KEYEVENTF_KEYUP};
SendInput(2, tabinput, sizeof(INPUT));
getchar();
}
I'm trying to fire a tab key stroke delayed 3s. I'am holding the alt key. This doesn't work. But the tab key is triggered, because When I run this code and switch to a text editor or something, there will be a tab event. My system is win8.1 64bit.
Windows 8 is blocking you.
In the Windows 8 security model, apps don’t have the privileges required to be a UI automation client. But you can write a desktop app that acts as an automation client with your app as the target. To do this, your desktop automation client app needs to be built with UIAccess permissions.
Change the manifest to UIAccess="true" and require administrator priviledge, created a certificate, sign the application with that certificate, put it in a location under Program Files, and run it. As explained here
https://msdn.microsoft.com/en-us/library/windows/desktop/dd979761.aspx?f=255&MSPPError=-2147217396
and here
https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/4b6dbc43-a026-4957-9178-91d2001e2d0d/windows-8-block-alttab-simulation#291eb5b4-f6d2-49b6-83db-658bd832f2c9
plus this
https://msdn.microsoft.com/en-us/library/ms742884.aspx?f=255&MSPPError=-2147217396
and this
https://translate.google.com/translate?sl=it&tl=en&js=y&prev=_t&hl=en&ie=UTF-8&u=http%3A%2F%2Fblogs.msdn.com%2Fb%2Fitasupport%2Farchive%2F2009%2F09%2F16%2Fsendsas-step-by-step.aspx&edit-text=&act=url
Arrays are 0-indexed, but you are populating the array using 1-based indexes. So you are not populating the first array element, and are trashing memory after the last array element. Use this instead:
int main(void) {
Sleep(1000 * 3);
INPUT tabinput[2];
tabinput[0].type = INPUT_KEYBOARD;
tabinput[0].ki = {VK_TAB, 0};
tabinput[1].type = INPUT_KEYBOARD;
tabinput[1].ki = {VK_TAB, 0, KEYEVENTF_KEYUP};
SendInput(2, tabinput, sizeof(INPUT));
getchar();
}
Related
I'm making a front end for various emulators and triggering their various functionality such as save/load state, save screenshot, but with a unified interface. FS-UAE annoyingly uses "Print Screen" as its screenshot key, and I'd like to avoid the user having to change emulators from their default hotkey settings.
I've managed to simulate any key press I want with SendInput, except for the "Print Screen" key.
I haven't had any luck with using virtual key codes, I think that doesn't work with full screen applications. Hence that part of the code is commented out. (EDIT: better explanation - Virtual Key codes are ignored by DirectInput software)
Using scan codes, I can get any key to press - almost. Print Screen seems to be the odd one out.
Here's the reference I'm using for the scan codes;
https://msdn.microsoft.com/en-us/library/aa299374(v=vs.60).aspx
Below is the minimum viable code to reproduce the problem. If you run it, press a key then quickly switch to notepad and wait 2 seconds, it should press the letter "q" into notepad, then quit.
Change the scan code from 0x10 (q) to 0x37 (Print Screen), be sure to do it in both places - KEY DOWN, and KEY UP.
Now run it again, press a key and wait. To see if Print Screen worked, open MS Paint or whatever and press CTRL+V, see if you get a screenshot of your desktop. It doesn't work! But if you manually press Print Screen, and CTRL+V into MS Paint, it will work.
Why doesn't the Print Screen key work?
#include "stdafx.h"
//For create process & keyboard codes
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
int main()
{
INPUT ip = {};
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.wVk = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.dwFlags = 0;
printf("Press a key, then taskswitch.\n");
system("pause");
Sleep(2000);
//KEY DOWN
ip.ki.wScan = 0x10; //0x37 PrintScreen, 0x10 Q
ip.ki.dwFlags = KEYEVENTF_SCANCODE;
//ip.ki.wVk = VK_SNAPSHOT;
//ip.ki.dwFlags = 0;
SendInput(1, &ip, sizeof(INPUT));
//KEY UP
ip.ki.wScan = 0x10;
ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
//ip.ki.wVk = VK_SNAPSHOT;
//ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
printf("Done.\n");
system("pause");
return 0;
}
Use wVk instead of wScan, and make sure KEYEVENTF_SCANCODE is not set because that ignores wVk. You have to use VK_SNAPSHOT
INPUT ip[2] = { 0 };
ip[0].type = INPUT_KEYBOARD;
ip[0].ki.wVk = VK_SNAPSHOT;
ip[1] = ip[0];
ip[1].ki.dwFlags |= KEYEVENTF_KEYUP;
SendInput(2, ip, sizeof(INPUT));
Okay I'm answering my own question here;
So I've done some more research, found this amazing post by someone who's nutted out the details of scan codes, and it seems that Print Screen is a weird one, requiring a special sequence to be triggered properly;
https://handmade.network/forums/t/2011-keyboard_inputs_-_scancodes,_raw_input,_text_input,_key_names
(And for additional reading, there is this article on the history of the 3 different scan code sets, which gives some insight as to why some keys might be weird, as new keys were added to the standard) http://www.quadibloc.com/comp/scan.htm
However, I still couldn't get it to work trying the variety of code sequences in that article - in the end, I managed to work around my original problem by learning that FS-UAE supports an ALTERNATE key sequence for saving a screenshot: F12-S, which I am using instead and it's working great.
So I may have avoided the issue this time, but woe be the person who needs to legitimately simulate a Print Screen key press at the scan code level WITHOUT using "Virtual Key codes"... it is a mysterious arcane task that I have still not achieved.
I am trying to make a program that would simulate holding down a keyboard button.
This program is supposed to work in games, where holding down buttons such as W,A,S,D is required. I tested the program both in Grand Theft Auto V and Garry's Mod, but it didn't work in either of them.
I tried using SendInput and keybd_event functions for emulating the input with no luck.
#include <windows.h>
#define VK_W 0x57
using namespace std;
int main(){
while(1){
keybd_event(VK_W, 0, 0, 0);
Sleep(3000); //should hold W for 3 seconds
keybd_event(VK_W, 0, KEYEVENTF_KEYUP, 0);
Sleep(1000);
}
return 0;
}
I've created macros using Razer's keyboard software, which work perfectly, so there must be a way to simulate the key hold input.
I also tried creating an AutoHotkey script, which does work in Garry's Mod, but not in Grand Theft Auto V:
w::
SendInput {w down}
Sleep 3000
SendInput {w up}
This script holds W for 3 seconds when W is pressed.
I tried searching the web, but didn't find any working implementation.
EDIT: I searched around some more and found this: https://stackoverflow.com/a/3647975/1587051
It turns out I was using Unicode instead of keyboard scan codes combined with KEYEVENTF_SCANCODE flag. DirectInput games are now receiving the keystrokes correctly.
For reference sake, as it has already been answered in the comments, you have to use SendInput rather than SendMessage, when filling the INPUT structure required for the SendInput function make sure you combine your Flags with KEYEVENTF_SCANCODE to send hardware signals instead of virtual ones. These will be handled by DirectInput.
Source : Simulating Keyboard with SendInput API in DirectInput applications
I am currently experimenting with xdotool to send keys to a process (I understand that it may not work for all processes that does not set _NET_WM_PID). I have trouble sending keystrokes to windows other from the focus. It does work if you are sending keystrokes to the CURRENTWINDOW. Below is the snippet that I used to test xdotool's functionality.
extern "C"{
#include <xdo.h>
}
//extern "C" xdo_window_search
#include <iostream>
#include <string.h>
using namespace std;
int main(){
xdo_t* p_xdo = xdo_new(NULL);
// Allocate memory for search query.
xdo_search_t s;
// Clear the allocated memory.
memset(&s, 0, sizeof(xdo_search_t));
// Set the search query.
s.pid = 1916;
s.max_depth = -1;
s.searchmask = SEARCH_PID;
s.require = xdo_search::SEARCH_ANY;
// Allocate memory for output
Window* windows;
int no_windows;
xdo_window_search(p_xdo,&s,&windows,&no_windows);
cout << no_windows << endl;
// Prints all windows' names with matching criteria
for( int i=0;i<no_windows;i++ ){
unsigned char * name;
int size;
int type;
xdo_get_window_name(p_xdo,windows[i],&name,&size,&type);
cout << i << ":" << name << endl;
}
for( int i=0;i<no_windows;i++ ){
xdo_type(p_xdo,windows[i],"Hello World",0);
}
//xdo_type(p_xdo,CURRENTWINDOW,"Hello World",0); // This does work.
return 0;
}
In additional to testing xdotool's functionality, I've looked into xdotool's source code. Interestingly, I found that they are using Xtest to send keystrokes to the focused window (CURRENTWINDOW) and X11's XSendEvent for other windows. I turned to xdotool because I couldn't get XSendEvent to work and Xtest cannot send keys to any other windows than the focused window.
Am I not using the xdotool correctly? Does xdotool not work with all *nix OS with X11?
[I am running this on Ubuntu 13.04.]
EDIT
So, it looks like that does work but not for all windows that it finds. For example, it works for firefox but not gedit and gnome-terminal although it found gedit and gnome-terminal by its pid. It behaves differently if I used CURRENTWINDOW.
So, it would be great if someone can explain why is this so. Like, is it related the force send flag in an XEvent?
Directly from the xdotool manual:
SENDEVENT NOTES
If you are trying to send key input to a specific window, and it does
not appear to be working, then it's likely your application is ignoring
the events xdotool is generating. This is fairly common.
Sending keystrokes to a specific window uses a different API than
simply typing to the active window. If you specify 'xdotool type
--window 12345 hello' xdotool will generate key events and send them
directly to window 12345. However, X11 servers will set a special flag
on all events generated in this way (see XEvent.xany.send_event in
X11's manual). Many programs observe this flag and reject these events.
It is important to note that for key and mouse events, we only use
XSendEvent when a specific window is targeted. Otherwise, we use XTEST.
Some programs can be configured to accept events even if they are
generated by xdotool. Seek the documentation of your application for
help.
Specific application notes (from the author's testing): * Firefox 3
seems to ignore all input when it does not have focus. * xterm can be
configured while running with ctrl+leftclick, 'Allow SendEvents' *
gnome-terminal appears to accept generated input by default.
I have this bit of code which uses SendInput to send a key press but it doesn't work for when I want to long hold a key (eg long hold 'a' would return 'aaaaaaaaa' in notepad).
Now I have looked all over google and the only way I can see to get around this is to keep sending the input if I want a long hold. I don't want to do that as this will just simulate 'a' being pressed over and over again.
keyboard.wVk = 0;
keyboard.wScan = MapVirtualKey(key, 0);
keyboard.dwFlags = KEYEVENTF_SCANCODE;
if (index_vector_no)
pressed[index_vector_no] = true;
keyboard.dwExtraInfo = 0;
input.type = INPUT_KEYBOARD;
input.ki = keyboard;
SendInput(1, &input, sizeof (input));
So I would like some answers to the following questions:
A) Am I right in thinking there is no way around this using SendInput and why doesn't it work for long hold?
B) What is an alternative method for successfully being able to send key down and key up signals. Preferably sending the keys to windows and not just to a particular application.
C) Is there a good lightweight C++ library I can use that handles global keyboard and mouse simulation?
Thanks in advance! =)
EDIT: Take a look at this post for more details of my problem: http://www.experts-exchange.com/Programming/Languages/Visual_Basic/Q_20833788.html
Repeating keystrokes is a feature of the keyboard controller, not of Windows or SendInput. You can certainly emulate it with a timer, repeatedly calling SendInput().
I'm writing a little tool in VC++ to record key strokes to replay them later, a macro recorder. It works quite nice already, using a keyboard hook function that reads each and every key press and release event. The playback works with the SendInput() function and generally also works fine - except for repeating key strokes. Pressing a key several times after releasing it every time is no problem. But pressing it and holding it down, for the input character to be repeated, can be recorded but can only be replayed in some applications. Some accept and enter the character multiple times, some do it only once. (It is reproducible which does which.) The macro recorder itself also sees the held down key pressed just a single time during playback, through its monitoring hook.
So, how can I make SendInput send multiple subsequent key strokes of a single key without adding key release events on my own in between? Sending a sequence of [press] [press] [press] ... [release] doesn't always work.
You could send Multiple keys in one SendInput calls, but you will still need to set keyup flags on every char to get same results on every type of keystrokes.
if you need to send "aa", you can do like this.
INPUT input[4];
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = 0;
input[0].ki.wScan = 'a';
input[0].ki.dwFlags = 0;
input[1].type = INPUT_KEYBOARD;
input[1].ki.wVk = 0;
input[1].ki.wScan = 'a';
input[1].ki.dwFlags = KEYEVENTF_KEYUP;
input[2].type = INPUT_KEYBOARD;
input[2].ki.wVk = 0;
input[2].ki.wScan = 'a';
input[2].ki.dwFlags = 0;
input[3].type = INPUT_KEYBOARD;
input[3].ki.wVk = 0;
input[3].ki.wScan = 'a';
input[3].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(4, input, sizeof(INPUT));
I'm not sure about your exact sequence of keystrokes, but I had a similar issue recently. I wrote a tiny Win32 tool [1] to send keys when a global shortcut key is pressed. When characters were repeated, e.g., "aaabc", the repeated characters were lost. I tried many combinations of KeyDown and KeyUp, but repeated characters were always lost.
Then I found this blog post: https://batchloaf.wordpress.com/2014/10/02/using-sendinput-to-type-unicode-characters/
While the author does not specifically discuss repeating characters, it inspired me to try SendInput() with only a single INPUT structure. This technique works very well for me.
In short:
Call SendInput() with only a single INPUT structure.
To simulate a single typed (regular) key, e.g., z, try this:
Send single KeyDown event: ki.dwFlags = KEYEVENTF_UNICODE
Send single KeyUp event: ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP
[1] https://github.com/kevinarpe/win32/tree/master/send_input
Many people experience issues with the keyup and keydown calls being "dismissed" or "dropped", and alot of people have resolved their problems by placing a small buffer amount of time between the two, to assure that all commands are transfered:
sendinput alt keydown
sendinput 3 keydown
sleep 50
sendinput 3 keyup
sendinput alt keyup
There's also a SendInput.SendWait command....
Cheers
As far as I know, the way it works is if a key down event is received with no key up event for a certain period of time (the repeat delay), the key is considered "repeating" until a key up occurs.
Since sending press, press, press, release doesn't work always, have you tried recording the time between the key down and key up, then repeating the commands in that same time? It becomes real time, but it should trigger the same repeat actions that way.
I can't think of any other way to end up with the same amount of "key repeats" as the original since those aren't recorded as individual key presses.