如何使 pynput 阻止某些击键到达特定应用程序?
How to make pynput prevent certain keystrokes from reaching a particular application?
我想创建一个工具,允许我在不支持它的应用程序 (Scrivener) 中使用一些 Vim 风格的命令。
例如,如果
- 当前模式为
Command
模式和
- 用户按下按钮
w
,
那么,插入符号应该向右移动一个字符。 Scrivener 应该收到“右箭头”信号,而不是 w
字符。
为了实现这一点,我编写了以下代码(基于这 2 个答案:1, 2):
from pynput.keyboard import Key, Listener, Controller
from typing import Optional
from ctypes import wintypes, windll, create_unicode_buffer
def getForegroundWindowTitle() -> Optional[str]:
hWnd = windll.user32.GetForegroundWindow()
length = windll.user32.GetWindowTextLengthW(hWnd)
buf = create_unicode_buffer(length + 1)
windll.user32.GetWindowTextW(hWnd, buf, length + 1)
if buf.value:
return buf.value
else:
return None
class State:
def __init__(self):
self.mode = "Command"
state = State()
keyboard = Controller()
def on_press(key):
pass
def on_release(key):
if key == Key.f12:
return False
window_title = getForegroundWindowTitle()
if not window_title.endswith("Scrivener"):
return
print("Mode: " + state.mode)
print('{0} release'.format(
key))
if state.mode == "Command":
print("1")
if str(key) == "'w'":
print("2")
print("w released in command mode")
# Press the backspace button to delete the w letter
keyboard.press(Key.backspace)
# Press the right arrow button
keyboard.press(Key.right)
if key == Key.insert:
if state.mode == "Command":
state.mode = "Insert"
else:
state.mode = "Command"
# Collect events until released
print("Press F12 to exit")
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
每当我在命令模式下按下 Scrivener 中的按钮 w
时,都会向 Scrivener 发送两次击键:
- 退格键删除已输入的
w
个字符。
- 向右箭头移动插入符号。
这有点管用,但您可以看到 w
字符再次显示并被删除(参见 this video)。
如果模式是 Command
并且当前聚焦 window 是 Scrivener 应用程序,我如何确保使用 w
的击键根本不会到达 Scrivener?
首先需要安装pyHook和pywin32库
然后通过pyhook监听键盘信息。如果需要截取键盘信息(比如按w),return False.
最后通过pythoncom.PumpMessages()实现循环监控。
这是示例:
import pyHook
import pythoncom
from pynput.keyboard import Key, Listener, Controller
keyboard = Controller()
def onKeyboardEvent(event):
if event.Key == "F12":
exit()
print("1")
if event.Key == 'W':
print("2")
print("w released in command mode")
# Press the right arrow button
keyboard.press(Key.right)
return False
print("hook" + event.Key)
return True
# Collect events until released
print("Press F12 to exit")
hm = pyHook.HookManager()
hm.KeyDown = onKeyboardEvent
hm.HookKeyboard()
pythoncom.PumpMessages()
我想创建一个工具,允许我在不支持它的应用程序 (Scrivener) 中使用一些 Vim 风格的命令。
例如,如果
- 当前模式为
Command
模式和 - 用户按下按钮
w
,
那么,插入符号应该向右移动一个字符。 Scrivener 应该收到“右箭头”信号,而不是 w
字符。
为了实现这一点,我编写了以下代码(基于这 2 个答案:1, 2):
from pynput.keyboard import Key, Listener, Controller
from typing import Optional
from ctypes import wintypes, windll, create_unicode_buffer
def getForegroundWindowTitle() -> Optional[str]:
hWnd = windll.user32.GetForegroundWindow()
length = windll.user32.GetWindowTextLengthW(hWnd)
buf = create_unicode_buffer(length + 1)
windll.user32.GetWindowTextW(hWnd, buf, length + 1)
if buf.value:
return buf.value
else:
return None
class State:
def __init__(self):
self.mode = "Command"
state = State()
keyboard = Controller()
def on_press(key):
pass
def on_release(key):
if key == Key.f12:
return False
window_title = getForegroundWindowTitle()
if not window_title.endswith("Scrivener"):
return
print("Mode: " + state.mode)
print('{0} release'.format(
key))
if state.mode == "Command":
print("1")
if str(key) == "'w'":
print("2")
print("w released in command mode")
# Press the backspace button to delete the w letter
keyboard.press(Key.backspace)
# Press the right arrow button
keyboard.press(Key.right)
if key == Key.insert:
if state.mode == "Command":
state.mode = "Insert"
else:
state.mode = "Command"
# Collect events until released
print("Press F12 to exit")
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
每当我在命令模式下按下 Scrivener 中的按钮 w
时,都会向 Scrivener 发送两次击键:
- 退格键删除已输入的
w
个字符。 - 向右箭头移动插入符号。
这有点管用,但您可以看到 w
字符再次显示并被删除(参见 this video)。
如果模式是 Command
并且当前聚焦 window 是 Scrivener 应用程序,我如何确保使用 w
的击键根本不会到达 Scrivener?
首先需要安装pyHook和pywin32库
然后通过pyhook监听键盘信息。如果需要截取键盘信息(比如按w),return False.
最后通过pythoncom.PumpMessages()实现循环监控。 这是示例:
import pyHook
import pythoncom
from pynput.keyboard import Key, Listener, Controller
keyboard = Controller()
def onKeyboardEvent(event):
if event.Key == "F12":
exit()
print("1")
if event.Key == 'W':
print("2")
print("w released in command mode")
# Press the right arrow button
keyboard.press(Key.right)
return False
print("hook" + event.Key)
return True
# Collect events until released
print("Press F12 to exit")
hm = pyHook.HookManager()
hm.KeyDown = onKeyboardEvent
hm.HookKeyboard()
pythoncom.PumpMessages()