问题描述
我正在为触摸屏界面修改应用程序,我们希望使用Windows Vista/7中包含的数位板文本输入面板,尤其是其键盘.我想显示和隐藏它适合我的应用程序.基本上我想要ShowKeyboard()
和HideKeyboard()
函数.控制此的最佳方法是什么?
I'm adapting an application for touch screen interface and we want to use the tablet text input panel included in Windows Vista/7, specifically its keyboard. I want to show and hide it as appropriate for my app. Basically I want ShowKeyboard()
and HideKeyboard()
functions. What's the best way to control this?
我查看了ITextInputPanel API,但无法直接用它控制键盘(也许我错过了什么?).我也尝试将窗口消息发送到其窗口失败.
I looked at the ITextInputPanel API but I was unable to control the keyboard directly with it (maybe I missed something?). I have also unsuccessfully tried to send window messages to its window.
该应用程序是用C ++/MFC编写的.
The application is written in C++/MFC.
非常感谢任何指针.
推荐答案
我解决了这个问题.事实证明,Spy ++确实是Windows程序员最好的朋友.
I solved the problem. It turns out that Spy++ really is a Windows programmers best friend.
首先,输入面板窗口的窗口类原来是"IPTip_Main_Window".我使用它来获取窗口句柄,如下所示:
First, the window class of the input panel window turns out to be "IPTip_Main_Window". I use this to get the window handle like so:
HWND wKB = ::FindWindow(_TEXT("IPTip_Main_Window"), NULL);
事实证明,我可以发布自己的菜单正在发送的相同WM_COMMAND消息.可以从菜单中进行大多数操作:码头顶部,码头底部和浮动.发送这些消息的代码是:
It turns out that I can just post the same WM_COMMAND messages that its own menu is sending. Most of the operations are available from the menu: dock top, dock bottom and float. The code for sending those messages are:
::PostMessage(wKB, WM_COMMAND, MAKEWPARAM(X,0) , 0);
其中X是船坞底部的10021,船坞顶部的10023和浮动船体的10020.高位字中的0表示消息是从菜单发送的.
where X is 10021 for dock bottom, 10023 for dock top and 10020 for floating. The 0 in the high word indicates that the message is sent from a menu.
最后,我希望能够显示和隐藏输入面板.我注意到我可以打开一个只包含一个用于切换输入面板可见性的按钮的办公桌带.监视此按钮发布的消息后发现,该消息发送了一个名为"TabletInputPanelDeskBandClicked"的全局注册窗口消息.将此消息发送到输入面板会导致其切换可见性.
Finally, I wanted to be able to show and hide the input panel. I noticed that I could turn on a desk band which only includes a single button for toggling the visibility of the input panel. Spy++ing on the messages posted from this button revealed that it sends a global registered window message which is named "TabletInputPanelDeskBandClicked".Sending this message to the input panel causes it to toggle its visibility.
HideKeyboard()函数现在如下所示:
The HideKeyboard() function now looks like this:
DWORD WM_DESKBAND_CLICKED =
::RegisterWindowMessage(_TEXT("TabletInputPanelDeskBandClicked"));
void HideKeyboard()
{
HWND wKB = ::FindWindow(_TEXT("IPTip_Main_Window"), NULL);
if(wKB != NULL && ::IsWindowVisible(wKB))
{
::PostMessage(wKB, WM_DESKBAND_CLICKED, 0, 0);
}
}
ShowWindow()函数的实现方式类似,但是如果未运行,它也会启动键盘.
The ShowWindow() function is implemented similarly, but it will also start the keyboard if it is not running.
似乎在Windows Vista/7中不允许此进程间消息传递.在非提升进程中运行此命令时,它将失败并显示访问被拒绝".我的猜测是这是由Windows Vista/7中的用户界面进程隔离(UIPI)保护引起的.由于Tablet PC输入面板作为服务的子进程运行,因此它具有比用户程序更高的完整性级别,因此无法向其发送任何(或一组非常有限的)消息.
It seems that this inter-process messaging is disallowed in Windows Vista/7. When running this command in a non-elevated process it will fail with "access denied". My guess is that this is caused by User Interface Process Isolation (UIPI) protection found in Windows Vista/7. Since the Tablet PC Input Panel is running as a child process of a service it has higher integrity level than user programs, and thus cannot be sent any (or a very limited set of) messages to.
事实证明,Tablet PC输入面板的确确实以高完整性级别运行,而由受限用户帐户启动的进程为中等完整性级别.
It turns out that the Tablet PC Input Panel is indeed running in high integrity level, whereas processes started by a limited user account is medium integrity level.
这篇关于如何在Windows Vista/7中以编程方式控制文本输入面板(TabTip.exe)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!