Comment puis-je créer un clavier à l’écran de style T9 pour Windows?

Parfois, la nuit, j’aime regarder des films au lit ou des émissions de télévision en ligne. C’est pratique puisque mon ordinateur est juste à côté de mon bureau, alors je tourne un de mes moniteurs, je désactive mon autre écran et je passe la souris. Mon clavier n’atteint pas tout à fait sans réacheminer le câble d’une manière qui ne fonctionne pas lorsque je retourne à mon bureau le lendemain. Parfois, pendant que je regarde des films, mes amis essaient de me parler et j’aimerais pouvoir parler sans sauter, tourner le moniteur, déplacer la souris et m’asseoir sur la chaise.

Ce que je voudrais faire, c’est utiliser un clavier à l’écran avec la souris – mais dans un style de clavier téléphonique T9 pour minimiser (espérons-le) le nombre de clics et la quantité de déplacement de la souris, les cibles manquantes. Je voudrais faire cela en Python puisque je connais déjà le langage, mais je ne sais pas par où commencer.

Une chose dont je ne suis pas sûr est de savoir comment cliquer sur le clavier à l’écran sans voler l’attention de la fenêtre de discussion. Est-ce que cela peut être accompli? Ou l’application peut-elle mémoriser le dernier contrôle ciblé dans la dernière fenêtre ciblée et y envoyer des séquences de touches?

De plus, aurais-je besoin d’une bibliothèque externe pour effectuer l’une de ces tâches de gestion de fenêtres et d’envoi de touches?

L’aide est grandement appréciée, et si une telle chose existe déjà (dans n’importe quelle langue), il serait également très utile de me pointer vers elle.

Je vais certainement l’ouvrir et poster un lien vers le projet ici si et quand je le développe, au cas où quelqu’un d’autre trouverait ce genre de chose utile 🙂

Il y a environ 12 ans, j’ai écrit un programme pour Windows qui se trouvait dans la barre des tâches et qui envoyait des frappes sur certaines fenêtres lorsqu’elles se sont concentrées. Je n’ai plus le code et j’ai oublié tous les détails.

Cependant, le processus fonctionnera comme ceci.

Pour votre interface graphique, si vous utilisez Python, vous souhaiterez probablement utiliser PyQT ou wxPython. Les deux bibliothèques facilitent l’écriture d’applications GUI (même si vous pouvez utiliser directement les API Windows).

Si c’était moi, cependant, je différerais la programmation de l’interface graphique et utiliserais PythonWin. Utilisez ses outils graphiques (de nombreux exemples dans la source) pour créer un simple dialog (également une Window ) pour gérer les événements.

Il y a probablement quelques approches pour que votre application sélectionne une fenêtre target . La fenêtre du clavier virtuel devra probablement voler le focus (pour recevoir les événements de la souris), mais il faudra alors savoir dans quelle fenêtre envoyer les frappes.

  • Vous pouvez avoir un contrôle déroulant dans la boîte de dialog qui vous permet de sélectionner une fenêtre cible (vous pouvez facilement saisir le titre de chaque fenêtre pour la sélection de la cible), ou
  • Lorsque votre fenêtre gagne du focus (il y a un événement que vous pouvez WM_FOCUS , quelque chose comme WM_FOCUS ), vous pouvez soit interroger la dernière fenêtre qui a le focus, soit garder les tabs sur les fenêtres ciblées et utiliser la dernière.

Dans les deux cas, une fois que vous avez un handle vers la fenêtre cible, vous pouvez utiliser SendMessage pour envoyer des séquences de touches à la fenêtre cible. Je suggère tout d’abord de relayer des frappes régulières, et de m’inquiéter plus tard de la capture des clics de souris.

Edit J’ai pu bricoler cela pour envoyer des frappes sur une autre fenêtre.

 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) 

J’ai trouvé que la technique de PostMessage ne fonctionnait pas très bien (je ne pouvais pas le faire fonctionner pour moi).

J’ai également trouvé cet article sur l’ identification de la dernière fenêtre active .