As written before, I would like to know how parallel keyboard input works.
This is my code so far:
cout << "Enter time for Key A: ";
cin >> timeA;
cout << "Enter time for Key B: ";
cin >> timeB;
while (1)
{
Sleep(timeA);
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.time = 0;
ip.ki.dwFlags = KEYEVENTF_UNICODE; // Specify the key as a unicode character
ip.ki.wScan = 'A'; // Which keypress to simulate
ip.ki.wVk = 0;
ip.ki.dwExtraInfo = 0;
SendInput(1, &ip, sizeof(INPUT));
Sleep(timeB);
ip.type = INPUT_KEYBOARD;
ip.ki.time = 0;
ip.ki.dwFlags = KEYEVENTF_UNICODE; // Specify the key as a unicode character
ip.ki.wScan = 'B'; // Which keypress to simulate
ip.ki.wVk = 0;
ip.ki.dwExtraInfo = 0;
SendInput(1, &ip, sizeof(INPUT));
}
It works, but I would like to reach, that e.g. the Letter A is being pressed every 500ms and the Letter B is pressed every 1s. How would I do that?
This is a timer class. You can create an object and call it like:
timer timer_1(time_in_milliseconds, true_if_async, &function_name, argument_1, arg_2, ...);
This way you can run your functions after a certain amount of time has passed, you can run multiple functions together with async as well or just use sync and queue them. Your choice.
Threads is the best solution for your problem.
class timer
{
public:
template <class Callable, class... Arguments>
timer(int after, const bool async, Callable&& f, Arguments&&... args)
{
std::function<typename std::result_of<Callable(Arguments...)>::type()> task(bind(forward<Callable>(f), forward<Arguments>(args)...));
if (async)
{
thread([after, task]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(after));
task();
}).detach();
}
else
{
std::this_thread::sleep_for(std::chrono::milliseconds(after));
task();
}
}
};
Here's a small example usage:
void say(const string& word)
{
cout << "Hello, " << word << "!\n";
}
int main(int argc, char* argv[])
{
while (true)
{
timer timer1(500, false, &say, "pyreN - A");
timer timer2(1000, false, &say, "pyreN - B");
}
}
Related
so I am trying to make an auto clicker that runs run you hold down the mouse button My current loop looks like However when I run this it just clicks for ever and ever and does not stop when I release the mouse button. Thanks in advance. ps pressed is defaulted as false.
while(GetAsyncKeyState(VK_LBUTTON)&&!pressed)
{
pressed = true;
INPUT Input = { 0 };
// left down
Input.type = INPUT_MOUSE;
Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
::SendInput(1, &Input, sizeof(INPUT
// left up
::ZeroMemory(&Input, sizeof(INPUT));
Input.type = INPUT_MOUSE;
Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
::SendInput(1, &Input, sizeof(INPUT
cout << "pressed"
sleep_for(milliseconds(100));
pressed = false;
}
First of all, the return value of GetAsyncKeyState has two bits, we only need its highest bit, so we use GetAsyncKeyState(VK_LBUTTON)&0x8000.
Secondly, the signal sent at the end of the loop simulates the operation of the mouse release, so the return value of GetAsyncKeyState() is 0, and you cannot continue to enter the loop to simulate the click operation of the mouse. Therefore, we should first simulate the mouse release operation, and then simulate the mouse click operation, so that the function can be realized normally.
Finally, SendInput() supports multiple operations at a time, we can build an array of INPUT, and then send the required signals at once, so that you can more easily achieve your needs.
Here is the code you can refer:
#include <windows.h>
#include <iostream>
using namespace std;
#define INPUT_COUNT 2
int main(int argc, char* argv[])
{
int pressed = false;
while (true)
{
while (GetAsyncKeyState(VK_LBUTTON) & 0x8000)
{
pressed = true;
INPUT Input[INPUT_COUNT] = { 0,0 };
Input[0].type = INPUT_MOUSE;
Input[0].mi.dwFlags = MOUSEEVENTF_LEFTUP;
Input[1].type = INPUT_MOUSE;
Input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
::SendInput(INPUT_COUNT, Input, sizeof(INPUT));
cout << "pressed" << endl;
pressed = false;
Sleep(100);
}
}
return 0;
}
I am trying to make a program that when you type "Alt+A" it will write type out a line like "Hello" for example. This is the closest I've gotten:
if (GetAsyncKeyState(65))
{
cout << "worked" << std::endl;
string bind = "Hello";
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
for (int i = 0; i < bind.length(); i++)
{
Input.ki.wVk = VkKeyScanA(bind[i]);
SendInput(1, &Input, sizeof(Input));
}
Sleep(500);
}
It works similar to how I want, but there are some problems that I encountered:
I can't get the Alt key to work. When I use GetAsyncKeyState(18), it runs the "worked" output but it doesn't type out any of the word.
Whenever I press the key bind (for example "A"), it will type that letter as well. Is there any way I can cancel out that key press? I was thinking that I could just make it so that it types the backspace button before the word, but I'm assuming there is a better to go about this.
I also have a problem that the program doesn't type exactly what is put in. It doesn't type capital letters, and it only types one letter if there are two in a row. In the code that I put, it will say "helo" instead of "Hello."
I have made some simple changes to your code, which can basically meet your needs.
But if you need higher functionality, you may need to use RegisterHotKey, and create your window to handle the WM_HOTKEY message.
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
HWND hwnd = (HWND)0x001E0BF2; //notepad window
SetForegroundWindow(hwnd);
while (1)
{
if (GetAsyncKeyState(18)&0x8000)
{
if (GetAsyncKeyState(65)&0x8000)
{
INPUT keyup_ALT = { 0 };
keyup_ALT.type = INPUT_KEYBOARD;
keyup_ALT.ki.wVk = 18;
keyup_ALT.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &keyup_ALT, sizeof(INPUT));
cout << "worked" << std::endl;
string bind = "Hello";
INPUT Input[2] = { 0 };
Input[0].type = Input[1].type = INPUT_KEYBOARD;
Input[1].ki.dwFlags = KEYEVENTF_KEYUP;
for (int i = 0; i < bind.length(); i++)
{
short ch = VkKeyScanA(bind[i]);
Input[0].ki.wVk = Input[1].ki.wVk = ch;
if (((ch & 0xff00) >> 8) & 0x1)
{
INPUT shift = { 0 };
shift.type = INPUT_KEYBOARD;
shift.ki.wVk = VK_SHIFT;
SendInput(1, &shift, sizeof(INPUT));
}
SendInput(2, Input, sizeof(INPUT));
if (((ch & 0xff00) >> 8) & 0x1)
{
INPUT shift = { 0 };
shift.type = INPUT_KEYBOARD;
shift.ki.wVk = VK_SHIFT;
shift.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &shift, sizeof(INPUT));
}
}
Sleep(500);
}
}
}
}
CHANGES:
Add status check of ALT key;
Make the return value of the GetAsyncKeyState and (&) 0x8000;
Make the ALT key up, to resolve "it runs the "worked" output but it
doesn't type out any of the word."
Check the return value of VkKeyScanA, the high-order byte contains
the shift state, which control the capital letters, then determine whether to send shift key.
I want to use the SendInput() function to automate pressing some keys.
My code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <Windows.h>
using std::cin;
using std::cout;
using std::string;
void presskeys(string s){
INPUT ip;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
HKL kbl = GetKeyboardLayout(0);
for (unsigned int i = 0; i < s.length(); ++i) {
ip.type = INPUT_KEYBOARD;
char c = s[i];
int vk = VkKeyScanEx((WCHAR)c, kbl);
ip.ki.wVk = vk;
SendInput(1, &ip, sizeof(ip));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(ip));
}
}
int main()
{
cout << "Enter a string!\n";
string str;
cin >> str;
Sleep(5000);
presskeys(str);
cout << "Done!\n";
return 0;
}
I boot up the program and enter a string, only for nothing to happen. Where did it go wrong?
Like Barmak said, you are mixing ANSI and UNICODE together in an improper manner, and you are not managing the input flags correctly.
When sending string characters, it is better to send UTF-16 codeunits via the KEYEVENTF_UNICODE flag instead of using scan codes or virtual keys.
You should also call SendInput() one time with multiple INPUT structs for the entire string, so that all of the characters get sent together as a single unit and cannot be interrupted by, or intermixed with, other input events that are generated by the user or other apps/threads at the same time.
See my answer to Sending Two or more chars using SendInput.
For example:
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
void presskeys(const std::wstring &str)
{
int len = str.length();
if (len == 0) return;
std::vector<INPUT> in(len*2);
ZeroMemory(&in[0], in.size()*sizeof(INPUT));
int i = 0, idx = 0;
while (i < len)
{
WORD ch = (WORD) str[i++];
if ((ch < 0xD800) || (ch > 0xDFFF))
{
in[idx].type = INPUT_KEYBOARD;
in[idx].ki.wScan = ch;
in[idx].ki.dwFlags = KEYEVENTF_UNICODE;
++idx;
in[idx] = in[idx-1];
in[idx].ki.dwFlags |= KEYEVENTF_KEYUP;
++idx;
}
else
{
in[idx].type = INPUT_KEYBOARD;
in[idx].ki.wScan = ch;
in[idx].ki.dwFlags = KEYEVENTF_UNICODE;
++idx;
in[idx].type = INPUT_KEYBOARD;
in[idx].ki.wScan = (WORD) str[i++];
in[idx].ki.dwFlags = KEYEVENTF_UNICODE;
++idx;
in[idx] = in[idx-2];
in[idx].ki.dwFlags |= KEYEVENTF_KEYUP;
++idx;
in[idx] = in[idx-2];
in[idx].ki.dwFlags |= KEYEVENTF_KEYUP;
++idx;
}
}
SendInput(in.size(), &in[0], sizeof(INPUT));
}
int main()
{
std::wcout << L"Enter a string and press enter:\n";
std::wstring str;
if (std::getline(std::wcin, str))
{
presskeys(str);
std::wcout << L"Done!\n";
}
return 0;
}
You are working with ANSI string so use VkKeyScanExA, or switch to std::wstring. But don't mix ANSI with UNICODE, and don't use casting to hide the compiler warnings.
You have to reset ip.ki.dwFlags to zero to indicate key down. Then set it to KEYEVENTF_KEYUP.
You also have to check the key state for caplock and shift, etc. Using SendInput in that way is pointless, the first parameter is there to allow sending multiple inputs at once. You might as well use keybd_event
void presskeys(string s)
{
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
HKL kbl = GetKeyboardLayout(0);
for (unsigned int i = 0; i < s.length(); ++i)
{
char c = s[i];
ip.ki.wVk = VkKeyScanExA(c, kbl); //<== don't mix ANSI with UNICODE
ip.ki.dwFlags = 0; //<= Add this to indicate key-down
SendInput(1, &ip, sizeof(ip));
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(ip));
}
}
The following program didn't do anything, athough had been expected to simulate pressing "a" and "b" for each second. Why it doesn't work?
#include <Windows.h>
#include <iostream>
using namespace std;
const int INPUTS = 4;
int main()
{
INPUT inputArray[INPUTS];
INPUT input;
input.type = INPUT_KEYBOARD;
//Press 'a' key
input.ki.wVk = 0x41;
input.ki.wScan = MapVirtualKey(0x41,MAPVK_VK_TO_VSC);
inputArray[0] = input;
//Release 'a' key
input.ki.dwFlags = KEYEVENTF_KEYUP;
inputArray[1] = input;
//Press 'b' key
input.ki.dwFlags = 0;
input.ki.wVk = 0x42;
input.ki.wScan = MapVirtualKey(0x42,MAPVK_VK_TO_VSC);
inputArray[2] = input;
//Release 'b' key
input.ki.dwFlags = KEYEVENTF_KEYUP;
inputArray[3] = input;
Sleep(5000);
std::cout<<"GO!!!\n";
for(int i=0; i<100; i++)
{
SendInput(sizeof(inputArray),inputArray,sizeof(INPUT));
Sleep(1000); //Don't remove!
}
std::cout<<GetLastError()<<std::endl;
system("Pause");
return 0;
}
The last error is
ERROR_NOACCESS
998 (0x3E6)
Invalid access to memory location.
but I don't know what caused it.
Try
SendInput(INPUTS, inputArray, sizeof(INPUT));
and check that the return value is non-zero. In fact, it should equal to the number of inputs sent, in this case 4.
The function may fail if it is blocked by another thread or UIPI (User Interface Privilege Isolation)
To avoid other problems you may want to check the current keyboard state as well as SendInput adds to the input stream and other keys being pressed while this is running could interfere with it.
Out of curiosity what action are you trying to simulate? It's generally not a very graceful practice to "fake" user input to any application.
I am trying to get my application to convert a character array to uppercase letter so I can pass them as key presses. I know I am close to getting this code working but I just cant see the problem.
int a, b, c, d;
char text[25];
char upper[25];
for (a = 0, b = sizeof(login); a < b; a++)
{
if (isalpha(login[a])){
l[a] = toupper(login[a]);
Sleep(1000);
GenerateKey(l[a], FALSE);}
else{
GenerateKey(l[a], FALSE);
Sleep(1000);
l[a] = login[a];}
}
login[a]='\0';
GenerateKey(0x09, FALSE);
for (c = 0, d = sizeof(pass); c < d; c++)
{
if (isalpha(pass[c])){
p[c] = toupper(pass[c]);
GenerateKey(p[c], FALSE);
Sleep(1000);}
else{
GenerateKey(p[c], FALSE);
p[c] = pass[c];
Sleep(1000);}
}
pass[a]='\0';
GenerateKey(0x09, FALSE);
Sleep(1000);
GenerateKey(0x09, FALSE);
Sleep(1000);
GenerateKey(0x0D, FALSE);
And here is the GenerateKey function:
void GenerateKey(int vk, BOOL bExtended) {
KEYBDINPUT kb = {0};
INPUT Input = {0};
/* Generate a "key down" */
if (bExtended) { kb.dwFlags = KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
/* Generate a "key up" */
ZeroMemory(&kb, sizeof(KEYBDINPUT));
ZeroMemory(&Input, sizeof(INPUT));
kb.dwFlags = KEYEVENTF_KEYUP;
if (bExtended) { kb.dwFlags |= KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
return;
}
Any help would be great!
EDIT:
This appplication is trying to open a webpage and then enter login information and press submit(using tab to select the username, password fields, etc). To answer #Rup, l[] and p[] are initialised above this block of code.
char l[180];
char p[180];
l is the users login name and p is their password. I am trying to convert these to uppercase to pass them in GenerateKey. eg GenerateKey('A', FALSE);
At the moment the code does not seem to pass any keypresses at all but the application freezes so I believe it is getting stuck in a for loop somewhere.
EDIT 2:
Thanks to #William for providing the helpful code.
Using the toUpper function I am very close to solving this issue. The only issue I am having now is that the login and password being passed contain extra characters. For example if I pass login as username, then rerun the program and pass login as user I get the output userame.
This is the code I have now with the GenerateKey and toUpper functions:
// Convert to uppercase to be passed as keypresses
toUpper(login, sizeof(login));
toUpper(pass, sizeof(pass));
int a;
for(a=0; a<sizeof(login);a++){
GenerateKey(login[a], FALSE);}
login[a]='\0';
GenerateKey(0x09, FALSE);
a=0;
for(a=0; a<sizeof(pass);a++){
GenerateKey(pass[a], FALSE);}
pass[a]='\0';
GenerateKey(0x09, FALSE);
Sleep(1000);
GenerateKey(0x09, FALSE);
Sleep(1000);
GenerateKey(0x0D, FALSE);
SOLUTION:
Using strlen(login); in the above code cleared up all hte issues I was having.
void toUpper(char* pArray, int arrayLength)
{
for(int i = 0; i < arrayLength; i++)
{
if(pArray[i] >= 'a' && pArray[i] <= 'z')
pArray[i] -= ' ';
}
}
I have solved the Issue with the following code:
The code is explained in the comments.
// Convert to uppercase to be passed as keypresses
toUpper(login, sizeof(login));
toUpper(pass, sizeof(pass));
int a;
// Loop through the character array and send the key presses
for(a=0; a<strlen(login);a++){
GenerateKey(login[a], FALSE);}
GenerateKey(0x09, FALSE);
for(a=0; a<strlen(pass);a++){
GenerateKey(pass[a], FALSE);}
// Additional keypresses
GenerateKey(0x09, FALSE);
Sleep(1000);
GenerateKey(0x09, FALSE);
Sleep(1000);
GenerateKey(0x0D, FALSE);
The GenerateKey function and toUpper functions provided are also needed in order for this code to function correctly.
Thank you for all your help on this Issue.