Search code examples
c++windowswinapisendinput

Do I need to introduce delays when simulating a mouse click with SendInput API?


I need to be able to simulate a mouse click on a control in another process. I came up with the following method:

BOOL SimulateMouseClick(POINT* pPntAt)
{
    //Simulate mouse left-click
    //'pPntAt' = mouse coordinate on the screen
    //RETURN:
    //      = TRUE if success
    BOOL bRes = FALSE;

    if(pPntAt)
    {
        //Get current mouse position
        POINT pntMouse = {0};
        BOOL bGotPntMouse = ::GetCursorPos(&pntMouse);

        //Move mouse to a new position
        ::SetCursorPos(pPntAt->x, pPntAt->y);

        //Send mouse click simulation
        INPUT inp = {0};
        inp.type = INPUT_MOUSE;
        inp.mi.dx = pPntAt->x;
        inp.mi.dy = pPntAt->y;
        inp.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
        if(SendInput(1, &inp, sizeof(inp)) == 1)
        {
            //Do I need to wait here?
            Sleep(100);

            inp.mi.dwFlags = MOUSEEVENTF_LEFTUP;
            if(SendInput(1, &inp, sizeof(inp)) == 1)
            {
                //Do I need to wait here before restoring mouse pos?
                Sleep(500);

                //Done
                bRes = TRUE;
            }
        }

        //Restore mouse
        if(bGotPntMouse)
        {
            ::SetCursorPos(pntMouse.x, pntMouse.y);
        }
    }

    return bRes;
}

My question is do I need to introduce those artificial delays like a human mouse click would have?


Solution

  • The documentation for SendInput contains the following:

    The SendInput function inserts the events in the INPUT structures serially into the keyboard or mouse input stream. These events are not interspersed with other keyboard or mouse input events inserted either by the user (with the keyboard or mouse) or by calls to keybd_event, mouse_event, or other calls to SendInput.

    This is the reason, why SendInput was introduced. Placing artificial delays between individual calls of SendInput completely defies its purpose.

    The short answer is: No, you do not need to introduce delays between synthesized input. You also do not need to call SetCursorPos; the INPUT structure already contains the location of the mouse input.

    Of course, you wouldn't have to deal with any of this, if you went with UI Automation instead. A design goal of UI Automation is "to manipulate the UI by means other than standard input. UI Automation also allows automated test scripts to interact with the UI."