-1
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.

blank
  • 54
  • 5
  • Calling `SendInput()` with `cInputs=1` is (almost) always a bug. Send multiple inputs in a single call using an `INPUT[]` array. Also, [it takes time for simulated input to be processed](https://devblogs.microsoft.com/oldnewthing/20140213-00/?p=1773). And how do you know this is not sending any clicks? What result are you expecting when a click happens? It looks like you expect a variable in another process to change, how do you know you are watching the correct variable, or that the other process is not designed to ignore simulated input? Why are you using simulated clicks in the first place? – Remy Lebeau Jul 07 '20 at 18:01
  • Yes, it's reading a boolean value and only clicks if that value is 1. I know it works, because without the clock stuff, it clicks too fast. I'm trying to only send 1 click every 500ms using clock() – blank Jul 07 '20 at 19:47
  • You didn't answer all of my questions. You said the code is not sending any clicks. How do you know that? Based on your console output, it actually is sending clicks. So how do you know the target process is not simply ignoring your clicks? Or that you are actually clicking at the right screen coordinates (since you are not moving the mouse)? What is your actual goal here? There are other ways to trigger UI clicks (UI Automation. Window messages), have you tried any of them yet? – Remy Lebeau Jul 07 '20 at 21:56
  • What would make it ignore the clicks? If value is 1, it's at the right coordinates. Goal is to left click when value is 1, which works; Every 500ms, which doesn't work. If you take out the clock stuff and just have leftClick in the if(value==1), it clicks using either SendInput or mouse_events. It's pretty obvious if it clicks. In your opinion, what's the best way to read process memory for a value, and send a left click with a 500ms delay between clicks? Like I said, this works just fine without the clock. – blank Jul 07 '20 at 22:15
  • "*What would make it ignore the clicks?*" - if it is *specifically designed* to ignore fake user input, which can be done easily via a `WH_MOUSE_LL` hook looking for the `LLMHF_INJECTED`/`LLMHF_LOWER_IL_INJECTED` flags on input events. "*Like I said, this works just fine without the clock*" - then the problem has to be in your own code, not in the clicks themselves, unless the target app is *specifically designed* to ignore clicks that are received after a delay. – Remy Lebeau Jul 07 '20 at 22:48
  • I'm speculating here, since we don't know what kind of app you are trying to control or why. How and where are you invoking your code? Is it inside some kind of loop, is that why you using `clock()` at all? Why not use a real timer instead? – Remy Lebeau Jul 07 '20 at 22:51
  • It's all in a while(1) loop to repeatedly read that memory address for the value, that's why it clicks too fast without a delay. First I tried Sleep but that isn't time accurate. I looked for more time accurate ways of delaying and clock seemed like a good option. If it was ignoring delayed inputs then at least the first click would send. If the problem is in the code, it's all right there. Whats wrong with it? It still calls leftClick and goes through it in the same way as without clock. – blank Jul 08 '20 at 01:37
  • All I've done is research to this point, so I don't understand the down vote. If the app is ignoring fake input, the clicks wouldn't work period. If it's only ignoring delayed fake input, the first leftClick would work, if there's something wrong with the clock code, it wouldn't still run everything except for specifically the SendInputs/mouse_events. I'll look in to "a real timer" and hopefully find an alternative solution. Hopefully if that code up there is wrong, someone can correct it. – blank Jul 08 '20 at 01:37
  • I would use [a waitable timer](https://learn.microsoft.com/en-us/windows/win32/sync/waitable-timer-objects) instead of constantly polling the `clock()`. Create a timer object with the desired interval, and then have the loop use `WaitForSingleObject()` with a 0ms timeout to query if the timer has been signaled or not. If it has, then perform the click, and reset the timer if needed. As for the downvote, that is likely because you lack a [mcve] to demonstrate the problem in action. – Remy Lebeau Jul 08 '20 at 01:38
  • Thank you for your help, that seems like a better way to do it. – blank Jul 08 '20 at 01:58

1 Answers1

0

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.

GuidedHacking
  • 3,628
  • 1
  • 9
  • 59