uLib  User mode C/C++ extended API library for Win32 programmers.
InputEmu.cpp
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode library.
3 // Module: Keyboard and mouse input emulation (SendInput simplifiers).
4 // Author: Copyright (c) Love Nystrom
5 // License: NNOSL (BSD descendant, see NNOSL.txt in the base directory).
6 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 
8 #include <uLib/InputEmu.h>
9 #include <uLib/Debug.h>
10 
11 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 // Keyboard
13 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14 
15 void MakeKeyInput( INPUT* Inp, WORD vKey, DWORD Flags )
16 {
17  bool ex = (vKey > 254) || (vKey == 0);
18  Inp->type = INPUT_KEYBOARD;
19  Inp->ki.wVk = ex ? 0 : vKey; // Only 1-254 allowed.
20  Inp->ki.dwFlags = Flags | (ex ? KEYEVENTF_SCANCODE : 0);
21  Inp->ki.wScan = ex ? MapVirtualKey( vKey, MAPVK_VK_TO_VSC ) : 0;
22  Inp->ki.dwExtraInfo = 0;
23  Inp->ki.time = 0;
24 }
25 
26 UINT SendKeyInput( WORD vKey, DWORD Flags ) // Send a single key
27 {
28  INPUT Inp; //INPUT Inp = { INPUT_KEYBOARD, {{ vKey,0, Flags,0,0 }}};
29  MakeKeyInput( &Inp, vKey, Flags );
30  TRACE( DP_DEBUG, _T("SendKeyInput( %u, %s )\n"), vKey, Flags & KEYEVENTF_KEYUP ? "KeyUp" : "KeyDown" );
31  return SendInput( 1, &Inp, sizeof(INPUT) );
32 }
33 
34 bool SendKeyPress( WORD vKey ) // Send a single key
35 {
36  INPUT Inp[2];
37  MakeKeyInput( &Inp[0], vKey, 0 );
38  MakeKeyInput( &Inp[1], vKey, KEYEVENTF_KEYUP );
39  TRACE( DP_DEBUG, _T("SendKeyPress( %u )\n"), vKey );
40  return (SendInput( 2, Inp, sizeof(INPUT) ) == 2);
41 }
42 
43 bool SendHotKey( WORD Hotkey )
44 {
45  WORD nEvt;
46  INT ix;
47  BYTE flags,fext;
48  UINT nSent;
49  bool kExt,kShift,kCtrl,kAlt;
50  INPUT Inp[9];
51 
52  flags = HIBYTE( Hotkey );
53  if (flags) {
54  kAlt = bool_cast( flags & HOTKEYF_ALT );
55  kCtrl = bool_cast( flags & HOTKEYF_CONTROL );
56  kShift = bool_cast( flags & HOTKEYF_SHIFT );
57  kExt = bool_cast( flags & HOTKEYF_EXT );
58  } else {
59  kExt = kShift = kCtrl = kAlt = false;
60  }
61  nEvt = 2; // Base vkey down/up events
62  if (kShift) nEvt += 2; // Shift down/up
63  if (kCtrl) nEvt += 2; // Ctrl down/up
64  if (kAlt) nEvt += 2; // Alt down/up
65 
66  #if 0
67  BYTE kbState[256];
68  // Make sure any pre-existing shift state don't affect the outcome.
69  // NOTE: SetKeyboardState effect only the current thread, which is
70  // not useful here, so send individual key ups if needed.
71  if (GetKeyboardState( kbState ))
72  {
73  if (kbState[VK_SHIFT] && !kShift) SendKeyInput( VK_SHIFT, KEYEVENTF_KEYUP );
74  if (kbState[VK_CONTROL] && !kCtrl) SendKeyInput( VK_CONTROL, KEYEVENTF_KEYUP );
75  if (kbState[VK_MENU] && !kAlt) SendKeyInput( VK_MENU, KEYEVENTF_KEYUP );
76  }
77  #endif
78 
79  ix = -1;
80  memset( Inp,0,sizeof(Inp) );
81 
82  if (kShift) MakeKeyInput( &Inp[++ix], VK_SHIFT, 0 );
83  if (kCtrl) MakeKeyInput( &Inp[++ix], VK_CONTROL, 0 );
84  if (kAlt) MakeKeyInput( &Inp[++ix], VK_MENU, 0 );
85 
86  fext = kExt ? KEYEVENTF_EXTENDEDKEY : 0;
87  MakeKeyInput( &Inp[++ix], LOBYTE( Hotkey ), fext );
88  MakeKeyInput( &Inp[++ix], LOBYTE( Hotkey ), KEYEVENTF_KEYUP| fext );
89 
90  if (kShift) MakeKeyInput( &Inp[++ix], VK_SHIFT, KEYEVENTF_KEYUP );
91  if (kCtrl) MakeKeyInput( &Inp[++ix], VK_CONTROL, KEYEVENTF_KEYUP );
92  if (kAlt) MakeKeyInput( &Inp[++ix], VK_MENU, KEYEVENTF_KEYUP );
93 
94  // Pump it out.
95  // NOTE: SendInput is a _sensitive_ beast.
96 
97  nSent = SendInput( nEvt, Inp, sizeof(INPUT) );
98  #ifdef _DEBUG
99  if (nSent != nEvt) ERROR_TRACE( _T("SendHotKey") );
100  #endif
101  return (nSent == nEvt);
102 }
103 
104 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105 // Mouse
106 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
107 
108 void MakeMouseInput( INPUT* Inp, LONG dx, LONG dy, LONG data, DWORD Flags )
109 {
110  Inp->type = INPUT_MOUSE;
111  Inp->mi.dx = dx;
112  Inp->mi.dy = dy;
113  Inp->mi.mouseData = (DWORD) data;
114  Inp->mi.dwFlags = Flags;
115  Inp->mi.dwExtraInfo = 0;
116  Inp->mi.time = 0;
117 }
118 
119 UINT SendMouseInput( LONG dx, LONG dy, LONG data, DWORD Flags )
120 // Send a single mouse event
121 {
122  INPUT Inp = { INPUT_MOUSE, {{ dx, dy, LITERAL( DWORD, data ), Flags, 0,0 }}};
123  // Whoever declared the MOUSEINPUT struct forgot to consider negative 'mouseData'.
124  TRACE( DP_DEBUG, _T("SendMouseInput( %i, %i, %i, %#x )\n"), dx, dy, data, Flags );
125  return SendInput( 1, &Inp, sizeof(INPUT) );
126 }
127 
129 // Send a single mouse click/chord (press and release)
130 {
131  INPUT Inp[6];
132  UINT nEvt, nSent;
133  bool kLeft, kMid, kRight;
134 
135  kLeft = ((Key & LBUTTON) != 0);
136  kMid = ((Key & MBUTTON) != 0);
137  kRight = ((Key & RBUTTON) != 0);
138  if (!kLeft && !kMid && !kRight) return false; // Huh? Nothing.
139 
140  nEvt = 0;
141  if (kLeft) MakeMouseInput( &Inp[nEvt++], 0,0,0, MOUSEEVENTF_LEFTDOWN );
142  if (kMid) MakeMouseInput( &Inp[nEvt++], 0,0,0, MOUSEEVENTF_MIDDLEDOWN );
143  if (kRight) {
144  MakeMouseInput( &Inp[nEvt++], 0,0,0, MOUSEEVENTF_RIGHTDOWN );
145  MakeMouseInput( &Inp[nEvt++], 0,0,0, MOUSEEVENTF_RIGHTUP );
146  }
147  if (kMid) MakeMouseInput( &Inp[nEvt++], 0,0,0, MOUSEEVENTF_MIDDLEUP );
148  if (kLeft) MakeMouseInput( &Inp[nEvt++], 0,0,0, MOUSEEVENTF_LEFTUP );
149 
150  nSent = SendInput( nEvt, Inp, sizeof(INPUT) );
151  #ifdef _DEBUG
152  if (nSent != nEvt) ERROR_TRACE( _T("SendMouseClick") );
153  #endif
154  return (nSent == nEvt);
155 }
156 
157 // EOF
unsigned long DWORD
Definition: Common.h:414
void MakeKeyInput(INPUT *Inp, WORD vKey, DWORD Flags)
Definition: InputEmu.cpp:15
unsigned short WORD
Definition: Common.h:413
UINT SendMouseInput(LONG dx, LONG dy, LONG data, DWORD Flags)
Definition: InputEmu.cpp:119
#define DP_DEBUG
Definition: Debug.h:85
#define ERROR_TRACE(What)
Definition: Debug.h:233
#define TRACE(_lvl,...)
Definition: Debug.h:216
bool SendHotKey(WORD Hotkey)
Definition: InputEmu.cpp:43
bool SendMouseClick(MOUSEKEY Key)
Definition: InputEmu.cpp:128
bool __forceinline bool_cast(BOOL B52)
Definition: Common.h:767
void MakeMouseInput(INPUT *Inp, LONG dx, LONG dy, LONG data, DWORD Flags)
Definition: InputEmu.cpp:108
Debug and error handling support.
UINT SendKeyInput(WORD vKey, DWORD Flags)
Definition: InputEmu.cpp:26
MOUSEKEY
Definition: InputEmu.h:76
#define LITERAL(type, x)
Definition: Common.h:969
unsigned char BYTE
Definition: Common.h:412
bool SendKeyPress(WORD vKey)
Definition: InputEmu.cpp:34