English 中文(简体)
How do I control the text input panel programmatically (TabTip.exe) in Windows Vista/7
原标题:

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?

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.

The application is written in C++/MFC.

Any pointers at all are greatly appreciated.

最佳回答

I solved the problem. It turns out that Spy++ really is a Windows programmers best friend.

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);

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);

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.

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.

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);
    }
}

The ShowWindow() function is implemented similarly, but it will also start the keyboard if it is not running.

Update:

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.

Update:

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.

问题回答

For Windows 8:

Note: Just like the Windows 7 solution, this requires an elevated process.

The input panel is not a descendant of HWND_DESKTOP. (It s probably some kind of Metro window.) In order to get the window handle, do a series of horizontal sweeps in a grid-like pattern testing with WindowFromPoint(). For each test, check the window class of the parent window to see if it is "IPTip_Main_Window".

To show the input panel, launch "C:\Program Files\Common Files\microsoft shared\ink\tabtip.exe". To determine if it is already in docked mode, read registry key:

HKEY_CURRENT_USERSoftwareMicrosoftTabletTip1.7EdgeTargetDockedState

A value of 0 indicates the input panel is in floating mode. If that was the case, post the following message to toggle the docked state:

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

To hide the keyboard, post the following:

PostMessage(hwndInputPanel, WM_SYSCOMMAND, SC_CLOSE, 0);




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签