Using SendInput or mouse_event doesn't work with clock()? - c++

void leftClick(){
INPUT input[2];
input[0].type = INPUT_MOUSE;
input[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
input[1].type = INPUT_MOUSE;
input[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(2, input, sizeof(INPUT));
cout<<"click down\n";
cout<<"click up\n\n";
/*
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
*/
}
ReadProcessMemory(process, (void*)address, &value, sizeof(value), 0);
if (value == 1){
if (clock() - click_time >= 500){
cout<<"click time = "<< click_time <<endl;
cout<<clock() - click_time <<endl;
leftClick();
click_time = clock();
}
}
This gives an output of
click time = 0
57209
click down
click up
click time = 57222
501
click down
click up
click time = 57738
500
click down
click up
As you can see, the clicks should be happening, but this doesn't send any clicks. It only actually clicks if I take out all the clock stuff. Same thing happens if I use mouse_event instead of SendInput.
edit: I changed SendInput up there, didn't change any behavior. The commented mouse_events gives the same behavior as well
edit: It seems I can't make a minimal reproducible example. Without ReadProcessMemory, it works fine with a delay, it only doesn't send clicks with a delay while reading the process. Looking in to issues with combining ReadProcessMemory with any sort of delayed input.

The target process/window can detect SendInput and block it using the LLMHF_INJECTED flag.
If it's not blocking the input, you should SendInput() once with MOUSEEVENTF_LEFTDOWN, then after a delay, you should call it again with MOUSEEVENTF_LEFTUP. You don't know how the target process is processing input, adding a delay has been helpful for me in several situations.
Here's an example usint std::chrono for 1 delay timer, I used a sleep between DOWN & UP, in an effort to not over complicate the solution more than it needs to be for a simple example.
#include <chrono>
#include <thread>
int main()
{
INPUT input{ 0 };
input.type = INPUT_MOUSE;
bool bClick = false;
using Clock = std::chrono::steady_clock;
std::chrono::time_point<std::chrono::steady_clock> start, now;
std::chrono::milliseconds duration;
start = Clock::now();
while (true)
{
//toggles it on and off with one key
if (GetAsyncKeyState('U') & 1)
bClick = !bClick;
if (bClick)
{
now = Clock::now();
duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
if (duration.count() >= 100)
{
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(1, &input, sizeof(INPUT));
std::this_thread::sleep_for(std::chrono::milliseconds(30));
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &input, sizeof(INPUT));
start = std::chrono::steady_clock::now();
}
}
}
return 0;
}
You can toggle it on and off with the U key.

Related

Failing to simulate mouse click via Windows API

I was dabbling with positioning of the mouse pointer which I had no trouble at all with, but trying to simulate a left click is giving me problems at the moment.
#include <Windows.h>
int main()
{
SetCursorPos(100, 450);
Sleep(3000);
SetCursorPos(1600, 450);
int n = 1;
while (n <= 10);
{
SetCursorPos(1600, 450);
LeftClick();
n++;
}
}
My LeftClick() function is as follows:
void LeftClick()
//down
INPUT Input = {0};
Input.type = INPUT_MOUSE;
Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
::SendInput(1, &Input, sizeof(INPUT));
//up
::ZeroMemory(&Input, sizeof(INPUT));
Input.type = INPUT_MOUSE;
Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
::SendInput(1, &Input, sizeof(INPUT));
I've looked around and so far everything I've seen hasn't worked for me.
Please give me any help with anything to do with my sloppy code, not just how I am trying to simulate clicking,

Loop repeated do statement with mouse left button variable click & hold

Hey, currently testing a autoclicker for a few games, I am quite new to C++
How can I use left mouse button to run a do statement for the mouse click function without it stopping the do statement
I've tried different flags including :
input.mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP);
with mouse_event(MOUSEEVENTF)
do {
if (GetAsyncKeyState(VK_LBUTTON) & 0x80000000) {
enabled = true;
while (GetAsyncKeyState(VK_LBUTTON) & 0x80000000) {
Sleep(1000 / cps);
INPUT input;
input.type = INPUT_MOUSE;
input.mi.dx = 0;
input.mi.dy = 0;
input.mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP);
input.mi.mouseData = 0;
input.mi.dwExtraInfo = NULL;
input.mi.time = 0;
SendInput(1, &input, sizeof(INPUT));
}
}
} while (true);
I am trying to make it so when you hold down left click, it runs the while statement containing the autoclicking function, without stopping the while statement due to repetitive clicking.
There is something you should notice in your code:
First, How to judge the return value of GetAsyncKeyState()
If the function succeeds, the return value specifies whether the key
was pressed since the last call to GetAsyncKeyState, and whether the
key is currently up or down. If the most significant bit is set, the
key is down, and if the least significant bit is set, the key was
pressed after the previous call to GetAsyncKeyState. However, you
should not rely on this last behavior; for more information, see the
Remarks.
the type of return value is SHORT which is 2 bytes. So try GetAsyncKeyState(VK_LBUTTON) & 0x8000 instead.
Second, How to use SendInput() to send different mouse state.
You should create a new INPUT data to save different action, but not just combine all of them.
Code Sample:
do {
if (GetAsyncKeyState(VK_LBUTTON) & 0x8000)
{
enabled = true;
while (GetAsyncKeyState(VK_LBUTTON) & 0x8000)
{
INPUT input[2];
input[0].type = input[1].type = INPUT_MOUSE;
input[0].mi.dx = 0;
input[0].mi.dy = 0;
input[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN;
input[1].mi.dx = 0;
input[1].mi.dy = 0;
input[1].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP;
SendInput(2, input, sizeof(INPUT) * 2);
}
}
} while (true);

C++ execution causes monitor to disconnect

the issue I'm having is that upon executing this code, it clicks, and then my monitor turns blue and says "HDMI no cable connected", and either returns back to normal after 1 second, or stays on that screen until I perform an action (click, alt etc).
Anybody with any idea on why this is happening would be appreciated.
#include "stdafx.h"
#include <Windows.h>
using namespace std;
void function() {
INPUT Input;
Input.type = INPUT_MOUSE;
Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(true, &Input, sizeof(Input));
Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(true, &Input, sizeof(Input));
};
int main()
{
Sleep(3000);
function();
return 0;
}
Also, I'm using Visual Studio 2017 Community. This problem occurs when debugging the code, and when running the executable. There are no errors or warnings with my code.
You are not initializing the INPUT structure properly thus (probably) invoking undefined behavior. Initialize the structure fields to zeros using:
INPUT Input = {};
You can also go with an array of two elements:
INPUT Input[2] = {0};
followed by a:
Input[0].type = INPUT_MOUSE;
Input[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
Input[1].type = INPUT_MOUSE;
Input[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
and one call to SendInput:
SendInput(2, Input, sizeof(INPUT));
You are not initializing most of INPUT fields sending some garbage and potentially triggering Undefined Behavior. You should at least fill them with zeros:
Input.type = INPUT_MOUSE;
Input.mi.dx = 0;
Input.mi.dy = 0;
Input.mi.mouseData = 0;
Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
Input.mi.time = 0;
Input.mi.dwExtraInfo = 0;

Sending Mouse Click to DirectX Game Running as Admin

I have been building a gaming-related program that needs to send simulated input to the game (which is the top window on the screen and runs in fullscreen mode). After some struggling, I finally got mouse movements (cursor drag) and keyboard input working, but for some reason, the game will not respond to simulated mouse clicks.
I have tried the following:
#if TRUE // SendInput works for keyboard simulation and mouse drag, but not clicks:
INPUT mouse = {0};
mouse.type = INPUT_MOUSE;
mouse.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(1, &mouse, sizeof(INPUT));
Sleep(100);
ZeroMemory(&mouse, sizeof INPUT);
mouse.type = INPUT_MOUSE;
mouse.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &mouse, sizeof(INPUT));
#else // tried this, but it did not work:
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Sleep(75);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
#endif
The first dilemma I faced was sending the messages in general, but I realized this issue was caused by game process privileges > sending application privileges. After this, I encountered another problem with keypresses only registering on certain game windows/screens, but after some searching, I was able to use scancodes to overcome this. For example:
void SendSpacePress(bool bHardwareLevel){
INPUT space = {0};
space.type = INPUT_KEYBOARD;
space.ki.time = 0;
space.ki.dwExtraInfo = 0;
if(!bHardwareLevel){
space.ki.wVk = VK_SPACE;
}else{
space.ki.wScan = 0x39; // physical keyboard scan code
}
space.ki.dwFlags = bHardwareLevel ? KEYEVENTF_SCANCODE : 0;
SendInput(1, &space, sizeof(INPUT));
Sleep(rand()%25 + 25);
space.ki.dwFlags = bHardwareLevel ? KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP : KEYEVENTF_KEYUP;
SendInput(1, &space, sizeof(INPUT));
}
I have also been able to do mouse movement using INPUT like below:
void PanMouse(){
INPUT mouse = {0};
mouse.type = INPUT_MOUSE;
mouse.mi.time = 0;
mouse.mi.mouseData = 0;
mouse.mi.dwExtraInfo = 0;
mouse.mi.dwFlags = MOUSEEVENTF_MOVE;
mouse.mi.dx = rand()%10 -5;
mouse.mi.dy = rand()%10 -5;
SendInput(1, &mouse, sizeof(INPUT));
}
Now the big problem is the game refuses to register my simulated mouse clicks. I would preferably like a way to send the mouse inputs without having to dive into hooking. (The game has multiple client-side anti-cheat mechanisms, so I would venture to guess that any kind of foreign process hooking or DLL injection would trigger the protection.) From what I have read, I might need to write a custom driver for a simulated hardware mouse so the input comes at the kernel level. Not a preferable option, but if need be, sobeit. (And if need be, can anyone provide helpful information for this? I have never messed around with writing drivers, but there's a first time for everything I suppose.)
TL;DR: What do I need to do to get simulated mouse clicks to register in a game that seems to ignore non-hardware input? (I.e., how can I trick the game into thinking mouse clicks are legitimate similarly to using KEYEVENTF_SCANCODE when simulating keyboard input?)
Instead of sleeping between inputs, you need to inject a pair of mouse inputs together with the time member appropriately set to indicate "how long".
Here's something close to what you want. This will click the current cursor position with the left mouse simulated for 100ms.
INPUT inputs[2] = {};
inputs[0].type = INPUT_MOUSE;
inputs[0].mi.time = 0;
inputs[0].mi.dx = 0;
inputs[0].mi.dy = 0;
inputs[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
inputs[1].type = INPUT_MOUSE;
inputs[1].mi.time = 100;
inputs[1].mi.dx = 0;
inputs[1].mi.dy = 0;
inputs[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(2, inputs, sizeof(INPUT));
The mouse event won't happen immediately. It gets "queued" to happen shortly afterwards.
You should use the same technique for your keyboard events. Don't call "Sleep".

Screen goes black when i use SendInput to send mouse cursor positions

I am using SendInput() to send relative positions of the mouse. First ill tel you what am doing.
i use my finger to move the mouse. So first i track my finger in a 640x480 image and get the absolute position in pixels with in the image.
then i send that position to the following method to generate relative mouse position commands using send input.
When the finger goes to the left boundary (xlim1) or the right boundary (xlim2) cursor keep scrolling horizontally to either left or right depending on which limit.
The issue is when i run the code and just when the cursor starts to move, screen goes to black.
when i comment the part else if(cx >= prevX && cx > xlim2){ .... } section, then it works.. (So the when finger point goes to right limit of the image it cursor keeps scrolling horizontally to the right. commented part enables the left horizontal scrolling).
bool first variable will be true if this is the first time, we capture the finger. Otherwise it is false.
void movMouse(int cx, int cy, bool first){
static int prevX = 0;
static int prevY = 0;
static int leftPrevX;
static int rightPrevX;
int mx,my;
if(first == true){
prevX = cx;
prevY = cy;
}
else{
mx = (cx - prevX);
my = (cy - prevY);
if(cx <= prevX && cx < xlim1){
mx = -20;
INPUT input;
input.type = INPUT_MOUSE;
input.mi.mouseData = 0;
input.mi.dx = -(mx);
input.mi.dy = (my);
input.mi.dwFlags = MOUSEEVENTF_MOVE;
SendInput(1, &input, sizeof(input));
}
else if(cx >= prevX && cx > xlim2){
mx = 20;
INPUT input;
input.type = INPUT_MOUSE;
input.mi.mouseData = 0;
input.mi.dx = -(mx);
input.mi.dy = (my);
input.mi.dwFlags = MOUSEEVENTF_MOVE;
SendInput(1, &input, sizeof(input));
}
else {
INPUT input;
input.type = INPUT_MOUSE;
input.mi.mouseData = 0;
input.mi.dx = -(mx);
input.mi.dy = (my);
input.mi.dwFlags = MOUSEEVENTF_MOVE;
SendInput(1, &input, sizeof(input));
}
prevX = cx;
prevY = cy;
}
}
Try
ZeroMemory(&input,sizeof(input));
also intialize all the variables including input.time
it worked for me :)
I ran into this same problem, even though I was calling ZeroMemory and doing everything else correctly. I was using input.mi.time to inform Windows of the spacing between the clicks, e.g. so double-click would work correctly. However I was getting the 'time' values from a remote computer. Because they differed from the local computer's time it caused Windows to invoke the screen saver! To workaround the problem I added some logic to detect the skew between the computers and bring the values somewhat in line with each other.
In summary: Make sure that input.mi.time is either zero or a value somewhat close to GetTickCount(). Using ZeroMemory to initialize the variable is an excellent suggestion.