Как заставить pynput предотвращать попадание определенных нажатий клавиш в конкретное приложение? - PullRequest
0 голосов
/ 11 июля 2020

Я хочу создать инструмент, который позволит мне использовать некоторые команды в стиле Vim в приложении ( Scrivener ), которое его не поддерживает.

Например, если

  • текущий режим - Command mode и
  • пользователь нажимает кнопку w,

, затем курсор должен перемещаться на один символ направо. Вместо символа w Скривенер должен получить сигнал «стрелка вправо».

Чтобы реализовать это, я написал следующий код (на основе этих двух ответов: 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()

Каждый раз, когда я нажимаю кнопку w в Scrivener в командном режиме, Scrivener отправляет два нажатия клавиш:

  1. Backspace для удаления уже введен символ w.
  2. Стрелка вправо для перемещения курсора.

Этот вид работает, но вы можете видеть, что символ w отображается и снова удаляется (см. это видео ).

Как я могу убедиться, что нажатие клавиши с w вообще не доходит до Scrivener, если установлен режим Command, а текущее окно с фокусом - это приложение Scrivener?

1 Ответ

2 голосов
/ 13 июля 2020

Сначала вам нужно установить библиотеки pyHook и pywin32.

Затем отслеживать информацию о клавиатуре через pyhook. Если вам нужно перехватить информацию с клавиатуры (например, нажать w), верните False.

Наконец, через pythoncom.PumpMessages () для достижения мониторинга l oop. Вот пример:

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() 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...