¿Cómo crear una tecla de acceso rápido global en Windows con 3 argumentos?

Al igual que Ctl, Alt + eliminar

Quiero escribir un progtwig, que usa teclas de acceso rápido globales con 3 o más argumentos en python. La función asignada solo debería ejecutarse cuando presiono las tres teclas de mi teclado. Por ejemplo alt, windows y f3.

win32con.VK_F3, win32con.MOD_WIN, win32con.VK_F5 

Este es el progtwig actual que quiero ejecutar, sin embargo, su salida es:

 Traceback (most recent call last): File "C:\Python32\Syntax\hot keys\hotkeys2.py", line 41, in  for id, (vk, modifiers) in HOTKEYS.items (): ValueError: too many values to unpack (expected 2) 

El progtwig:

 import os import sys import ctypes from ctypes import wintypes import win32con byref = ctypes.byref user32 = ctypes.windll.user32 HOTKEYS = { 1 : (win32con.VK_F3, win32con.MOD_WIN, win32con.VK_F5), 2 : (win32con.VK_F4, win32con.MOD_WIN), 3 : (win32con.VK_F2, win32con.MOD_WIN) } def handle_win_f3 (): #os.startfile (os.environ['TEMP']) print ("Hello WOrld! F3") def handle_win_f4 (): #user32.PostQuitMessage (0) print ("Hello WOrld! F4") def handle_win_f1_escape (): print("exit") sys.exit() HOTKEY_ACTIONS = { 1 : handle_win_f3, 2 : handle_win_f4, 3 : handle_win_f1_escape } for id, (vk, modifiers) in HOTKEYS.items (): print ("Registering id", id, "for key", vk) if not user32.RegisterHotKey (None, id, modifiers, vk): print ("Unable to register id", id) try: msg = wintypes.MSG () while user32.GetMessageA (byref (msg), None, 0, 0) != 0: if msg.message == win32con.WM_HOTKEY: action_to_take = HOTKEY_ACTIONS.get (msg.wParam) #print(" msg.message == win32con.WM_HOTKEY:") if action_to_take: action_to_take () user32.TranslateMessage (byref (msg)) user32.DispatchMessageA (byref (msg)) finally: for id in HOTKEYS.keys (): user32.UnregisterHotKey (None, id) print("user32.UnregisterHotKey (None, id)") 

¿Registrar 3 teclas de acceso rápido? ¿Posible? Explica cómo se puede usar asignar una tecla que se debe presionar y luego si se debe presionar dos de las cuales. Sin embargo, no quiero que la función solo se ejecute cuando todos los botones se presionan simultáneamente. Yo tomé

Para empezar, si quisieras alt, windows y F3, ¿no necesitarías usar win32con.VK_F3, win32con.MOD_ALT, win32con.MOD_WIN para la entrada HOTKEYS ?

Sin embargo, no tiene sentido decir que presiona F3 con los modificadores de las teclas Win y F5 .

El error en la línea:

 for id, (vk, modifiers) in HOTKEYS.items (): 

es porque el valor de cada entrada del diccionario es una tuple longitud variable. Aquí hay una manera de manejar aquello que también a nivel de bit O son todos los valores modificadores juntos en preparación para pasarlos como un solo argumento a RegisterHotKey() .

 from functools import reduce for id, values in HOTKEYS.items (): vk, modifiers = values[0], reduce (lambda x, y: x | y, values[1:]) print ("Registering id", id, "for key", vk) if not user32.RegisterHotKey (None, id, modifiers, vk): print ("Unable to register id", id) 

Habría sido más fácil trabajar en su problema si su código estuviera sangrado correctamente y siguiera las recomendaciones de PEP 8 – Style Guide for Python Code . Por favor considere hacerlo en el futuro.

Para cualquier persona interesada en los detalles y en un ejemplo más detallado sobre este tema, recientemente escribí un progtwig corto que muestra las funciones de las teclas de acceso rápido que proporciona win32con. El progtwig le permite especificar y probar las teclas de acceso rápido que desee a través de la línea de comandos:

Uso: python.exe hotkey.py MOD_ALT VK_UP -> tecla de python.exe hotkey.py MOD_ALT VK_UP rápido de prueba ALT + flecha ARRIBA

 # Imports import win32con import ctypes, ctypes.wintypes import sys # # Functions # def dispatch_hotkey(msg): mod = msg.lParam & 0b1111111111111111 key = msg.lParam >> 16 bit = bin(msg.lParam)[2:] print("\n*** Received hotkey message (wParam: %d, lParam: %d)" % (msg.wParam, msg.lParam)) print("lParam bitmap: %s" % bit) print("lParam low-word (modifier): %d, high-word (key): %d" % (mod, key)) print("-> Hotkey %s with modifier %s detected\n" % (keys[key], mods[mod])) # # Main # # Build translation maps (virtual key codes / modifiers to string) # Note: exec() is a hack and should not be used in real programs!! print("\n*** Building translation maps") mods = {} keys = {} for item in dir(win32con): if item.startswith("MOD_"): exec("mods[item] = win32con." + item) exec("mods[win32con." + item + "] = '" + item + "'") if item.startswith("VK_"): exec("keys[item] = win32con." + item) exec("keys[win32con." + item + "] = '" + item + "'") # Process command line print("\n*** Processing command line") mod = "MOD_WIN" key = "VK_ESCAPE" for param in sys.argv: if param.startswith("MOD_"): if param in mods: mod = param else: print("\nInvalid modifier specified (%s). Using default.\n-> Use '--list-mods' for a list of valid modifiers." % param) if param.startswith("VK_"): if param in keys: key = param else: print("\nInvalid key specified (%s). Using default.\n-> Use '--list-keys' for a list of valid keys." % param) if "--list-mods" in sys.argv: print("\nAvailable modifiers:") for item in dir(win32con): if item.startswith("MOD_"): sys.stdout.write(item + ", ") print("\b\b ") if "--list-keys" in sys.argv: print("\nAvailable keys:") for item in dir(win32con): if item.startswith("VK_"): sys.stdout.write(item + ", ") print("\b\b ") # Register hotkey print("\n*** Registering global hotkey (modifier: %s, key: %s)" % (mod, key)) ctypes.windll.user32.RegisterHotKey(None, 1, mods[mod], keys[key]) # Wait for hotkey to be triggered print("\n*** Waiting for hotkey message...") try: msg = ctypes.wintypes.MSG() while ctypes.windll.user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0: if msg.message == win32con.WM_HOTKEY: dispatch_hotkey(msg) break ctypes.windll.user32.TranslateMessage(ctypes.byref(msg)) ctypes.windll.user32.DispatchMessageA(ctypes.byref(msg)) # Unregister hotkey finally: ctypes.windll.user32.UnregisterHotKey(None, 1) 

Tenga en cuenta que este progtwig está destinado solo a fines de demostración, ya que algunas partes del progtwig (por ejemplo, la función exec) no deben utilizarse en entornos de producción. También tenga en cuenta que con este enfoque, no podrá anular las teclas de acceso directo incorporadas como WIN + E, etc., simplemente serán ignoradas y seguirán desempeñando las funciones integradas (por ejemplo, al abrir Explorer).

Otra manera (cortesía de @martineau)

Aquí es cómo construir los mapas de traducción sin usar exec() :

 print("\n*** Building translation maps") mods = {} keys = {} for item, value in vars(win32con).items(): if item.startswith("MOD_"): mods[item] = value mods[value] = item elif item.startswith("VK_"): keys[item] = value keys[value] = item