【问题标题】:How can I make a T9 style on-screen keyboard for Windows?如何为 Windows 制作 T9 风格的屏幕键盘?
【发布时间】:2011-03-11 09:45:37
【问题描述】:

有时晚上,我喜欢在床上看电影,或者在线看电视节目。这很方便,因为我的电脑就在我的桌子旁边,所以我只需旋转我的一个显示器,禁用我的另一个屏幕并将鼠标拉到上面。如果不重新布置电缆,我的键盘就不能完全够到,这种方式在我第二天搬回办公桌时不起作用。有时我在看电影时,我的朋友试图跟我说话,而我希望能够在不跳起来、旋转显示器、向后移动鼠标并重新坐在椅子上的情况下回话。

我想做的是制作一个与鼠标一起使用的屏幕键盘——但在 T9 电话键盘样式中,以(希望)最大限度地减少点击次数和移动鼠标的数量,丢失目标。我想在 Python 中执行此操作,因为我已经熟悉该语言,但我不确定从哪里开始。

我不确定的一件事是如何在不从聊天窗口中窃取焦点的情况下单击屏幕键盘。这可以实现吗?或者应用程序是否可以记住最后一个焦点窗口中的最后一个焦点控件并将击键发送给它?

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

非常感谢您的帮助,如果这样的事情已经存在(以任何语言),将我指向它也将不胜感激。

如果我开发它,我肯定会开源它并在此处发布项目的链接,以防其他人会发现这种东西很有用:)

【问题讨论】:

  • 你可以使用PyGTK或者PyQT来实现GUI,但是部分重点我不知道在Windows 7中你是如何完成的。

标签: python windows windows-7 soft-keyboard


【解决方案1】:

大约 12 年前,我为 Windows 编写了一个程序,该程序位于托盘中,当它们获得焦点时会向某些窗口发送击键。我已经没有代码了,我忘记了所有的细节。

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

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

不过,如果是我,我会推迟 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)

我发现 PostMessage 技术效果不佳(我根本无法让它为我工作)。

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

【讨论】:

猜你喜欢
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 2015-11-05
  • 1970-01-01
  • 2019-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多