short summary:
I am trying to create a program that will send keyboard events to the computer that for all purposes the simulated events should be t
Every platform is going to have a different approach to being able to generate keyboard events. This is because they each need to make use of system libraries (and system extensions). For a cross platform solution, you would need to take each of these solutions and wrap then into a platform check to perform the proper approach.
For windows, you might be able to use the pywin32 extension. win32api.keybd_event
win32api.keybd_event
keybd_event(bVk, bScan, dwFlags, dwExtraInfo)
Simulate a keyboard event
Parameters
bVk : BYTE - Virtual-key code
bScan : BYTE - Hardware scan code
dwFlags=0 : DWORD - Flags specifying various function options
dwExtraInfo=0 : DWORD - Additional data associated with keystroke
You will need to investigate pywin32 for how to properly use it, as I have never used it.
Windows only: You can either use Ironpython or a library that allows cPython to access the .NET frameworks on Windows. Then use the sendkeys class of .NET or the more general send to simulate a keystroke.
OS X only: Use PyObjC then use use CGEventCreateKeyboardEvent
call.
Full disclosure: I have only done this on OS X with Python, but I have used .NET sendkeys (with C#) and that works great.
I had this same problem and made my own library for it that uses ctypes:
"""
< --- CTRL by [object Object] --- >
Only works on windows.
Some characters only work with a US standard keyboard.
Some parts may also only work in python 32-bit.
"""
#--- Setup ---#
from ctypes import *
from time import sleep
user32 = windll.user32
kernel32 = windll.kernel32
delay = 0.01
####################################
###---KEYBOARD CONTROL SECTION---###
####################################
#--- Key Code Variables ---#
class key:
cancel = 0x03
backspace = 0x08
tab = 0x09
enter = 0x0D
shift = 0x10
ctrl = 0x11
alt = 0x12
capslock = 0x14
esc = 0x1B
space = 0x20
pgup = 0x21
pgdown = 0x22
end = 0x23
home = 0x24
leftarrow = 0x26
uparrow = 0x26
rightarrow = 0x27
downarrow = 0x28
select = 0x29
print = 0x2A
execute = 0x2B
printscreen = 0x2C
insert = 0x2D
delete = 0x2E
help = 0x2F
num0 = 0x30
num1 = 0x31
num2 = 0x32
num3 = 0x33
num4 = 0x34
num5 = 0x35
num6 = 0x36
num7 = 0x37
num8 = 0x38
num9 = 0x39
a = 0x41
b = 0x42
c = 0x43
d = 0x44
e = 0x45
f = 0x46
g = 0x47
h = 0x48
i = 0x49
j = 0x4A
k = 0x4B
l = 0x4C
m = 0x4D
n = 0x4E
o = 0x4F
p = 0x50
q = 0x51
r = 0x52
s = 0x53
t = 0x54
u = 0x55
v = 0x56
w = 0x57
x = 0x58
y = 0x59
z = 0x5A
leftwin = 0x5B
rightwin = 0x5C
apps = 0x5D
sleep = 0x5F
numpad0 = 0x60
numpad1 = 0x61
numpad3 = 0x63
numpad4 = 0x64
numpad5 = 0x65
numpad6 = 0x66
numpad7 = 0x67
numpad8 = 0x68
numpad9 = 0x69
multiply = 0x6A
add = 0x6B
seperator = 0x6C
subtract = 0x6D
decimal = 0x6E
divide = 0x6F
F1 = 0x70
F2 = 0x71
F3 = 0x72
F4 = 0x73
F5 = 0x74
F6 = 0x75
F7 = 0x76
F8 = 0x77
F9 = 0x78
F10 = 0x79
F11 = 0x7A
F12 = 0x7B
F13 = 0x7C
F14 = 0x7D
F15 = 0x7E
F16 = 0x7F
F17 = 0x80
F19 = 0x82
F20 = 0x83
F21 = 0x84
F22 = 0x85
F23 = 0x86
F24 = 0x87
numlock = 0x90
scrolllock = 0x91
leftshift = 0xA0
rightshift = 0xA1
leftctrl = 0xA2
rightctrl = 0xA3
leftmenu = 0xA4
rightmenu = 0xA5
browserback = 0xA6
browserforward = 0xA7
browserrefresh = 0xA8
browserstop = 0xA9
browserfavories = 0xAB
browserhome = 0xAC
volumemute = 0xAD
volumedown = 0xAE
volumeup = 0xAF
nexttrack = 0xB0
prevoustrack = 0xB1
stopmedia = 0xB2
playpause = 0xB3
launchmail = 0xB4
selectmedia = 0xB5
launchapp1 = 0xB6
launchapp2 = 0xB7
semicolon = 0xBA
equals = 0xBB
comma = 0xBC
dash = 0xBD
period = 0xBE
slash = 0xBF
accent = 0xC0
openingsquarebracket = 0xDB
backslash = 0xDC
closingsquarebracket = 0xDD
quote = 0xDE
play = 0xFA
zoom = 0xFB
PA1 = 0xFD
clear = 0xFE
#--- Keyboard Control Functions ---#
# Category variables
letters = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
shiftsymbols = "~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?"
# Presses and releases the key
def press(key):
user32.keybd_event(key, 0, 0, 0)
sleep(delay)
user32.keybd_event(key, 0, 2, 0)
sleep(delay)
# Holds a key
def hold(key):
user32.keybd_event(key, 0, 0, 0)
sleep(delay)
# Releases a key
def release(key):
user32.keybd_event(key, 0, 2, 0)
sleep(delay)
# Types out a string
def typestr(sentence):
for letter in sentence:
shift = letter in shiftsymbols
fixedletter = "space"
if letter == "`" or letter == "~":
fixedletter = "accent"
elif letter == "1" or letter == "!":
fixedletter = "num1"
elif letter == "2" or letter == "@":
fixedletter = "num2"
elif letter == "3" or letter == "#":
fixedletter = "num3"
elif letter == "4" or letter == "$":
fixedletter = "num4"
elif letter == "5" or letter == "%":
fixedletter = "num5"
elif letter == "6" or letter == "^":
fixedletter = "num6"
elif letter == "7" or letter == "&":
fixedletter = "num7"
elif letter == "8" or letter == "*":
fixedletter = "num8"
elif letter == "9" or letter == "(":
fixedletter = "num9"
elif letter == "0" or letter == ")":
fixedletter = "num0"
elif letter == "-" or letter == "_":
fixedletter = "dash"
elif letter == "=" or letter == "+":
fixedletter = "equals"
elif letter in letters:
fixedletter = letter.lower()
elif letter == "[" or letter == "{":
fixedletter = "openingsquarebracket"
elif letter == "]" or letter == "}":
fixedletter = "closingsquarebracket"
elif letter == "\\" or letter == "|":
fixedletter == "backslash"
elif letter == ";" or letter == ":":
fixedletter = "semicolon"
elif letter == "'" or letter == "\"":
fixedletter = "quote"
elif letter == "," or letter == "<":
fixedletter = "comma"
elif letter == "." or letter == ">":
fixedletter = "period"
elif letter == "/" or letter == "?":
fixedletter = "slash"
elif letter == "\n":
fixedletter = "enter"
keytopress = eval("key." + str(fixedletter))
if shift:
hold(key.shift)
press(keytopress)
release(key.shift)
else:
press(keytopress)
#--- Mouse Variables ---#
class mouse:
left = [0x0002, 0x0004]
right = [0x0008, 0x00010]
middle = [0x00020, 0x00040]
#--- Mouse Control Functions ---#
# Moves mouse to a position
def move(x, y):
user32.SetCursorPos(x, y)
# Presses and releases mouse
def click(button):
user32.mouse_event(button[0], 0, 0, 0, 0)
sleep(delay)
user32.mouse_event(button[1], 0, 0, 0, 0)
sleep(delay)
# Holds a mouse button
def holdclick(button):
user32.mouse_event(button[0], 0, 0, 0, 0)
sleep(delay)
# Releases a mouse button
def releaseclick(button):
user32.mouse_event(button[1])
sleep(delay)
user648852's idea at least for me works great for OS X, here is the code to do it:
#!/usr/bin/env python
import time
from Quartz.CoreGraphics import CGEventCreateKeyboardEvent
from Quartz.CoreGraphics import CGEventPost
# Python releases things automatically, using CFRelease will result in a scary error
#from Quartz.CoreGraphics import CFRelease
from Quartz.CoreGraphics import kCGHIDEventTap
# From http://stackoverflow.com/questions/281133/controlling-the-mouse-from-python-in-os-x
# and from https://developer.apple.com/library/mac/documentation/Carbon/Reference/QuartzEventServicesRef/index.html#//apple_ref/c/func/CGEventCreateKeyboardEvent
def KeyDown(k):
keyCode, shiftKey = toKeyCode(k)
time.sleep(0.0001)
if shiftKey:
CGEventPost(kCGHIDEventTap, CGEventCreateKeyboardEvent(None, 0x38, True))
time.sleep(0.0001)
CGEventPost(kCGHIDEventTap, CGEventCreateKeyboardEvent(None, keyCode, True))
time.sleep(0.0001)
if shiftKey:
CGEventPost(kCGHIDEventTap, CGEventCreateKeyboardEvent(None, 0x38, False))
time.sleep(0.0001)
def KeyUp(k):
keyCode, shiftKey = toKeyCode(k)
time.sleep(0.0001)
CGEventPost(kCGHIDEventTap, CGEventCreateKeyboardEvent(None, keyCode, False))
time.sleep(0.0001)
def KeyPress(k):
keyCode, shiftKey = toKeyCode(k)
time.sleep(0.0001)
if shiftKey:
CGEventPost(kCGHIDEventTap, CGEventCreateKeyboardEvent(None, 0x38, True))
time.sleep(0.0001)
CGEventPost(kCGHIDEventTap, CGEventCreateKeyboardEvent(None, keyCode, True))
time.sleep(0.0001)
CGEventPost(kCGHIDEventTap, CGEventCreateKeyboardEvent(None, keyCode, False))
time.sleep(0.0001)
if shiftKey:
CGEventPost(kCGHIDEventTap, CGEventCreateKeyboardEvent(None, 0x38, False))
time.sleep(0.0001)
# From http://stackoverflow.com/questions/3202629/where-can-i-find-a-list-of-mac-virtual-key-codes
def toKeyCode(c):
shiftKey = False
# Letter
if c.isalpha():
if not c.islower():
shiftKey = True
c = c.lower()
if c in shiftChars:
shiftKey = True
c = shiftChars[c]
if c in keyCodeMap:
keyCode = keyCodeMap[c]
else:
keyCode = ord(c)
return keyCode, shiftKey
shiftChars = {
'~': '`',
'!': '1',
'@': '2',
'#': '3',
'$': '4',
'%': '5',
'^': '6',
'&': '7',
'*': '8',
'(': '9',
')': '0',
'_': '-',
'+': '=',
'{': '[',
'}': ']',
'|': '\\',
':': ';',
'"': '\'',
'<': ',',
'>': '.',
'?': '/'
}
keyCodeMap = {
'a' : 0x00,
's' : 0x01,
'd' : 0x02,
'f' : 0x03,
'h' : 0x04,
'g' : 0x05,
'z' : 0x06,
'x' : 0x07,
'c' : 0x08,
'v' : 0x09,
'b' : 0x0B,
'q' : 0x0C,
'w' : 0x0D,
'e' : 0x0E,
'r' : 0x0F,
'y' : 0x10,
't' : 0x11,
'1' : 0x12,
'2' : 0x13,
'3' : 0x14,
'4' : 0x15,
'6' : 0x16,
'5' : 0x17,
'=' : 0x18,
'9' : 0x19,
'7' : 0x1A,
'-' : 0x1B,
'8' : 0x1C,
'0' : 0x1D,
']' : 0x1E,
'o' : 0x1F,
'u' : 0x20,
'[' : 0x21,
'i' : 0x22,
'p' : 0x23,
'l' : 0x25,
'j' : 0x26,
'\'' : 0x27,
'k' : 0x28,
';' : 0x29,
'\\' : 0x2A,
',' : 0x2B,
'/' : 0x2C,
'n' : 0x2D,
'm' : 0x2E,
'.' : 0x2F,
'`' : 0x32,
'k.' : 0x41,
'k*' : 0x43,
'k+' : 0x45,
'kclear' : 0x47,
'k/' : 0x4B,
'k\n' : 0x4C,
'k-' : 0x4E,
'k=' : 0x51,
'k0' : 0x52,
'k1' : 0x53,
'k2' : 0x54,
'k3' : 0x55,
'k4' : 0x56,
'k5' : 0x57,
'k6' : 0x58,
'k7' : 0x59,
'k8' : 0x5B,
'k9' : 0x5C,
# keycodes for keys that are independent of keyboard layout
'\n' : 0x24,
'\t' : 0x30,
' ' : 0x31,
'del' : 0x33,
'delete' : 0x33,
'esc' : 0x35,
'escape' : 0x35,
'cmd' : 0x37,
'command' : 0x37,
'shift' : 0x38,
'caps lock' : 0x39,
'option' : 0x3A,
'ctrl' : 0x3B,
'control' : 0x3B,
'right shift' : 0x3C,
'rshift' : 0x3C,
'right option' : 0x3D,
'roption' : 0x3D,
'right control' : 0x3E,
'rcontrol' : 0x3E,
'fun' : 0x3F,
'function' : 0x3F,
'f17' : 0x40,
'volume up' : 0x48,
'volume down' : 0x49,
'mute' : 0x4A,
'f18' : 0x4F,
'f19' : 0x50,
'f20' : 0x5A,
'f5' : 0x60,
'f6' : 0x61,
'f7' : 0x62,
'f3' : 0x63,
'f8' : 0x64,
'f9' : 0x65,
'f11' : 0x67,
'f13' : 0x69,
'f16' : 0x6A,
'f14' : 0x6B,
'f10' : 0x6D,
'f12' : 0x6F,
'f15' : 0x71,
'help' : 0x72,
'home' : 0x73,
'pgup' : 0x74,
'page up' : 0x74,
'forward delete' : 0x75,
'f4' : 0x76,
'end' : 0x77,
'f2' : 0x78,
'page down' : 0x79,
'pgdn' : 0x79,
'f1' : 0x7A,
'left' : 0x7B,
'right' : 0x7C,
'down' : 0x7D,
'up' : 0x7E
}
def keyboardevent():
keyboard.press_and_release('a')
keyboard.press_and_release('shift + b')
keyboardevent()
It can be done using ctypes:
import ctypes
from ctypes import wintypes
import time
user32 = ctypes.WinDLL('user32', use_last_error=True)
INPUT_MOUSE = 0
INPUT_KEYBOARD = 1
INPUT_HARDWARE = 2
KEYEVENTF_EXTENDEDKEY = 0x0001
KEYEVENTF_KEYUP = 0x0002
KEYEVENTF_UNICODE = 0x0004
KEYEVENTF_SCANCODE = 0x0008
MAPVK_VK_TO_VSC = 0
# msdn.microsoft.com/en-us/library/dd375731
VK_TAB = 0x09
VK_MENU = 0x12
# C struct definitions
wintypes.ULONG_PTR = wintypes.WPARAM
class MOUSEINPUT(ctypes.Structure):
_fields_ = (("dx", wintypes.LONG),
("dy", wintypes.LONG),
("mouseData", wintypes.DWORD),
("dwFlags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", wintypes.ULONG_PTR))
class KEYBDINPUT(ctypes.Structure):
_fields_ = (("wVk", wintypes.WORD),
("wScan", wintypes.WORD),
("dwFlags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", wintypes.ULONG_PTR))
def __init__(self, *args, **kwds):
super(KEYBDINPUT, self).__init__(*args, **kwds)
# some programs use the scan code even if KEYEVENTF_SCANCODE
# isn't set in dwFflags, so attempt to map the correct code.
if not self.dwFlags & KEYEVENTF_UNICODE:
self.wScan = user32.MapVirtualKeyExW(self.wVk,
MAPVK_VK_TO_VSC, 0)
class HARDWAREINPUT(ctypes.Structure):
_fields_ = (("uMsg", wintypes.DWORD),
("wParamL", wintypes.WORD),
("wParamH", wintypes.WORD))
class INPUT(ctypes.Structure):
class _INPUT(ctypes.Union):
_fields_ = (("ki", KEYBDINPUT),
("mi", MOUSEINPUT),
("hi", HARDWAREINPUT))
_anonymous_ = ("_input",)
_fields_ = (("type", wintypes.DWORD),
("_input", _INPUT))
LPINPUT = ctypes.POINTER(INPUT)
def _check_count(result, func, args):
if result == 0:
raise ctypes.WinError(ctypes.get_last_error())
return args
user32.SendInput.errcheck = _check_count
user32.SendInput.argtypes = (wintypes.UINT, # nInputs
LPINPUT, # pInputs
ctypes.c_int) # cbSize
# Functions
def PressKey(hexKeyCode):
x = INPUT(type=INPUT_KEYBOARD,
ki=KEYBDINPUT(wVk=hexKeyCode))
user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))
def ReleaseKey(hexKeyCode):
x = INPUT(type=INPUT_KEYBOARD,
ki=KEYBDINPUT(wVk=hexKeyCode,
dwFlags=KEYEVENTF_KEYUP))
user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))
def AltTab():
"""Press Alt+Tab and hold Alt key for 2 seconds
in order to see the overlay.
"""
PressKey(VK_MENU) # Alt
PressKey(VK_TAB) # Tab
ReleaseKey(VK_TAB) # Tab~
time.sleep(2)
ReleaseKey(VK_MENU) # Alt~
if __name__ == "__main__":
AltTab()
hexKeyCode
is the virtual keyboard mapping as defined by the Windows API. The list of codes is available on MSDN: Virtual-Key Codes (Windows)