Skip to content

Instantly share code, notes, and snippets.

@the-nose-knows
Last active May 24, 2018 23:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save the-nose-knows/ea22ed01f2662855a2ce8c067e0ad8d4 to your computer and use it in GitHub Desktop.
Save the-nose-knows/ea22ed01f2662855a2ce8c067e0ad8d4 to your computer and use it in GitHub Desktop.
#include <Windows.h>
// == MOUSE ACTIONS ==
// Uses absolute coords where the primary display starts at 0,0
// That works well with enumerated monitors structures and their reported coords.
#define SET_MOUSE_MOVE mip.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
#define SET_MOUSE_RCLICK_HOLD mip.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
#define SET_MOUSE_RCLICK_RELEASE mip.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
#define SET_MOUSE_LCLICK_HOLD mip.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
#define SET_MOUSE_LCLICK_RELEASE mip.mi.dwFlags = MOUSEEVENTF_LEFTUP;
#define SET_MOUSE_MDCLICK_HOLD mip.mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN;
#define SET_MOUSE_MDCLICK_RELEASE mip.mi.dwFlags = MOUSEEVENTF_MIDDLEUP;
// You need these modifiers for correct coordinate mapping
#define VIRTUAL_X_MODIFIER (65536 / GetSystemMetrics(SM_CXSCREEN));
#define VIRTUAL_Y_MODIFIER (65536 / GetSystemMetrics(SM_CYSCREEN));
// Each wheel segment is supposed to be a multiple of 120.
// WHEEL_DELTA is 120. INT_MAX and -INT_MAX are the max values that mouseData will accept for this.
// INT_MAX is roughly 8 to 12 "pages" of scrolling, but your scroll behavior will vary per-app.
#define SET_MOUSE_WHEEL_UP_ONCE mip.mi.dwFlags = MOUSEEVENTF_WHEEL; mip.mi.mouseData = WHEEL_DELTA;
#define SET_MOUSE_WHEEL_DOWN_ONCE mip.mi.dwFlags = MOUSEEVENTF_WHEEL; mip.mi.mouseData = -WHEEL_DELTA;
#define SET_MOUSE_WHEEL_UP_MAX mip.mi.dwFlags = MOUSEEVENTF_WHEEL; mip.mi.mouseData = INT_MAX;
#define SET_MOUSE_WHEEL_DOWN_MAX mip.mi.dwFlags = MOUSEEVENTF_WHEEL; mip.mi.mouseData = -INT_MAX;
#define SEND_MOUSE_ACTION SendInput(1, &mip, sizeof(mip));
// == KEYBOARD ACTIONS ==
#define KEYDOWN 0;
#define SET_SHIFT_KEY_DOWN kip.ki.wVk = VK_SHIFT; kip.ki.dwFlags = KEYDOWN;
#define SET_SHIFT_KEY_UP kip.ki.wVk = VK_SHIFT; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_LSHIFT_KEY_DOWN kip.ki.wVk = VK_LSHIFT; kip.ki.dwFlags = KEYDOWN;
#define SET_LSHIFT_KEY_UP kip.ki.wVk = VK_LSHIFT; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_RSHIFT_KEY_DOWN kip.ki.wVk = VK_RSHIFT; kip.ki.dwFlags = KEYDOWN;
#define SET_RSHIFT_KEY_UP kip.ki.wVk = VK_RSHIFT; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_ALT_KEY_DOWN kip.ki.wVk = VK_MENU; kip.ki.dwFlags = KEYDOWN;
#define SET_ALT_KEY_UP kip.ki.wVk = VK_MENU; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_LALT_KEY_DOWN kip.ki.wVk = VK_LMENU; kip.ki.dwFlags = KEYDOWN;
#define SET_LALT_KEY_UP kip.ki.wVk = VK_LMENU; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_RALT_KEY_DOWN kip.ki.wVk = VK_RMENU; kip.ki.dwFlags = KEYDOWN;
#define SET_RALT_KEY_UP kip.ki.wVk = VK_RMENU; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_CTRL_KEY_DOWN kip.ki.wVk = VK_CONTROL; kip.ki.dwFlags = KEYDOWN;
#define SET_CTRL_KEY_UP kip.ki.wVk = VK_CONTROL; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_LCTRL_KEY_DOWN kip.ki.wVk = VK_LCONTROL; kip.ki.dwFlags = KEYDOWN;
#define SET_LCTRL_KEY_UP kip.ki.wVk = VK_LCONTROL; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_RCTRL_KEY_DOWN kip.ki.wVk = VK_RCONTROL; kip.ki.dwFlags = KEYDOWN;
#define SET_RCTRL_KEY_UP kip.ki.wVk = VK_RCONTROL; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_LWIN_KEY_DOWN kip.ki.wVk = VK_LWIN; kip.ki.dwFlags = KEYDOWN;
#define SET_LWIN_KEY_UP kip.ki.wVk = VK_LWIN; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_RWIN_KEY_DOWN kip.ki.wVk = VK_RWIN; kip.ki.dwFlags = KEYDOWN;
#define SET_RWIN_KEY_UP kip.ki.wVk = VK_RWIN; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_APPS_KEY_DOWN kip.ki.wVk = VK_APPS; kip.ki.dwFlags = KEYDOWN;
#define SET_APPS_KEY_UP kip.ki.wVk = VK_APPS; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_PAUSE_KEY_DOWN kip.ki.wVk = VK_PAUSE; kip.ki.dwFlags = KEYDOWN;
#define SET_PAUSE_KEY_UP kip.ki.wVk = VK_PAUSE; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_CLEAR_KEY_DOWN kip.ki.wVk = VK_CLEAR; kip.ki.dwFlags = KEYDOWN;
#define SET_CLEAR_KEY_UP kip.ki.wVk = VK_CLEAR; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_INSERT_KEY_DOWN kip.ki.wVk = VK_INSERT; kip.ki.dwFlags = KEYDOWN;
#define SET_INSERT_KEY_UP kip.ki.wVk = VK_INSERT; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_PRNTSCRN_KEY_DOWN kip.ki.wVk = VK_SNAPSHOT; kip.ki.dwFlags = KEYDOWN;
#define SET_PRNTSCRN_KEY_UP kip.ki.wVk = VK_SNAPSHOT; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_PRINT_KEY_DOWN kip.ki.wVk = VK_PRINT; kip.ki.dwFlags = KEYDOWN;
#define SET_PRINT_KEY_UP kip.ki.wVk = VK_PRINT; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_BREAK_KEY_DOWN kip.ki.wVk = VK_CANCEL; kip.ki.dwFlags = KEYDOWN;
#define SET_BREAK_KEY_UP kip.ki.wVk = VK_CANCEL; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_BACKSPACE_KEY_DOWN kip.ki.wVk = VK_BACK; kip.ki.dwFlags = KEYDOWN;
#define SET_BACKSPACE_KEY_UP kip.ki.wVk = VK_BACK; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_DEL_KEY_DOWN kip.ki.wVk = VK_DELETE; kip.ki.dwFlags = KEYDOWN;
#define SET_DEL_KEY_UP kip.ki.wVk = VK_DELETE; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_TAB_KEY_DOWN kip.ki.wVk = VK_TAB; kip.ki.dwFlags = KEYDOWN;
#define SET_TAB_KEY_UP kip.ki.wVk = VK_TAB; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_ENTER_KEY_DOWN kip.ki.wVk = VK_RETURN; kip.ki.dwFlags = KEYDOWN;
#define SET_ENTER_KEY_UP kip.ki.wVk = VK_RETURN; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_CAPSLOCK_KEY_DOWN kip.ki.wVk = VK_CAPITAL; kip.ki.dwFlags = KEYDOWN;
#define SET_CAPSLOCK_KEY_UP kip.ki.wVk = VK_CAPITAL; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_NUMLOCK_KEY_DOWN kip.ki.wVk = VK_NUMLOCK; kip.ki.dwFlags = KEYDOWN;
#define SET_NUMLOCK_KEY_UP kip.ki.wVk = VK_NUMLOCK; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_SCROLLLOCK_KEY_DOWN kip.ki.wVk = VK_SCROLL; kip.ki.dwFlags = KEYDOWN;
#define SET_SCROLLLOCK_KEY_UP kip.ki.wVk = VK_SCROLL; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_ESCAPE_KEY_DOWN kip.ki.wVk = VK_ESCAPE; kip.ki.dwFlags = KEYDOWN;
#define SET_ESCAPE_KEY_UP kip.ki.wVk = VK_ESCAPE; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_SPACEBAR_KEY_DOWN kip.ki.wVk = VK_SPACE; kip.ki.dwFlags = KEYDOWN;
#define SET_SPACEBAR_KEY_UP kip.ki.wVk = VK_SPACE; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_PAGEUP_KEY_DOWN kip.ki.wVk = VK_PRIOR; kip.ki.dwFlags = KEYDOWN;
#define SET_PAGEUP_KEY_UP kip.ki.wVk = VK_PRIOR; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_PAGEDOWN_KEY_DOWN kip.ki.wVk = VK_NEXT; kip.ki.dwFlags = KEYDOWN;
#define SET_PAGEDOWN_KEY_UP kip.ki.wVk = VK_NEXT; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_HOME_KEY_DOWN kip.ki.wVk = VK_HOME; kip.ki.dwFlags = KEYDOWN;
#define SET_HOME_KEY_UP kip.ki.wVk = VK_HOME; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_END_KEY_DOWN kip.ki.wVk = VK_END; kip.ki.dwFlags = KEYDOWN;
#define SET_END_KEY_UP kip.ki.wVk = VK_END; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_L_ARROW_KEY_DOWN kip.ki.wVk = VK_LEFT; kip.ki.dwFlags = KEYDOWN;
#define SET_L_ARROW_KEY_UP kip.ki.wVk = VK_LEFT; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_R_ARROW_KEY_DOWN kip.ki.wVk = VK_RIGHT; kip.ki.dwFlags = KEYDOWN;
#define SET_R_ARROW_KEY_UP kip.ki.wVk = VK_RIGHT; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_UP_ARROW_KEY_DOWN kip.ki.wVk = VK_UP; kip.ki.dwFlags = KEYDOWN;
#define SET_UP_ARROW_KEY_UP kip.ki.wVk = VK_UP; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_DOWN_ARROW_KEY_DOWN kip.ki.wVk = VK_DOWN; kip.ki.dwFlags = KEYDOWN;
#define SET_DOWN_ARROW_KEY_UP kip.ki.wVk = VK_DOWN; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_SLEEP_KEY_DOWN kip.ki.wVk = VK_SLEEP; kip.ki.dwFlags = KEYDOWN;
#define SET_SLEEP_KEY_UP kip.ki.wVk = VK_SLEEP; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F1_KEY_DOWN kip.ki.wVk = VK_F1; kip.ki.dwFlags = KEYDOWN;
#define SET_F1_KEY_UP kip.ki.wVk = VK_F1; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F2_KEY_DOWN kip.ki.wVk = VK_F2; kip.ki.dwFlags = KEYDOWN;
#define SET_F2_KEY_UP kip.ki.wVk = VK_F2; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F3_KEY_DOWN kip.ki.wVk = VK_F3; kip.ki.dwFlags = KEYDOWN;
#define SET_F3_KEY_UP kip.ki.wVk = VK_F3; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F4_KEY_DOWN kip.ki.wVk = VK_F4; kip.ki.dwFlags = KEYDOWN;
#define SET_F4_KEY_UP kip.ki.wVk = VK_F4; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F5_KEY_DOWN kip.ki.wVk = VK_F5; kip.ki.dwFlags = KEYDOWN;
#define SET_F5_KEY_UP kip.ki.wVk = VK_F5; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F6_KEY_DOWN kip.ki.wVk = VK_F6; kip.ki.dwFlags = KEYDOWN;
#define SET_F6_KEY_UP kip.ki.wVk = VK_F6; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F7_KEY_DOWN kip.ki.wVk = VK_F7; kip.ki.dwFlags = KEYDOWN;
#define SET_F7_KEY_UP kip.ki.wVk = VK_F7; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F8_KEY_DOWN kip.ki.wVk = VK_F8; kip.ki.dwFlags = KEYDOWN;
#define SET_F8_KEY_UP kip.ki.wVk = VK_F8; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F9_KEY_DOWN kip.ki.wVk = VK_F9; kip.ki.dwFlags = KEYDOWN;
#define SET_F9_KEY_UP kip.ki.wVk = VK_F9; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F10_KEY_DOWN kip.ki.wVk = VK_F10; kip.ki.dwFlags = KEYDOWN;
#define SET_F10_KEY_UP kip.ki.wVk = VK_F10; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F11_KEY_DOWN kip.ki.wVk = VK_F11; kip.ki.dwFlags = KEYDOWN;
#define SET_F11_KEY_UP kip.ki.wVk = VK_F11; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SET_F12_KEY_DOWN kip.ki.wVk = VK_F12; kip.ki.dwFlags = KEYDOWN;
#define SET_F12_KEY_UP kip.ki.wVk = VK_F12; kip.ki.dwFlags = KEYEVENTF_KEYUP;
#define SEND_KEYBOARD_ACTION SendInput(1, &kip, sizeof(kip));
int main()
{
INPUT mip;
mip.type = INPUT_MOUSE;
mip.mi.mouseData = 0;
INPUT kip;
kip.type = INPUT_KEYBOARD;
kip.ki.wScan = 0;
kip.ki.time = 0;
kip.ki.dwExtraInfo = 0;
// Change 500 to -500 for a left-hand extended display.
mip.mi.dx = -500 * VIRTUAL_X_MODIFIER;
mip.mi.dy = 1000 * VIRTUAL_Y_MODIFIER;
// Un-comment this Sleep timer if you're debugging in an IDE and need a quick pause.
// Sleep(500);
SET_MOUSE_MOVE;
SEND_MOUSE_ACTION;
// Various users advise brief Sleep pauses between queued mouse and keyboard events.
// 500 milliseconds is probably overkill for your automation requirements.
Sleep(500);
SET_MOUSE_RCLICK_HOLD;
SEND_MOUSE_ACTION;
Sleep(500);
SET_MOUSE_RCLICK_RELEASE;
SEND_MOUSE_ACTION;
Sleep(500);
mip.mi.dx -= 10 * VIRTUAL_X_MODIFIER;
mip.mi.dx -= 10 * VIRTUAL_Y_MODIFIER;
SET_MOUSE_MOVE;
SEND_MOUSE_ACTION;
Sleep(500);
SET_MOUSE_LCLICK_HOLD;
SEND_MOUSE_ACTION;
Sleep(1);
SET_MOUSE_LCLICK_RELEASE;
SEND_MOUSE_ACTION;
Sleep(500);
// This will do an "Apps"-key click, aka Menu-click.
// The ALT key was historically referred to as MENU, unfortunately.
SET_APPS_KEY_DOWN;
SEND_KEYBOARD_ACTION;
Sleep(1);
SET_MOUSE_LCLICK_HOLD;
SEND_MOUSE_ACTION;
Sleep(1);
SET_MOUSE_LCLICK_RELEASE;
SEND_MOUSE_ACTION;
Sleep(1);
SET_APPS_KEY_UP;
SEND_KEYBOARD_ACTION;
mip.mi.dx -= 10 * VIRTUAL_X_MODIFIER;
mip.mi.dx -= 10 * VIRTUAL_Y_MODIFIER;
Sleep(500);
SET_MOUSE_MOVE;
SEND_MOUSE_ACTION;
Sleep(500);
SET_MOUSE_LCLICK_HOLD;
SEND_MOUSE_ACTION;
Sleep(1);
SET_MOUSE_LCLICK_RELEASE;
SEND_MOUSE_ACTION;
// These next two are simulating scrolling the mouse-wheel one segment down, then up.
Sleep(500);
SET_MOUSE_WHEEL_DOWN_ONCE;
SEND_MOUSE_ACTION;
Sleep(500);
SET_MOUSE_WHEEL_UP_ONCE;
SEND_MOUSE_ACTION;
// You can't arbitrarily scroll to the bottom of any app with one max scroll movement.
// You should be able to chain them unnoticeably, however.
// Test this with at least 2000 lines in Notepad++
Sleep(500);
SET_MOUSE_WHEEL_DOWN_MAX;
SEND_MOUSE_ACTION;
Sleep(1);
SET_MOUSE_WHEEL_DOWN_MAX;
SEND_MOUSE_ACTION;
Sleep(500);
SET_MOUSE_WHEEL_UP_MAX;
SEND_MOUSE_ACTION;
Sleep(500);
SET_CTRL_KEY_DOWN;
SEND_KEYBOARD_ACTION;
Sleep(1);
SET_SHIFT_KEY_DOWN;
SEND_KEYBOARD_ACTION;
Sleep(1);
SET_ESCAPE_KEY_DOWN;
SEND_KEYBOARD_ACTION;
Sleep(1);
SET_ESCAPE_KEY_UP;
SEND_KEYBOARD_ACTION;
Sleep(1);
SET_SHIFT_KEY_UP;
SEND_KEYBOARD_ACTION;
Sleep(1);
SET_CTRL_KEY_UP;
SEND_KEYBOARD_ACTION;
Sleep(1000);
SET_ALT_KEY_DOWN;
SEND_KEYBOARD_ACTION;
Sleep(1);
SET_F4_KEY_DOWN;
SEND_KEYBOARD_ACTION;
Sleep(1);
SET_F4_KEY_UP;
SEND_KEYBOARD_ACTION;
Sleep(1);
SET_ALT_KEY_UP;
SEND_KEYBOARD_ACTION;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment