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;
}
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.
Basically, the code below detects "U" is clicked, and if it's clicked then it checks for the left mouse button being clicked. It works up until that point, say you open it, gives it a click per second value, click 'u', and left-click. After you hold the left click it sends left clicks at the desired speed, but it doesn't stop until you click escape. I need it to stop once you let go of the left click button. I've tried a few different things all of which ending up with it either only sending 2 clicks or just not working. TLDR - need it to detect on key, then if the left click button is held down, sends the clicks at the desired cps, and when you let go of left click it stops clicking. I know it worded terribly, English isn't my first language. bool bClick = false;
while (true)
{
//toggles it on and off
if (GetAsyncKeyState('U') & 1)
bClick = !bClick;
if (bClick)
{
while (GetAsyncKeyState(VK_LBUTTON) < 0)
{
while (1)
{
INPUT input[2] = {};
input[0].type = INPUT_MOUSE;
input[0].mi.dx = x;
input[0].mi.dy = y;
input[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
input[1] = input[0];
input[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(2, input, sizeof(INPUT));
std::cout << "Clicked ";
std::cout << clicks++;
std::cout << " times \n";
Sleep(1000 / cps);
if (GetAsyncKeyState(VK_ESCAPE))
{
break;
}
}
}
}
}
your program will continuously send click messages when running on my computer, and it will not stop by pressing the'U' or Esc key.
(I’m not sure if your problem is that the special button cannot be detected or the click is not issued)
Get rid of the inner-most while loop. It is an infinite loop that is broken only by pressing ESC. The middle while loop is all you need, it stops when the left mouse button is released.
while (true)
{
//toggles it on and off
if (GetAsyncKeyState('U') & 1)
bClick = !bClick;
if (bClick)
{
while (GetAsyncKeyState(VK_LBUTTON) < 0)
{
INPUT input[2] = {};
input[0].type = INPUT_MOUSE;
input[0].mi.dx = x;
input[0].mi.dy = y;
input[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
input[1] = input[0];
input[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(2, input, sizeof(INPUT));
std::cout << "Clicked ";
std::cout << clicks++;
std::cout << " times \n";
Sleep(1000 / cps);
if (GetAsyncKeyState(VK_ESCAPE))
{
break;
}
}
}
}
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.
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 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 ;)