2013-05-17 53 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