play.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. # coding: utf-8
  2. """
  3. """
  4. import ctypes
  5. import time
  6. import sys
  7. import argparse
  8. import re
  9. parser = argparse.ArgumentParser()
  10. parser.add_argument("--file", "-f", type=str, required=True)
  11. parser.add_argument("--title", "-t", type=str, required=True)
  12. LONG = ctypes.c_long
  13. DWORD = ctypes.c_ulong
  14. ULONG_PTR = ctypes.POINTER(DWORD)
  15. WORD = ctypes.c_ushort
  16. INPUT_MOUSE = 0
  17. INPUT_KEYBOARD = 1
  18. INPUT_HARDWARE = 2
  19. KEYEVENTF_EXTENDEDKEY = 0x0001
  20. KEYEVENTF_KEYUP = 0x0002
  21. KEYEVENTF_SCANCODE = 0x0008
  22. KEYEVENTF_UNICODE = 0x0004
  23. VK_LBUTTON = 0x01 # Left mouse button
  24. VK_RBUTTON = 0x02 # Right mouse button
  25. VK_CANCEL = 0x03 # Control-break processing
  26. VK_MBUTTON = 0x04 # Middle mouse button (three-button mouse)
  27. VK_XBUTTON1 = 0x05 # X1 mouse button
  28. VK_XBUTTON2 = 0x06 # X2 mouse button
  29. VK_BACK = 0x08 # BACKSPACE key
  30. VK_TAB = 0x09 # TAB key
  31. VK_CLEAR = 0x0C # CLEAR key
  32. VK_RETURN = 0x0D # ENTER key
  33. VK_SHIFT = 0x10 # SHIFT key
  34. VK_CONTROL = 0x11 # CTRL key
  35. VK_MENU = 0x12 # ALT key
  36. VK_PAUSE = 0x13 # PAUSE key
  37. VK_CAPITAL = 0x14 # CAPS LOCK key
  38. VK_KANA = 0x15 # IME Kana mode
  39. VK_HANGUL = 0x15 # IME Hangul mode
  40. VK_JUNJA = 0x17 # IME Junja mode
  41. VK_FINAL = 0x18 # IME final mode
  42. VK_HANJA = 0x19 # IME Hanja mode
  43. VK_KANJI = 0x19 # IME Kanji mode
  44. VK_ESCAPE = 0x1B # ESC key
  45. VK_CONVERT = 0x1C # IME convert
  46. VK_NONCONVERT = 0x1D # IME nonconvert
  47. VK_ACCEPT = 0x1E # IME accept
  48. VK_MODECHANGE = 0x1F # IME mode change request
  49. VK_SPACE = 0x20 # SPACEBAR
  50. VK_PRIOR = 0x21 # PAGE UP key
  51. VK_NEXT = 0x22 # PAGE DOWN key
  52. VK_END = 0x23 # END key
  53. VK_HOME = 0x24 # HOME key
  54. VK_LEFT = 0x25 # LEFT ARROW key
  55. VK_UP = 0x26 # UP ARROW key
  56. VK_RIGHT = 0x27 # RIGHT ARROW key
  57. VK_DOWN = 0x28 # DOWN ARROW key
  58. VK_SELECT = 0x29 # SELECT key
  59. VK_PRINT = 0x2A # PRINT key
  60. VK_EXECUTE = 0x2B # EXECUTE key
  61. VK_SNAPSHOT = 0x2C # PRINT SCREEN key
  62. VK_INSERT = 0x2D # INS key
  63. VK_DELETE = 0x2E # DEL key
  64. VK_HELP = 0x2F # HELP key
  65. VK_LWIN = 0x5B # Left Windows key (Natural keyboard)
  66. VK_RWIN = 0x5C # Right Windows key (Natural keyboard)
  67. VK_APPS = 0x5D # Applications key (Natural keyboard)
  68. VK_SLEEP = 0x5F # Computer Sleep key
  69. VK_NUMPAD0 = 0x60 # Numeric keypad 0 key
  70. VK_NUMPAD1 = 0x61 # Numeric keypad 1 key
  71. VK_NUMPAD2 = 0x62 # Numeric keypad 2 key
  72. VK_NUMPAD3 = 0x63 # Numeric keypad 3 key
  73. VK_NUMPAD4 = 0x64 # Numeric keypad 4 key
  74. VK_NUMPAD5 = 0x65 # Numeric keypad 5 key
  75. VK_NUMPAD6 = 0x66 # Numeric keypad 6 key
  76. VK_NUMPAD7 = 0x67 # Numeric keypad 7 key
  77. VK_NUMPAD8 = 0x68 # Numeric keypad 8 key
  78. VK_NUMPAD9 = 0x69 # Numeric keypad 9 key
  79. VK_MULTIPLY = 0x6A # Multiply key
  80. VK_ADD = 0x6B # Add key
  81. VK_SEPARATOR = 0x6C # Separator key
  82. VK_SUBTRACT = 0x6D # Subtract key
  83. VK_DECIMAL = 0x6E # Decimal key
  84. VK_DIVIDE = 0x6F # Divide key
  85. VK_F1 = 0x70 # F1 key
  86. VK_F2 = 0x71 # F2 key
  87. VK_F3 = 0x72 # F3 key
  88. VK_F4 = 0x73 # F4 key
  89. VK_F5 = 0x74 # F5 key
  90. VK_F6 = 0x75 # F6 key
  91. VK_F7 = 0x76 # F7 key
  92. VK_F8 = 0x77 # F8 key
  93. VK_F9 = 0x78 # F9 key
  94. VK_F10 = 0x79 # F10 key
  95. VK_F11 = 0x7A # F11 key
  96. VK_F12 = 0x7B # F12 key
  97. VK_F13 = 0x7C # F13 key
  98. VK_F14 = 0x7D # F14 key
  99. VK_F15 = 0x7E # F15 key
  100. VK_F16 = 0x7F # F16 key
  101. VK_F17 = 0x80 # F17 key
  102. VK_F18 = 0x81 # F18 key
  103. VK_F19 = 0x82 # F19 key
  104. VK_F20 = 0x83 # F20 key
  105. VK_F21 = 0x84 # F21 key
  106. VK_F22 = 0x85 # F22 key
  107. VK_F23 = 0x86 # F23 key
  108. VK_F24 = 0x87 # F24 key
  109. VK_NUMLOCK = 0x90 # NUM LOCK key
  110. VK_SCROLL = 0x91 # SCROLL LOCK key
  111. VK_LSHIFT = 0xA0 # Left SHIFT key
  112. VK_RSHIFT = 0xA1 # Right SHIFT key
  113. VK_LCONTROL = 0xA2 # Left CONTROL key
  114. VK_RCONTROL = 0xA3 # Right CONTROL key
  115. VK_LMENU = 0xA4 # Left MENU key
  116. VK_RMENU = 0xA5 # Right MENU key
  117. VK_BROWSER_BACK = 0xA6 # Browser Back key
  118. VK_BROWSER_FORWARD = 0xA7 # Browser Forward key
  119. VK_BROWSER_REFRESH = 0xA8 # Browser Refresh key
  120. VK_BROWSER_STOP = 0xA9 # Browser Stop key
  121. VK_BROWSER_SEARCH = 0xAA # Browser Search key
  122. VK_BROWSER_FAVORITES = 0xAB # Browser Favorites key
  123. VK_BROWSER_HOME = 0xAC # Browser Start and Home key
  124. VK_VOLUME_MUTE = 0xAD # Volume Mute key
  125. VK_VOLUME_DOWN = 0xAE # Volume Down key
  126. VK_VOLUME_UP = 0xAF # Volume Up key
  127. VK_MEDIA_NEXT_TRACK = 0xB0 # Next Track key
  128. VK_MEDIA_PREV_TRACK = 0xB1 # Previous Track key
  129. VK_MEDIA_STOP = 0xB2 # Stop Media key
  130. VK_MEDIA_PLAY_PAUSE = 0xB3 # Play/Pause Media key
  131. VK_LAUNCH_MAIL = 0xB4 # Start Mail key
  132. VK_LAUNCH_MEDIA_SELECT = 0xB5 # Select Media key
  133. VK_LAUNCH_APP1 = 0xB6 # Start Application 1 key
  134. VK_LAUNCH_APP2 = 0xB7 # Start Application 2 key
  135. VK_OEM_1 = 0xBA # Used for miscellaneous characters; it can vary by keyboard.
  136. # For the US standard keyboard, the ';:' key
  137. VK_OEM_PLUS = 0xBB # For any country/region, the '+' key
  138. VK_OEM_COMMA = 0xBC # For any country/region, the ',' key
  139. VK_OEM_MINUS = 0xBD # For any country/region, the '-' key
  140. VK_OEM_PERIOD = 0xBE # For any country/region, the '.' key
  141. VK_OEM_2 = 0xBF # Used for miscellaneous characters; it can vary by keyboard.
  142. # For the US standard keyboard, the '/?' key
  143. VK_OEM_3 = 0xC0 # Used for miscellaneous characters; it can vary by keyboard.
  144. # For the US standard keyboard, the '`~' key
  145. VK_OEM_4 = 0xDB # Used for miscellaneous characters; it can vary by keyboard.
  146. # For the US standard keyboard, the '[{' key
  147. VK_OEM_5 = 0xDC # Used for miscellaneous characters; it can vary by keyboard.
  148. # For the US standard keyboard, the '\|' key
  149. VK_OEM_6 = 0xDD # Used for miscellaneous characters; it can vary by keyboard.
  150. # For the US standard keyboard, the ']}' key
  151. VK_OEM_7 = 0xDE # Used for miscellaneous characters; it can vary by keyboard.
  152. # For the US standard keyboard, the 'single-quote/double-quote' key
  153. VK_OEM_8 = 0xDF # Used for miscellaneous characters; it can vary by keyboard.
  154. VK_OEM_102 = 0xE2 # Either the angle bracket key or the backslash key on the RT 102-key keyboard
  155. VK_PROCESSKEY = 0xE5 # IME PROCESS key
  156. VK_PACKET = 0xE7 # Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP
  157. VK_ATTN = 0xF6 # Attn key
  158. VK_CRSEL = 0xF7 # CrSel key
  159. VK_EXSEL = 0xF8 # ExSel key
  160. VK_EREOF = 0xF9 # Erase EOF key
  161. VK_PLAY = 0xFA # Play key
  162. VK_ZOOM = 0xFB # Zoom key
  163. VK_PA1 = 0xFD # PA1 key
  164. VK_OEM_CLEAR = 0xFE # Clear key
  165. KEYEVENTF_EXTENDEDKEY = 0x0001
  166. KEYEVENTF_KEYUP = 0x0002
  167. KEYEVENTF_SCANCODE = 0x0008
  168. KEYEVENTF_UNICODE = 0x0004
  169. KEY_0 = 0x30
  170. KEY_1 = 0x31
  171. KEY_2 = 0x32
  172. KEY_3 = 0x33
  173. KEY_4 = 0x34
  174. KEY_5 = 0x35
  175. KEY_6 = 0x36
  176. KEY_7 = 0x37
  177. KEY_8 = 0x38
  178. KEY_9 = 0x39
  179. KEY_A = 0x41
  180. KEY_B = 0x42
  181. KEY_C = 0x43
  182. KEY_D = 0x44
  183. KEY_E = 0x45
  184. KEY_F = 0x46
  185. KEY_G = 0x47
  186. KEY_H = 0x48
  187. KEY_I = 0x49
  188. KEY_J = 0x4A
  189. KEY_K = 0x4B
  190. KEY_L = 0x4C
  191. KEY_M = 0x4D
  192. KEY_N = 0x4E
  193. KEY_O = 0x4F
  194. KEY_P = 0x50
  195. KEY_Q = 0x51
  196. KEY_R = 0x52
  197. KEY_S = 0x53
  198. KEY_T = 0x54
  199. KEY_U = 0x55
  200. KEY_V = 0x56
  201. KEY_W = 0x57
  202. KEY_X = 0x58
  203. KEY_Y = 0x59
  204. KEY_Z = 0x5A
  205. class MOUSEINPUT(ctypes.Structure):
  206. _fields_ = (('dx', LONG),
  207. ('dy', LONG),
  208. ('mouseData', DWORD),
  209. ('dwFlags', DWORD),
  210. ('time', DWORD),
  211. ('dwExtraInfo', ULONG_PTR))
  212. class KEYBDINPUT(ctypes.Structure):
  213. _fields_ = (('wVk', WORD),
  214. ('wScan', WORD),
  215. ('dwFlags', DWORD),
  216. ('time', DWORD),
  217. ('dwExtraInfo', ULONG_PTR))
  218. class HARDWAREINPUT(ctypes.Structure):
  219. _fields_ = (('uMsg', DWORD),
  220. ('wParamL', WORD),
  221. ('wParamH', WORD))
  222. class _INPUTunion(ctypes.Union):
  223. _fields_ = (('mi', MOUSEINPUT),
  224. ('ki', KEYBDINPUT),
  225. ('hi', HARDWAREINPUT))
  226. class INPUT(ctypes.Structure):
  227. _fields_ = (('type', DWORD),
  228. ('union', _INPUTunion))
  229. def send_input(*inputs):
  230. nInputs = len(inputs)
  231. LPINPUT = INPUT * nInputs
  232. pInputs = LPINPUT(*inputs)
  233. cbSize = ctypes.c_int(ctypes.sizeof(INPUT))
  234. return ctypes.windll.user32.SendInput(nInputs, pInputs, cbSize)
  235. def input_structure(structure):
  236. if isinstance(structure, MOUSEINPUT):
  237. return INPUT(INPUT_MOUSE, _INPUTunion(mi=structure))
  238. if isinstance(structure, KEYBDINPUT):
  239. return INPUT(INPUT_KEYBOARD, _INPUTunion(ki=structure))
  240. if isinstance(structure, HARDWAREINPUT):
  241. return INPUT(INPUT_HARDWARE, _INPUTunion(hi=structure))
  242. raise TypeError('Cannot create INPUT structure!')
  243. def keyboard_input(code, flags):
  244. return KEYBDINPUT(0, code, flags, 0, None)
  245. def mouse_input(flags, x, y, data):
  246. return MOUSEINPUT(x, y, data, flags, 0, None)
  247. def hardware_input(message, parameter):
  248. return HARDWAREINPUT(message & 0xFFFFFFFF,
  249. parameter & 0xFFFF,
  250. parameter >> 16 & 0xFFFF)
  251. def Mouse(flags, x=0, y=0, data=0):
  252. return input_structure(mouse_input(flags, x, y, data))
  253. def Keyboard(code, flags=0):
  254. return input_structure(keyboard_input(code, flags))
  255. def Hardware(message, parameter=0):
  256. return input_structure(hardware_input(message, parameter))
  257. class WindowMgr:
  258. """Encapsulates some calls to the winapi for window management"""
  259. BLACK_BRUSH = 4
  260. CS_HREDRAW = 2
  261. CS_VREDRAW = 1
  262. PM_NOREMOVE = 0
  263. SM_CXSCREEN = 0
  264. SM_CYSCREEN = 1
  265. SW_SHOW = 5
  266. SW_SHOWNORMAL = 1
  267. SWP_NOMOVE = 2
  268. SWP_NOSIZE = 1
  269. WM_CLOSE = 16
  270. WM_DESTROY = 2
  271. WM_KEYDOWN = 256
  272. WM_KEYUP = 257
  273. WM_CHAR = 0x0102
  274. WM_LBUTTONDOWN = 513
  275. WM_MBUTTONDOWN = 519
  276. WM_MOUSEMOVE = 512
  277. WM_PAINT = 15
  278. WM_QUIT = 18
  279. WM_RBUTTONDOWN = 516
  280. WS_EX_TOPMOST = 8
  281. WS_POPUP = 0x80000000
  282. WS_VISIBLE = 0x10000000
  283. def __init__ (self):
  284. """Constructor"""
  285. self._handle = None
  286. def ZeroChk (self, result):
  287. if result == 0:
  288. print(result)
  289. raise ctypes.WinError(ctypes.windll.kernel32.GetLastError())
  290. return result
  291. def find_window(self, class_name, window_name = None):
  292. """find a window by its class_name"""
  293. self._handle = ctypes.windll.user32.FindWindow(class_name, window_name)
  294. def _window_enum_callback(self, hwnd, wildcard):
  295. wildcard = ctypes.cast(wildcard, ctypes.c_wchar_p).value.encode('utf-8', 'replace')
  296. length = ctypes.windll.user32.GetWindowTextLengthW(hwnd) + 1
  297. buff = ctypes.create_unicode_buffer(length)
  298. ctypes.windll.user32.GetWindowTextW(hwnd, buff, length)
  299. wintitle = ctypes.cast(buff, ctypes.c_wchar_p).value.encode('utf-8', 'replace')
  300. #print("len =", length, repr(buff.value))
  301. #if re.search(wildcard, wintitle) is not None:
  302. if wintitle.endswith(wildcard):
  303. #print(repr(buff.value))
  304. self._handle = hwnd
  305. return True
  306. else:
  307. return False
  308. def find_window_wildcard(self, wildcard):
  309. self._handle = None
  310. enum_windows_proc = \
  311. ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
  312. self.ZeroChk(ctypes.windll.user32.EnumWindows(enum_windows_proc(self._window_enum_callback), wildcard))
  313. def set_foreground(self):
  314. """put the window in the foreground"""
  315. ctypes.windll.user32.ShowWindow(self._handle, self.SW_SHOWNORMAL);
  316. ctypes.windll.user32.BringWindowToTop(self._handle);
  317. self.ZeroChk(ctypes.windll.user32.SetForegroundWindow(self._handle))
  318. def send_keypress(self, vkCode, flags=0):
  319. hwnd = self._handle
  320. #keyState = ctypes.windll.user32.GetAsyncKeyState(vkCode)
  321. if vkCode==0x101:
  322. lParam = 0x31
  323. else:
  324. lParam = 0
  325. #hwnd = ctypes.windll.user32.GetForegroundWindow()
  326. #print("hwnd:", hwnd, "self:", ctypes.cast(self._handle, ctypes.c_void_p).value)
  327. #print("key state: ",keyState)
  328. self.ZeroChk(ctypes.windll.user32.PostMessageW(hwnd, flags, vkCode, lParam))
  329. #self.ZeroChk(ctypes.windll.user32.PostMessageW(hwnd, self.WM_CHAR, code, ctypes.windll.user32.MapVirtualKeyW(code, 1)))
  330. #time.sleep(0.1)
  331. #self.ZeroChk(ctypes.windll.user32.PostMessageW(hwnd, self.WM_KEYUP, code, 65539) - 1)
  332. def main():
  333. args = parser.parse_args()
  334. w = WindowMgr()
  335. w.find_window_wildcard(args.title) #"Deus Ex: Revision"
  336. w.set_foreground()
  337. delay = 10
  338. try:
  339. file = open(args.file, 'r')
  340. for line in file.readlines():
  341. if line.startswith(("#",",",":","/n")): continue
  342. evt,flags,data,hold = line.split(",")
  343. sdata = data.split(":")
  344. if int(evt, 16)==INPUT_MOUSE:
  345. for x,y,code in sdata:
  346. print(x,y,code)
  347. time.sleep(int(delay)/1000)
  348. elif int(evt, 16)==INPUT_KEYBOARD:
  349. for code in sdata:
  350. print(code, flags)
  351. #send_input(Keyboard(int(code,16),int(flags,16)-0x100))
  352. w.send_keypress(int(code,16), int(flags,16))
  353. time.sleep(int(delay)/1000)
  354. time.sleep(int(hold)/1000)
  355. finally:
  356. file.close()
  357. if __name__ == '__main__':
  358. main()