import cpyHook def GetKeyState(key_id): return cpyHook.cGetKeyState(key_id) class HookConstants: ''' Stores internal windows hook constants including hook types, mappings from virtual keycode name to value and value to name, and event type value to name. ''' WH_MIN = -1 WH_MSGFILTER = -1 WH_JOURNALRECORD = 0 WH_JOURNALPLAYBACK = 1 WH_KEYBOARD = 2 WH_GETMESSAGE = 3 WH_CALLWNDPROC = 4 WH_CBT = 5 WH_SYSMSGFILTER = 6 WH_MOUSE = 7 WH_HARDWARE = 8 WH_DEBUG = 9 WH_SHELL = 10 WH_FOREGROUNDIDLE = 11 WH_CALLWNDPROCRET = 12 WH_KEYBOARD_LL = 13 WH_MOUSE_LL = 14 WH_MAX = 15 WM_MOUSEFIRST = 0x0200 WM_MOUSEMOVE = 0x0200 WM_LBUTTONDOWN = 0x0201 WM_LBUTTONUP = 0x0202 WM_LBUTTONDBLCLK = 0x0203 WM_RBUTTONDOWN =0x0204 WM_RBUTTONUP = 0x0205 WM_RBUTTONDBLCLK = 0x0206 WM_MBUTTONDOWN = 0x0207 WM_MBUTTONUP = 0x0208 WM_MBUTTONDBLCLK = 0x0209 WM_MOUSEWHEEL = 0x020A WM_MOUSELAST = 0x020A WM_KEYFIRST = 0x0100 WM_KEYDOWN = 0x0100 WM_KEYUP = 0x0101 WM_CHAR = 0x0102 WM_DEADCHAR = 0x0103 WM_SYSKEYDOWN = 0x0104 WM_SYSKEYUP = 0x0105 WM_SYSCHAR = 0x0106 WM_SYSDEADCHAR = 0x0107 WM_KEYLAST = 0x0108 #VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 -' : 0x39) #VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 -' : 0x5A) #virtual keycode constant names to virtual keycodes numerical id vk_to_id = {'VK_LBUTTON' : 0x01, 'VK_RBUTTON' : 0x02, 'VK_CANCEL' : 0x03, 'VK_MBUTTON' : 0x04, 'VK_BACK' : 0x08, 'VK_TAB' : 0x09, 'VK_CLEAR' : 0x0C, 'VK_RETURN' : 0x0D, 'VK_SHIFT' : 0x10, 'VK_CONTROL' : 0x11, 'VK_MENU' : 0x12, 'VK_PAUSE' : 0x13, 'VK_CAPITAL' : 0x14, 'VK_KANA' : 0x15, 'VK_HANGEUL' : 0x15, 'VK_HANGUL' : 0x15, 'VK_JUNJA' : 0x17, 'VK_FINAL' : 0x18, 'VK_HANJA' : 0x19, 'VK_KANJI' : 0x19, 'VK_ESCAPE' : 0x1B, 'VK_CONVERT' : 0x1C, 'VK_NONCONVERT' : 0x1D, 'VK_ACCEPT' : 0x1E, 'VK_MODECHANGE' : 0x1F, 'VK_SPACE' : 0x20, 'VK_PRIOR' : 0x21, 'VK_NEXT' : 0x22, 'VK_END' : 0x23, 'VK_HOME' : 0x24, 'VK_LEFT' : 0x25, 'VK_UP' : 0x26, 'VK_RIGHT' : 0x27, 'VK_DOWN' : 0x28, 'VK_SELECT' : 0x29, 'VK_PRINT' : 0x2A, 'VK_EXECUTE' : 0x2B, 'VK_SNAPSHOT' : 0x2C, 'VK_INSERT' : 0x2D, 'VK_DELETE' : 0x2E, 'VK_HELP' : 0x2F, 'VK_LWIN' : 0x5B, 'VK_RWIN' : 0x5C, 'VK_APPS' : 0x5D, 'VK_NUMPAD0' : 0x60, 'VK_NUMPAD1' : 0x61, 'VK_NUMPAD2' : 0x62, 'VK_NUMPAD3' : 0x63, 'VK_NUMPAD4' : 0x64, 'VK_NUMPAD5' : 0x65, 'VK_NUMPAD6' : 0x66, 'VK_NUMPAD7' : 0x67, 'VK_NUMPAD8' : 0x68, 'VK_NUMPAD9' : 0x69, 'VK_MULTIPLY' : 0x6A, 'VK_ADD' : 0x6B, 'VK_SEPARATOR' : 0x6C, 'VK_SUBTRACT' : 0x6D, 'VK_DECIMAL' : 0x6E, 'VK_DIVIDE' : 0x6F ,'VK_F1' : 0x70, 'VK_F2' : 0x71, 'VK_F3' : 0x72, 'VK_F4' : 0x73, 'VK_F5' : 0x74, 'VK_F6' : 0x75, 'VK_F7' : 0x76, 'VK_F8' : 0x77, 'VK_F9' : 0x78, 'VK_F10' : 0x79, 'VK_F11' : 0x7A, 'VK_F12' : 0x7B, 'VK_F13' : 0x7C, 'VK_F14' : 0x7D, 'VK_F15' : 0x7E, 'VK_F16' : 0x7F, 'VK_F17' : 0x80, 'VK_F18' : 0x81, 'VK_F19' : 0x82, 'VK_F20' : 0x83, 'VK_F21' : 0x84, 'VK_F22' : 0x85, 'VK_F23' : 0x86, 'VK_F24' : 0x87, 'VK_NUMLOCK' : 0x90, 'VK_SCROLL' : 0x91, 'VK_LSHIFT' : 0xA0, 'VK_RSHIFT' : 0xA1, 'VK_LCONTROL' : 0xA2, 'VK_RCONTROL' : 0xA3, 'VK_LMENU' : 0xA4, 'VK_RMENU' : 0xA5, 'VK_PROCESSKEY' : 0xE5, 'VK_ATTN' : 0xF6, 'VK_CRSEL' : 0xF7, 'VK_EXSEL' : 0xF8, 'VK_EREOF' : 0xF9, 'VK_PLAY' : 0xFA, 'VK_ZOOM' : 0xFB, 'VK_NONAME' : 0xFC, 'VK_PA1' : 0xFD, 'VK_OEM_CLEAR' : 0xFE, 'VK_BROWSER_BACK' : 0xA6, 'VK_BROWSER_FORWARD' : 0xA7, 'VK_BROWSER_REFRESH' : 0xA8, 'VK_BROWSER_STOP' : 0xA9, 'VK_BROWSER_SEARCH' : 0xAA, 'VK_BROWSER_FAVORITES' : 0xAB, 'VK_BROWSER_HOME' : 0xAC, 'VK_VOLUME_MUTE' : 0xAD, 'VK_VOLUME_DOWN' : 0xAE, 'VK_VOLUME_UP' : 0xAF, 'VK_MEDIA_NEXT_TRACK' : 0xB0, 'VK_MEDIA_PREV_TRACK' : 0xB1, 'VK_MEDIA_STOP' : 0xB2, 'VK_MEDIA_PLAY_PAUSE' : 0xB3, 'VK_LAUNCH_MAIL' : 0xB4, 'VK_LAUNCH_MEDIA_SELECT' : 0xB5, 'VK_LAUNCH_APP1' : 0xB6, 'VK_LAUNCH_APP2' : 0xB7, 'VK_OEM_1' : 0xBA, 'VK_OEM_PLUS' : 0xBB, 'VK_OEM_COMMA' : 0xBC, 'VK_OEM_MINUS' : 0xBD, 'VK_OEM_PERIOD' : 0xBE, 'VK_OEM_2' : 0xBF, 'VK_OEM_3' : 0xC0, 'VK_OEM_4' : 0xDB, 'VK_OEM_5' : 0xDC, 'VK_OEM_6' : 0xDD, 'VK_OEM_7' : 0xDE, 'VK_OEM_8' : 0xDF, 'VK_OEM_102' : 0xE2, 'VK_PROCESSKEY' : 0xE5, 'VK_PACKET' : 0xE7} #inverse mapping of keycodes id_to_vk = dict([(v,k) for k,v in vk_to_id.items()]) #message constants to message names msg_to_name = {WM_MOUSEMOVE : 'mouse move', WM_LBUTTONDOWN : 'mouse left down', WM_LBUTTONUP : 'mouse left up', WM_LBUTTONDBLCLK : 'mouse left double', WM_RBUTTONDOWN : 'mouse right down', WM_RBUTTONUP : 'mouse right up', WM_RBUTTONDBLCLK : 'mouse right double', WM_MBUTTONDOWN : 'mouse middle down', WM_MBUTTONUP : 'mouse middle up', WM_MBUTTONDBLCLK : 'mouse middle double', WM_MOUSEWHEEL : 'mouse wheel', WM_KEYDOWN : 'key down', WM_KEYUP : 'key up', WM_CHAR : 'key char', WM_DEADCHAR : 'key dead char', WM_SYSKEYDOWN : 'key sys down', WM_SYSKEYUP : 'key sys up', WM_SYSCHAR : 'key sys char', WM_SYSDEADCHAR : 'key sys dead char'} def MsgToName(cls, msg): ''' Class method. Converts a message value to message name. @param msg: Keyboard or mouse event message @type msg: integer @return: Name of the event @rtype: string ''' return HookConstants.msg_to_name.get(msg) def VKeyToID(cls, vkey): ''' Class method. Converts a virtual keycode name to its value. @param vkey: Virtual keycode name @type vkey: string @return: Virtual keycode value @rtype: integer ''' return HookConstants.vk_to_id.get(vkey) def IDToName(cls, code): ''' Class method. Gets the keycode name for the given value. @param code: Virtual keycode value @type code: integer @return: Virtual keycode name @rtype: string ''' if (code >= 0x30 and code <= 0x39) or (code >= 0x41 and code <= 0x5A): text = chr(code) else: text = HookConstants.id_to_vk.get(code) if text is not None: text = text[3:].title() return text MsgToName=classmethod(MsgToName) IDToName=classmethod(IDToName) VKeyToID=classmethod(VKeyToID) class HookEvent(object): ''' Holds information about a general hook event. @ivar Message: Keyboard or mouse event message @type Message: integer @ivar Time: Seconds since the epoch when the even current @type Time: integer @ivar Window: Window handle of the foreground window at the time of the event @type Window: integer @ivar WindowName: Name of the foreground window at the time of the event @type WindowName: string ''' def __init__(self, msg, time, hwnd, window_name): '''Initializes an event instance.''' self.Message = msg self.Time = time self.Window = hwnd self.WindowName = window_name def GetMessageName(self): ''' @return: Name of the event @rtype: string ''' return HookConstants.MsgToName(self.Message) MessageName = property(fget=GetMessageName) class MouseEvent(HookEvent): ''' Holds information about a mouse event. @ivar Position: Location of the mouse event on the screen @type Position: 2-tuple of integer @ivar Wheel: Positive if the wheel scrolls up, negative if down, zero otherwise @type Wheel: integer @ivar Injected: Was this event generated programmatically? @type Injected: boolean ''' def __init__(self, msg, x, y, data, flags, time, hwnd, window_name): '''Initializes an instance of the class.''' HookEvent.__init__(self, msg, time, hwnd, window_name) self.Position = (x,y) if data > 0: w = 1 elif data < 0: w = -1 else: w = 0 self.Wheel = w self.Injected = flags & 0x01 class KeyboardEvent(HookEvent): ''' Holds information about a mouse event. @ivar KeyID: Virtual key code @type KeyID: integer @ivar ScanCode: Scan code @type ScanCode: integer @ivar Ascii: ASCII value, if one exists @type Ascii: string ''' def __init__(self, msg, vk_code, scan_code, ascii, flags, time, hwnd, window_name): '''Initializes an instances of the class.''' HookEvent.__init__(self, msg, time, hwnd, window_name) self.KeyID = vk_code self.ScanCode = scan_code self.Ascii = ascii self.flags = flags def GetKey(self): ''' @return: Name of the virtual keycode @rtype: string ''' return HookConstants.IDToName(self.KeyID) def IsExtended(self): ''' @return: Is this an extended key? @rtype: boolean ''' return self.flags & 0x01 def IsInjected(self): ''' @return: Was this event generated programmatically? @rtype: boolean ''' return self.flags & 0x10 def IsAlt(self): ''' @return: Was the alt key depressed? @rtype: boolean ''' return self.flags & 0x20 def IsTransition(self): ''' @return: Is this a transition from up to down or vice versa? @rtype: boolean ''' return self.flags & 0x80 Key = property(fget=GetKey) Extended = property(fget=IsExtended) Injected = property(fget=IsInjected) Alt = property(fget=IsAlt) Transition = property(fget=IsTransition) class HookManager(object): ''' Registers and manages callbacks for low level mouse and keyboard events. @ivar mouse_funcs: Callbacks for mouse events @type mouse_funcs: dictionary @ivar keyboard_funcs: Callbacks for keyboard events @type keyboard_funcs: dictionary @ivar mouse_hook: Is a mouse hook set? @type mouse_hook: boolean @ivar key_hook: Is a keyboard hook set? @type key_hook: boolean ''' def __init__(self): '''Initializes an instance by setting up an empty set of handlers.''' self.mouse_funcs = {} self.keyboard_funcs = {} self.mouse_hook = False self.key_hook = False def __del__(self): '''Unhook all registered hooks.''' self.UnhookMouse() self.UnhookKeyboard() def HookMouse(self): '''Begins watching for mouse events.''' cpyHook.cSetHook(HookConstants.WH_MOUSE_LL, self.MouseSwitch) self.mouse_hook = True def HookKeyboard(self): '''Begins watching for keyboard events.''' cpyHook.cSetHook(HookConstants.WH_KEYBOARD_LL, self.KeyboardSwitch) self.keyboard_hook = True def UnhookMouse(self): '''Stops watching for mouse events.''' if self.mouse_hook: cpyHook.cUnhook(HookConstants.WH_MOUSE_LL) self.mouse_hook = False def UnhookKeyboard(self): '''Stops watching for keyboard events.''' if self.keyboard_hook: cpyHook.cUnhook(HookConstants.WH_KEYBOARD_LL) self.keyboard_hook = False def MouseSwitch(self, msg, x, y, data, flags, time, hwnd, window_name): ''' Passes a mouse event on to the appropriate handler if one is registered. @param msg: Message value @type msg: integer @param x: x-coordinate of the mouse event @type x: integer @param y: y-coordinate of the mouse event @type y: integer @param data: Data associated with the mouse event (scroll information) @type data: integer @param flags: Flags associated with the mouse event (injected or not) @type flags: integer @param time: Seconds since the epoch when the even current @type time: integer @param hwnd: Window handle of the foreground window at the time of the event @type hwnd: integer ''' event = MouseEvent(msg, x, y, data, flags, time, hwnd, window_name) func = self.mouse_funcs.get(msg) if func: return func(event) else: return True def KeyboardSwitch(self, msg, vk_code, scan_code, ascii, flags, time, hwnd, win_name): ''' Passes a keyboard event on to the appropriate handler if one is registered. @param msg: Message value @type msg: integer @param vk_code: The virtual keycode of the key @type vk_code: integer @param scan_code: The scan code of the key @type scan_code: integer @param ascii: ASCII numeric value for the key if available @type ascii: integer @param flags: Flags associated with the key event (injected or not, extended key, etc.) @type flags: integer @param time: Time since the epoch of the key event @type time: integer @param hwnd: Window handle of the foreground window at the time of the event @type hwnd: integer ''' event = KeyboardEvent(msg, vk_code, scan_code, ascii, flags, time, hwnd, win_name) try: func = self.keyboard_funcs.get(msg) if func: return func(event) else: return True except Exception, e: return True def SubscribeMouseMove(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseMove property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_MOUSEMOVE) else: self.connect(self.mouse_funcs, HookConstants.WM_MOUSEMOVE, func) def SubscribeMouseLeftUp(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseLeftUp property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_LBUTTONUP) else: self.connect(self.mouse_funcs, HookConstants.WM_LBUTTONUP, func) def SubscribeMouseLeftDown(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseLeftDown property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_LBUTTONDOWN) else: self.connect(self.mouse_funcs, HookConstants.WM_LBUTTONDOWN, func) def SubscribeMouseLeftDbl(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseLeftDbl property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_LBUTTONDBLCLK) else: self.connect(self.mouse_funcs, HookConstants.WM_LBUTTONDBLCLK, func) def SubscribeMouseRightUp(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseRightUp property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_RBUTTONUP) else: self.connect(self.mouse_funcs, HookConstants.WM_RBUTTONUP, func) def SubscribeMouseRightDown(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseRightDown property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_RBUTTONDOWN) else: self.connect(self.mouse_funcs, HookConstants.WM_RBUTTONDOWN, func) def SubscribeMouseRightDbl(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseRightDbl property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_RBUTTONDBLCLK) else: self.connect(self.mouse_funcs, HookConstants.WM_RBUTTONDBLCLK, func) def SubscribeMouseMiddleUp(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseMiddleUp property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_MBUTTONUP) else: self.connect(self.mouse_funcs, HookConstants.WM_MBUTTONUP, func) def SubscribeMouseMiddleDown(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseMiddleDown property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_MBUTTONDOWN) else: self.connect(self.mouse_funcs, HookConstants.WM_MBUTTONDOWN, func) def SubscribeMouseMiddleDbl(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseMiddleDbl property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_MBUTTONDBLCLK) else: self.connect(self.mouse_funcs, HookConstants.WM_MBUTTONDBLCLK, func) def SubscribeMouseWheel(self, func): ''' Registers the given function as the callback for this mouse event type. Use the MouseWheel property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.mouse_funcs, HookConstants.WM_MOUSEWHEEL) else: self.connect(self.mouse_funcs, HookConstants.WM_MOUSEWHEEL, func) def SubscribeMouseAll(self, func): ''' Registers the given function as the callback for all mouse events. Use the MouseAll property as a shortcut. @param func: Callback function @type func: callable ''' self.SubscribeMouseMove(func) self.SubscribeMouseWheel(func) self.SubscribeMouseAllButtons(func) def SubscribeMouseAllButtons(self, func): ''' Registers the given function as the callback for all mouse button events. Use the MouseButtonAll property as a shortcut. @param func: Callback function @type func: callable ''' self.SubscribeMouseAllButtonsDown(func) self. SubscribeMouseAllButtonsUp(func) self.SubscribeMouseAllButtonsDbl(func) def SubscribeMouseAllButtonsDown(self, func): ''' Registers the given function as the callback for all mouse button down events. Use the MouseAllButtonsDown property as a shortcut. @param func: Callback function @type func: callable ''' self.SubscribeMouseLeftDown(func) self.SubscribeMouseRightDown(func) self.SubscribeMouseMiddleDown(func) def SubscribeMouseAllButtonsUp(self, func): ''' Registers the given function as the callback for all mouse button up events. Use the MouseAllButtonsUp property as a shortcut. @param func: Callback function @type func: callable ''' self.SubscribeMouseLeftUp(func) self.SubscribeMouseRightUp(func) self.SubscribeMouseMiddleUp(func) def SubscribeMouseAllButtonsDbl(self, func): ''' Registers the given function as the callback for all mouse button double click events. Use the MouseAllButtonsDbl property as a shortcut. @param func: Callback function @type func: callable ''' self.SubscribeMouseLeftDbl(func) self.SubscribeMouseRightDbl(func) self.SubscribeMouseMiddleDbl(func) def SubscribeKeyDown(self, func): ''' Registers the given function as the callback for this keyboard event type. Use the KeyDown property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.keyboard_funcs, HookConstants.WM_KEYDOWN) self.disconnect(self.keyboard_funcs, HookConstants.WM_SYSKEYDOWN) else: self.connect(self.keyboard_funcs, HookConstants.WM_KEYDOWN, func) self.connect(self.keyboard_funcs, HookConstants.WM_SYSKEYDOWN, func) def SubscribeKeyUp(self, func): ''' Registers the given function as the callback for this keyboard event type. Use the KeyUp property as a shortcut. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.keyboard_funcs, HookConstants.WM_KEYUP) self.disconnect(self.keyboard_funcs, HookConstants.WM_SYSKEYUP) else: self.connect(self.keyboard_funcs, HookConstants.WM_KEYUP, func) self.connect(self.keyboard_funcs, HookConstants.WM_SYSKEYUP, func) def SubscribeKeyChar(self, func): ''' Registers the given function as the callback for this keyboard event type. Use the KeyChar property as a shortcut. B{Note}: this is currently non-functional, no WM_*CHAR messages are processed by the keyboard hook. @param func: Callback function @type func: callable ''' if func is None: self.disconnect(self.keyboard_funcs, HookConstants.WM_CHAR) self.disconnect(self.keyboard_funcs, HookConstants.WM_DEADCHAR) self.disconnect(self.keyboard_funcs, HookConstants.WM_SYSCHAR) self.disconnect(self.keyboard_funcs, HookConstants.WM_SYSDEADCHAR) else: self.connect(self.keyboard_funcs, HookConstants.WM_CHAR, func) self.connect(self.keyboard_funcs, HookConstants.WM_DEADCHAR, func) self.connect(self.keyboard_funcs, HookConstants.WM_SYSCHAR, func) self.connect(self.keyboard_funcs, HookConstants.WM_SYSDEADCHAR, func) def SubscribeKeyAll(self, func): ''' Registers the given function as the callback for all keyboard events. Use the KeyAll property as a shortcut. @param func: Callback function @type func: callable ''' self.SubscribeKeyDown(func) self.SubscribeKeyUp(func) self.SubscribeKeyChar(func) MouseAll = property(fset=SubscribeMouseAll) MouseAllButtons = property(fset=SubscribeMouseAllButtons) MouseAllButtonsUp = property(fset=SubscribeMouseAllButtonsUp) MouseAllButtonsDown = property(fset=SubscribeMouseAllButtonsDown) MouseAllButtonsDbl = property(fset=SubscribeMouseAllButtonsDbl) MouseWheel = property(fset=SubscribeMouseWheel) MouseMove = property(fset=SubscribeMouseMove) MouseLeftUp = property(fset=SubscribeMouseLeftUp) MouseLeftDown = property(fset=SubscribeMouseLeftDown) MouseLeftDbl = property(fset=SubscribeMouseLeftDbl) MouseRightUp = property(fset=SubscribeMouseRightUp) MouseRightDown = property(fset=SubscribeMouseRightDown) MouseRightDbl = property(fset=SubscribeMouseRightDbl) MouseMiddleUp = property(fset=SubscribeMouseMiddleUp) MouseMiddleDown = property(fset=SubscribeMouseMiddleDown) MouseMiddleDbl = property(fset=SubscribeMouseMiddleDbl) KeyUp = property(fset=SubscribeKeyUp) KeyDown = property(fset=SubscribeKeyDown) KeyChar = property(fset=SubscribeKeyChar) KeyAll = property(fset=SubscribeKeyAll) def connect(self, switch, id, func): ''' Registers a callback to the given function for the event with the given ID in the provided dictionary. Internal use only. @param switch: Collection of callbacks @type switch: dictionary @param id: Event type @type id: integer @param func: Callback function @type func: callable ''' switch[id] = func def disconnect(self, switch, id): ''' Unregisters a callback for the event with the given ID in the provided dictionary. Internal use only. @param switch: Collection of callbacks @type switch: dictionary @param id: Event type @type id: integer ''' try: del switch[id] except: pass