【问题标题】:How do I control the text input panel programmatically (TabTip.exe) in Windows Vista/7如何在 Windows Vista/7 中以编程方式控制文本输入面板 (TabTip.exe)
【发布时间】:2010-12-18 17:53:45
【问题描述】:

我正在为触摸屏界面调整应用程序,我们想使用 Windows Vista/7 中包含的平板电脑文本输入面板,特别是它的键盘。我想根据我的应用程序显示和隐藏它。基本上我想要ShowKeyboard()HideKeyboard() 函数。控制这种情况的最佳方法是什么?

我查看了 ITextInputPanel API,但无法直接用它控制键盘(也许我错过了什么?)。我也尝试将窗口消息发送到其窗口,但未成功。

应用程序是用 C++/MFC 编写的。

非常感谢任何指针。

【问题讨论】:

标签: c++ windows mfc winapi accessibility


【解决方案1】:

我解决了这个问题。事实证明,Spy++ 确实是 Windows 程序员最好的朋友。

首先,输入面板窗口的窗口类是“IPTip_Main_Window”。我用它来获取窗口句柄,如下所示:

HWND wKB = ::FindWindow(_TEXT("IPTip_Main_Window"), NULL);

事实证明,我可以只发布它自己的菜单发送的相同 WM_COMMAND 消息。大多数操作都可以从菜单中获得:停靠顶部、停靠底部和浮动。发送这些消息的代码是:

::PostMessage(wKB, WM_COMMAND, MAKEWPARAM(X,0) , 0);

其中 X 是 10021 用于底座底部,10023 用于底座顶部,10020 用于浮动。高位字中的 0 表示消息是从菜单发送的。

最后,我希望能够显示和隐藏输入面板。我注意到我可以打开一个桌带,它只包含一个用于切换输入面板可见性的按钮。对从此按钮发布的消息进行窥探显示,它发送了一个名为“TabletInputPanelDeskBandClicked”的全局注册窗口消息。 将此消息发送到输入面板会导致它切换其可见性。

HideKeyboard() 函数现在如下所示:

DWORD WM_DESKBAND_CLICKED = ::RegisterWindowMessage(_TEXT("TabletInputPanelDeskBandClicked")); 无效隐藏键盘() { HWND wKB = ::FindWindow(_TEXT("IPTip_Main_Window"), NULL); if(wKB != NULL && ::IsWindowVisible(wKB)) { ::PostMessage(wKB, WM_DESKBAND_CLICKED, 0, 0); } }

ShowWindow() 函数实现类似,但是如果它没有运行它也会启动键盘。

更新:

在 Windows Vista/7 中似乎不允许这种进程间消息传递。在非提升进程中运行此命令时,它将失败并显示“拒绝访问”。我的猜测是这是由 Windows Vista/7 中的用户界面进程隔离 (UIPI) 保护引起的。由于 Tablet PC 输入面板作为服务的子进程运行,因此它具有比用户程序更高的完整性级别,因此无法向其发送任何(或非常有限的一组)消息。

更新:

事实证明,Tablet PC 输入面板确实以高完整性级别运行,而由受限用户帐户启动的进程是中等完整性级别。

【讨论】:

    【解决方案2】:

    对于 Windows 8:

    注意:就像 Windows 7 解决方案一样,这需要提升的进程。

    输入面板不是 HWND_DESKTOP 的后代。 (它可能是某种 Metro 窗口。)为了获得窗口句柄,使用 WindowFromPoint() 在网格状模式测试中进行一系列水平扫描。每次测试,检查父窗口的窗口类,看是否为“IPTip_Main_Window”。

    要显示输入面板,请启动 "C:\\Program Files\\Common Files\\microsoft shared\\ink\\tabtip.exe"。要确定它是否已经处于停靠模式,请读取注册表项:

    HKEY_CURRENT_USER\Software\Microsoft\TabletTip\1.7\EdgeTargetDockedState
    

    值为 0 表示输入面板处于浮动模式。如果是这种情况,请发布以下消息以切换停靠状态:

    DWORD WM_DOCK_BUTTON_PRESSED = ::RegisterWindowMessage(_TEXT("IPTipDockButtonPressed"));
    PostMessage(hwndInputPanel, WM_DOCK_BUTTON_PRESSED, 0, 0);
    

    要隐藏键盘,请发布以下内容:

    PostMessage(hwndInputPanel, WM_SYSCOMMAND, SC_CLOSE, 0);
    

    【讨论】:

    • 感谢您的信息!你有没有机会知道我发布的“解决方案”是否仍然适用于 Windows 8?
    • 我的测试表明它不起作用。看起来微软为 Windows 8 重新设计了输入面板。不再有设置停靠状态的下拉菜单,因此 WM_COMMAND 不会做任何事情。现在只有一个按钮可以在停靠和取消停靠之间切换。此外,由于窗口层次结构的一些变化,FindWindow() 将无法实际获取窗口句柄。我必须使用 WindowFromPoint() 进行命中测试才能找到它。
    • 这也适用于Windows 7。对于那些不太熟悉windows api的人:您可以使用GetParent(HWND窗口)获取父级,您可以使用GetClassName()获取它的类名。
    猜你喜欢
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 2011-01-17
    相关资源
    最近更新 更多