如何为Windows制作T9风格的屏幕键盘

2024-04-27 09:44:22 发布

您现在位置:Python中文网/ 问答频道 /正文

有时候晚上,我喜欢在床上看电影,或者在线看电视节目。这很方便,因为我的电脑就在我的桌子旁边,所以我只需旋转我的一个显示器,关闭我的另一个屏幕,把我的鼠标拉过来。第二天我搬回办公桌时,如果不重新布线,键盘就无法正常工作。有时我在看电影的时候,我的朋友们会试图和我交谈,我希望能够在不跳起来、不旋转显示器、不移动鼠标、不坐椅子的情况下顶嘴。在

我想做的是做一个屏幕键盘来和鼠标一起使用——但是用T9手机键盘样式(希望如此)来减少点击次数和移动鼠标的次数,以及丢失的目标。我想用Python来做这件事,因为我已经熟悉了Python语言,但是我不知道从哪里开始。在

有一件事我不确定,那就是如何在不窃取聊天窗口焦点的情况下点击屏幕键盘。这能实现吗?或者应用程序能否记住最后一个聚焦窗口中的最后一个焦点控件并向其发送击键?在

另外,我是否需要一个外部库来执行任何窗口管理和按键发送?在

我们非常感谢你的帮助,如果这样的事情已经存在(以任何语言),我也会非常感激。在

如果我开发它的时候,我肯定会把它开源并在这里发布一个项目链接,以防其他人会发现这类东西有用:)


Tags: 语言电影屏幕情况鼠标键盘次数显示器
1条回答
网友
1楼 · 发布于 2024-04-27 09:44:22

大约12年前,我为Windows编写了一个程序,当窗口获得焦点时,它会将按键发送到某些窗口。我已经没有密码了,我已经忘记了所有的细节。在

不过,这个过程还是会像这样工作的。在

对于GUI,如果使用Python,您可能希望使用PyQT或wxPython。这两个库都使得编写GUI应用程序变得很容易(尽管您可以直接使用windowsapi)。在

不过,如果是我,我会推迟GUI编程并使用PythonWin。使用它的GUI工具(源代码中有很多示例)创建一个简单的对话框(也是一个Window)来进行事件处理。在

您的应用程序可能有几种选择target窗口的方法。虚拟键盘窗口可能需要窃取焦点(以接收鼠标事件),但它需要知道将按键发送到哪个窗口。在

  • 您可以在对话框中有一个下拉控件,允许您选择一个目标窗口(您可以轻松获取每个窗口的标题以进行目标选择),或者
  • 当您的窗口获得焦点时(有一个事件可以被捕获,类似于WM_FOCUS),您可以查询最后一个有焦点的窗口,也可以keep tabs on which windows have 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)

我发现邮件后处理技术效果不太好(我根本无法让它为我工作)。在

我还在identifying the last active window上找到了这篇文章。在

相关问题 更多 >