Programming Input Panels

The input panel includes a window, a button on the taskbar, an input panel Properties dialog box, and several interface methods. The Input Panel button and Properties dialog box let the user change the state of the input panel and select a different IM. You can use these user interface (UI) elements and interface methods to add additional features to your applications.

The Input Panel window is the most visible aspect of the input panel UI elements. A user can dock this window above the taskbar or float the window in various screen positions. The default Input Panel window size is 240 pixels wide by 80 pixels high. A user can display or hide the input panel through the Input Panel button on the taskbar. The following screen shot shows the Input Panel window, the Input Panel button, and the handwriting IM.

When a user first selects the Input Panel button, Windows CE creates a dedicated input panel thread. The thread creates an Input Panel window and initializes the input panel. Then, the thread enters a message loop. Within the message loop, the thread responds to messages and UI requests from the Input Panel window. The thread also calls into the IM object. This allows the IM to create child windows of the Input Panel window. The content of the Input Panel window is determined by the current IM.

The input panel thread has a special status with the operating system. Any window that the input panel thread creates will not be obscured by other windows. Because some interface elements save and clear themselves when they lose focus, the input panel and its children do not receive the focus, even if the user is currently using the input panel.

The input panel queries the IM for information through the IInputMethod interface. The input panel can remove the current IM and replace it with a new IM. The following table shows the order in which an IM can expect to receive interface queries from the input panel.

Method
Description
Deselect Destroys its window and perform IM-specific cleanup procedures.
Select Creates the IM window and image list.
GetInfo Requests information regarding the new IM, including property flags and the preferred size of the IM.
ReceiveSipInfo Sends the IM information about the size, placement, and docked status the IM should use.
RegisterCallback Provides the IM with a pointer to the IIMRegisterCallback interface.

After the input panel has called these methods, the IM should render the Input Panel window space and responding to user actions. For more information on programming the IM, see Programming Input Methods.

Note SIP stands for Soft Input Panel, the original name of the input panel. While the name has since been shortened, the abbreviation SIP remains part of many structure and function names.

An application that uses the input panel should know the input panel state — whether the panel is visible, whether it is docked or floating, and its size and position. All this information is stored in the SIPINFO structure, which is accessed through the SHSipInfo function. The following code example shows how to use the SHSipInfo function to access and modify the SIPINFO structure.

BOOL LowerSip( void )
{
    BOOL fRes = FALSE;
    SIPINFO si;

    memset( &si, 0, sizeof( si ) );
    si.cbSize = sizeof( si );
    if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) ) 
    {
        si.fdwFlags &= ~SIPF_ON;
        fRes = SHSipInfo( SPI_SETSIPINFO, 0, &si, 0 );
    }

    return fRes;
}

When the user changes the input panel state, the operating system sends out a WM_SETTINGCHANGE message to all active applications. This message has SPI_SETSIPINFO in its wParam parameter. The following code example shows how you can use the SHSipInfo function to move the input panel on the screen in response to a WM_SETTINGCHANGE message.

WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    SIPINFO si;
    switch( msg ) 
    {
        case WM_SETTINGCHANGE:
            switch( wParam ) 
            {
                case SPI_SETSIPINFO:
                    memset( &si, 0, sizeof( si ) );
                    si.cbSize = sizeof( si );
                    if( SHSipInfo( SPI_GETSIPINFO, 0, &si, 0 ) ) 
                    {
                        MoveWindow(
                            hwnd,
                            si.rcVisibleDesktop.left,
                            si.rcVisibleDesktop.top,
                            si.rcVisibleDesktop.right -                                                si.rcVisibleDesktop.left,
                            si.rcVisibleDesktop.bottom -
                            si.rcVisibleDesktop.top,
                            TRUE );
                    }
                    break;
            }
            break;
    }

return 0;
}