2013-05-17 40 views
3

就像Ctl,Alt +删除如何使用3个参数在Windows上创建全局热键?

我想写一个程序,它使用全局热键和3个或更多的参数在Python中。只有当我按下键盘上的所有三个键时才能执行指定的功能。例如alt,windows和F3。

win32con.VK_F3, win32con.MOD_WIN, win32con.VK_F5 

这是目前的方案我想运行,但其输出为:

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

方案:

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)") 

Registering 3 hotkeys? Possible? 介绍一个如何使用分配一个密钥需要按下,然后如果其中两个需要按下。不过,我不会说只有同时按下所有按钮才能执行此功能。我花了

+0

https://github.com/boppreh/keyboard – Andrew

回答

4

对于初学者来说,如果你想alt,windows和F3,你不需要使用win32con.VK_F3, win32con.MOD_ALT, win32con.MOD_WIN作为HOTKEYS条目吗?

但是,它并没有真正意义地说按F3F5关键的修饰语。

线上的错误:

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

是因为每个字典条目的值是可变长度tuple。这里有一种方法可以处理那些同时将所有修饰符值逐位递增的数据,以准备将它们作为单个参数传递给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) 

这本来是容易对你的问题的工作,如果你的代码是缩进正确,并遵循PEP 8 -- Style Guide for Python Code建议。请考虑将来这样做。

4

对于任何对有兴趣的细节和更详细的例子关于这个主题,我最近写了一个简短的程序来演示win32con提供的热键功能。该计划允许你指定,并通过命令行测试任何你想要的热键:

用法:python.exe hotkey.py MOD_ALT VK_UP - >测试热键ALT +箭头向上

# 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) 

请注意,此计划仅用于演示目的作为程序的一部分(例如,exec函数)不应在生产环境中使用。另外请注意,使用这种方法,您将无法覆盖像WIN + E等内置热键,它们将被忽略并仍然执行内置函数(例如打开资源管理器)。

换种方式(@martineau提供)

下面是如何构建平移图,而无需使用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 
+0

建议,使这是一个[活动状态Python食谱](http://code.activestate.com/recipes/langs/python/),也许发布一个链接到它的评论,而不是一个无法回答这里一个模糊的相关问题在这个网站上。 – martineau