So I have a working keypress simulator. It presses the key "W" every 2 seconds. I'm testing it out on a game that uses the keys 'WASD' however, when I run the program and run up my game, it doesn't move my character? I have to physically push the W key to move it. Any ideas why?
Here's my code:
#include <iostream>
#define WINVER 0x0500
#include <windows.h>
class KeyBot {
private:
INPUT _buffer[1];
public:
KeyBot();
void KeyUp(char key);
void KeyDown(char key);
void KeyClick(char key);
};
KeyBot::KeyBot() {
_buffer->type = INPUT_KEYBOARD;
_buffer->ki.wScan = 0;
_buffer->ki.time = 0;
_buffer->ki.dwExtraInfo = 0;
}
void KeyBot::KeyUp(char key) {
_buffer->ki.wVk = key;
_buffer->ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, _buffer, sizeof(INPUT));
}
void KeyBot::KeyDown(char key) {
_buffer->ki.wVk = key;
_buffer->ki.dwFlags = 0;
SendInput(1, _buffer, sizeof(INPUT));
}
void KeyBot::KeyClick(char key) {
KeyDown(key);
Sleep(10);
KeyUp(key);
}
int main() {
KeyBot bot;
while (1) {
bot.KeyDown(0x57); //Press and hold 'W'
Sleep(2000); // Wait 2000 ms (2 seconds)
bot.KeyUp(0x37);
}
}
This thread describes a similar problem - DirectX input handling seem to ignore normal scancodes; try using their DIK_ variant, from the dinput.h DirectX header.
Related
I am making an autoclicker. The "ClickLoop" function I found on another SO post works, but I am trying to add a key to toggle the autoclicker on and off.
This is my code so far:
#include <windows.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <random>
bool on = false;
void tick () {
if(GetKeyState('x') & 0x8000) {
on = !on;
}
tick();
};
void WINAPI ClickLoop(int delay) {
std::cout << "test" << std::endl;
while ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0) {
Sleep(1);
}
int nCurrKeyState = GetKeyState(VK_LBUTTON);
int nPrevKeyState;
do {
if (on) {
INPUT Input;
ZeroMemory(&Input, sizeof(INPUT));
Input.type = INPUT_MOUSE;
Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &Input, sizeof(INPUT));
Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(1, &Input, sizeof(INPUT));
// Delay in MS
Sleep(delay);
nPrevKeyState = nCurrKeyState;
nCurrKeyState = GetKeyState(VK_LBUTTON);
if ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0)
break;
} else {
break;
}
} while (nCurrKeyState != nPrevKeyState);
ClickLoop(delay);
}
int main() {
int delay;
std::cout << "Delay in milliseconds: ";
std::cin >> delay;
tick();
ClickLoop(delay);
return 0;
}
I then use G++ to compile the code:
g++ main.cpp -o main
After running the "main" executable, I find that it starts up, asks me for the delay and then stops after a couple of seconds.
Why does this happen?
void tick () {
...
tick();
}
This is an endless recursion loop. Once main() calls tick(), the program is stuck in this loop and never reaches ClickLoop().
void WINAPI ClickLoop(int delay) {
...
ClickLoop(delay);
}
This is also an endless recursion loop.
You need to get rid of these recursive loops.
Another problem I see is that you are using GetKeyState() in places, but GetKeyState() depends on the calling thread having a message loop to process WM_(L|M|R)BUTTON(DOWN|UP) window messages to update the thread's internal keyboard state. But there is no window or message loop in this code.
GetAsyncKeyState() does not depend on a window or a message loop.
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 wanted to make a strafe bot for garry's mod, and I came up with this:
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include "stdafx.h"
class KeyBot
{
private:
INPUT _buffer[1];
public:
KeyBot();
void KeyUp(char key);
void KeyDown(char key);
void KeyClick(char key);
};
KeyBot::KeyBot()
{
_buffer->type = INPUT_KEYBOARD;
_buffer->ki.wScan = 0;
_buffer->ki.time = 0;
_buffer->ki.dwExtraInfo = 0;
}
void KeyBot::KeyUp(char key)
{
_buffer->ki.wVk = key;
_buffer->ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, _buffer, sizeof(INPUT));
}
void KeyBot::KeyDown(char key)
{
_buffer->ki.wVk = key;
_buffer->ki.dwFlags = 0;
SendInput(1, _buffer, sizeof(INPUT));
}
void KeyBot::KeyClick(char key)
{
KeyDown(key);
Sleep(10);
KeyUp(key);
}
char check_mouse(POINT xOne, POINT xTwo)
{
GetCursorPos(&xOne);
Sleep(1);
GetCursorPos(&xTwo);
if ((xTwo.x - xOne.x) > 0) {
return 'D';
}
else {
if ((xTwo.x - xOne.x) < 0) {
return 'A';
}
else {
if ((xTwo.x - xOne.x) == 0) {
return 'N';
}
}
}
}
int main()
{
KeyBot bot;
POINT xOne;
POINT xTwo;
while (1) {
if (check_mouse(xOne, xTwo) == 'A') {
bot.KeyUp(0x44);
bot.KeyDown(0x41);
}
if (check_mouse(xOne, xTwo) == 'D') {
bot.KeyUp(0x41);
bot.KeyDown(0x44);
}
if (check_mouse(xOne, xTwo) == 'N') {
bot.KeyUp(0x44);
bot.KeyUp(0x41);
}
}
return 0;
}
This works fine, when opening notepad or game chat, it holds a when I move my mouse left, and it holds d when I move my mouse to the right. The problem is, that, when I am in game, it doesn't move my character at all. I think the problem is that this is a virtual key press and not a hardware one, and I don't know how to change this.
can someone modify my code in order for this to work?
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");
}
}
I want to make a program that can catch keyboard events even if it's not active on any moment. Hooks were too complicated with all the things I have to do to make it to work (making a DLL, reading it, etcetera) so I decided to go on using hotkeys.
But now I have a problem. Registering the hotkey disables the key on the keyboard, thus I can only send the key to the program, while I can't type on any other program (e.g. Notepad).
This is my code:
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, char* argv[]) {
RegisterHotKey(NULL, 1, NULL, 0x41); //Register A
MSG msg = {0};
while (GetMessageA(&msg, NULL, 0, 0) != 0) {
if (msg.message == WM_HOTKEY) {
cout << "A"; //Print A if I pressed it
}
}
UnregisterHotKey(NULL, 1);
return 0;
}
// and now I can't type A's
Is there any simple solution to this problem?
Thank you
I would let your program simulate a keypress which equals the one you actually performed. That means:
You press 'A'.
The program catches the 'A'.
The program simulates the keypress.
It's quite simple. The only problem would be that your program would also catch the simulated keypress. To avoid it, you can do the following:
You press 'A'.
The program catches the 'A'.
The program unregisters the hotkey.
The program simulates the keypress.
(The program does not (!) catch the 'A'.)
The program registers the hotkey again.
That's the whole loop.
Now, to simulate the keypress, you need to add some additional code. Have a look at this:
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, char* argv[]) {
RegisterHotKey(NULL, 1, 0, 0x41); //Register A; Third argument should also be "0" instead of "NULL", so it is not seen as pointer argument
MSG msg = {0};
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wVk = 0x41; //The key to be pressed is A.
while (GetMessage(&msg, NULL, 0, 0) != 0) {
if (msg.message == WM_HOTKEY) {
UnregisterHotKey(NULL, 1); //Prevents the loop from caring about the following
ip.ki.dwFlags = 0; //Prepares key down
SendInput(1, &ip, sizeof(INPUT)); //Key down
ip.ki.dwFlags = KEYEVENTF_KEYUP; //Prepares key up
SendInput(1, &ip, sizeof(INPUT)); //Key up
cout << "A"; //Print A if I pressed it
RegisterHotKey(NULL, 1, 0, 0x41); //you know...
}
}
UnregisterHotKey(NULL, 1);
return 0;
}
I tried it and it works fine, I guess.
Hope I could help ;)