【问题标题】:How to create a global hotkey on Windows with 3 arguments?如何在 Windows 上使用 3 个参数创建全局热键?
【发布时间】:2013-05-12 23:29:12
【问题描述】:

就像 Ctl,Alt + 删除

我想编写一个程序,它在 python 中使用具有 3 个或更多参数的全局热键。只有当我按下键盘上的所有三个键时,分配的功能才会执行。例如 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? 解释如何使用分配一个需要按下的键,然后是否需要按下其中的两个。但是我不认为该功能仅在同时按下所有功能时才执行。我拿了

【问题讨论】:

标签: python hotkeys registerhotkey global-hotkey


【解决方案1】:

对于初学者,如果您想要 alt、windows 和 F3,您不需要使用 win32con.VK_F3, win32con.MOD_ALT, win32con.MOD_WIN 来输入 HOTKEYS 吗?

但是,用 Win and F5修饰符说按 F3 并没有什么意义> 键。

就行的错误:

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

是因为每个字典条目的值都是可变长度tuple。这是一种处理方式,它也按位 OR 将所有修饰符值组合在一起,以准备将它们作为单个参数传递给 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 的建议,解决您的问题会更容易。请考虑在未来这样做。

【讨论】:

    【解决方案2】:

    对于任何对这个主题的详细信息和更详细的示例感兴趣的人,我最近编写了一个简短的程序来演示 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
    

    【讨论】:

    • 建议将其设为Active State Python Recipe,并可能在评论中发布指向它的链接,而不是作为对本网站上模糊相关问题的非回答。
    猜你喜欢
    • 2013-10-21
    • 1970-01-01
    • 2022-10-21
    • 2011-07-12
    • 1970-01-01
    • 2011-02-15
    • 2014-01-02
    • 2011-08-21
    • 2014-05-27
    相关资源
    最近更新 更多