Как сделать экранную клавиатуру в стиле T9 для Windows? - PullRequest
3 голосов
/ 03 июля 2010

Иногда по ночам я люблю смотреть фильмы в постели или смотреть ТВ-шоу онлайн.Это удобно, так как мой компьютер находится прямо возле моего стола, поэтому я просто вращаю один из моих мониторов, отключаю другой экран и перетаскиваю мышь.Моя клавиатура не совсем тянется, если не переставить кабель так, чтобы он не работал, когда я возвращаюсь к своему столу на следующий день.Иногда, когда я смотрю фильмы, мои друзья пытаются поговорить со мной, и я хотел бы иметь возможность разговаривать, не подпрыгивая, вращая монитор вокруг, двигая мышь назад и снова садясь в кресло.

То, что я хотел бы сделать, - это создать экранную клавиатуру, которая будет использоваться с мышью, но в стиле телефонной клавиатуры T9, чтобы (надеюсь) минимизировать количество щелчков и количество перемещений мыши, отсутствующих целей,Я хотел бы сделать это на Python, так как я уже знаком с языком, но я не уверен, с чего начать.

Одна вещь, в которой я не уверен, это как нажимать наклавиатура без кражи фокуса из окна чата.Можно ли это сделать?Или приложение может запомнить последний сфокусированный элемент управления в последнем сфокусированном окне и отправить ему нажатия клавиш?

Кроме того, нужна ли мне внешняя библиотека для управления этим окном и отправки нажатий клавиш?

Помощь очень ценится, и если такая вещь уже существует (на любом языке), то я также буду благодарна за указание на нее.

Я обязательно открою ее исходный код и опубликую здесь ссылку на проект.если и когда я его разработаю, если кто-то еще сочтет такую ​​вещь полезной:)

1 Ответ

3 голосов
/ 03 июля 2010

Около 12 лет назад я написал программу для Windows, которая сидела в трее и посылала нажатия клавиш на определенные окна, когда они получали фокус.У меня больше нет кода, и я забыл все детали.

Тем не менее, процесс будет работать примерно так:

Для вашего GUI, если вы используете Python, вы, вероятно, захотитеиспользуйте PyQT или wxPython.Обе библиотеки облегчают написание приложений с графическим интерфейсом (хотя вы можете напрямую использовать API-интерфейсы Windows).

Если бы это был я, я бы отложил программирование с использованием графического интерфейса и использовал бы PythonWin.Используйте инструменты GUI (множество примеров в исходном коде), чтобы создать простой диалог (также Window) для обработки событий.

Возможно, для вашего приложения есть несколько подходов для выбора target окно.Окно виртуальной клавиатуры, вероятно, будет нуждаться в краже фокуса (для получения событий мыши), но затем ему нужно будет знать, в какое окно отправлять нажатия клавиш.

  • Вы можете иметь раскрывающийся элемент управления вдиалоговое окно, которое позволяет вам выбрать целевое окно (вы можете легко получить заголовок каждого окна для выбора цели), или
  • Когда ваше окно получает фокус (есть событие, которое вы можете перехватить, что-то вроде WM_FOCUS), вы можете запросить последнее окно с фокусом или сохранить вкладки, на которых окна имеют фокус , и использовать последнее, которое вы заметили.

В любом случае,если у вас есть дескриптор целевого окна, вы можете использовать SendMessage для отправки нажатий клавиш в целевое окно.Сначала я предлагаю просто передавать обычные нажатия клавиш, а потом беспокоиться о захвате щелчков мыши.

Редактировать Мне удалось объединить это для отправки нажатий клавиш в другое окно.

import win32ui
import win32con
import time
from ctypes import *

PUL = POINTER(c_ulong)
class KeyBdInput(Structure):
    _fields_ = [("wVk", c_ushort),
                ("wScan", c_ushort),
                ("dwFlags", c_ulong),
                ("time", c_ulong),
                ("dwExtraInfo", PUL)]

class HardwareInput(Structure):
    _fields_ = [("uMsg", c_ulong),
                ("wParamL", c_short),
                ("wParamH", c_ushort)]

class MouseInput(Structure):
    _fields_ = [("dx", c_long),
                ("dy", c_long),
                ("mouseData", c_ulong),
                ("dwFlags", c_ulong),
                ("time",c_ulong),
                ("dwExtraInfo", PUL)]

class Input_I(Union):
    _fields_ = [("ki", KeyBdInput),
                 ("mi", MouseInput),
                 ("hi", HardwareInput)]

class Input(Structure):
    _fields_ = [("type", c_ulong),
                ("ii", Input_I)]

def send_char(char):
    FInputs = Input * 1
    extra = c_ulong(0)
    ii_ = Input_I()
    KEYEVENTF_UNICODE = 0x4
    ii_.ki = KeyBdInput( 0, ord(char), KEYEVENTF_UNICODE, 0, pointer(extra) )
    x = FInputs( ( 1, ii_ ) )
    windll.user32.SendInput(1, pointer(x), sizeof(x[0]))

if __name__ == '__main__':
    wnd = win32ui.FindWindow(None, '* Untitled - Notepad2 (Administrator)')
    type_this = 'jaraco'
    wnd.SetFocus()
    wnd.SetForegroundWindow()
    for char in type_this:
        send_char(char)

Я обнаружил, что техника PostMessage не очень хорошо работала (у меня она вообще не работала).

Я также нашел эту статью о , идентифицирующую последнее активное окно .

...