One way to adapt desktop applications to the touch screen

    After working for some time with Windows 8 on a tablet and an ultrabook with a touch screen, I came across one interesting feature. When working with input fields in desktop applications, the on-screen keyboard does not appear automatically, you have to call it each time by touching the icon in the system tray, and then close it by clicking on the close window button.
    In Windows UI applications, there is no such problem, the keyboard automatically appears as soon as the input field receives focus and disappears when it is no longer needed - for example, the control lost input focus, or the user began to enter text from the iron keyboard.
    Since I am not only a user, but also a developer, I thought: what if I transfer this behavior of the on-screen keyboard to my desktop applications? The task is set, we are looking for a solution.
    Congratulations to the harachitiki with the upcoming holidays! To everyone who has read to the end - a ready-to-use code as a gift! :)

    Task number 1 is to display the keyboard.


    Tablet PC Input Panel is an application included in the standard package of Windows 8, which actually displays the on-screen keyboard. Run it and see what happens. After starting the application, we see that a keyboard appears on the screen. Therefore, to display the keyboard, we implement a software launch.

    TCHAR kbdPath[MAX_PATH] = {0};
    ExpandEnvironmentStrings(_T("%CommonProgramW6432%"), kbdPath, _countof(kbdPath));
    wcscat_s(kbdPath, _countof(kbdPath), _T("\\microsoft shared\\ink\\tabtip.exe"));
    ShellExecute(NULL, _T("open"), kbdPath, NULL, NULL, SW_SHOWNORMAL);
    


    If you execute this code, an on-screen keyboard will appear on the screen, which is what they achieved.

    Task number 2 - hide the keyboard


    After the user presses Enter or the input field has lost focus, it would be nice to hide the keyboard so that he does not have to do it on his own. To make this even easier, since the keyboard is displayed in the window, this can be realized by programmatically closing or minimizing the window. But first you need to find it somehow.

    I launched the keyboard and checked the window properties using the Spy ++ utility included with Visual Studio and found what interests me, namely the IPTip_Main_Window window class . The rest is a matter of technology, using the name of the class we find the window and minimize it by sending the corresponding message.

    HWND kbd = ::FindWindow(_T("IPTip_Main_Window"), NULL);
    if(kbd != NULL)
    {
    	::PostMessage(kbd, WM_SYSCOMMAND, SC_CLOSE, 0);
    }
    


    Task number 3 - expand to the full width of the screen, minimize the keyboard


    The on-screen keyboard can have a standard size on the screen, and can be expanded to the entire width of the screen. To change the width of the keyboard, you can send her a message that she receives when she clicks on the maximize button in the upper left corner.

    DWORD msgSwitchTo = ::RegisterWindowMessage(_T("IPTipDockButtonPressed"));
    HWND kbd = ::FindWindow(_T("IPTip_Main_Window"), NULL);
    if(kbd != NULL)
    {
    	::PostMessage(kbd, msgSwitchTo, 0x891, 0);
    }
    

    It would also be nice to understand what state the keyboard is in. Here I decided to do simply - to determine the width of the screen, then the width of the keyboard and compare these two values

    HWND kbd = ::FindWindow(_T("IPTip_Main_Window"), NULL);
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    RECT touchWindow = {0};
    if(GetWindowRect(kbd, &touchWindow) == false)
    {
    	return false;
    }
    int touchWidth = touchWindow.right - touchWindow.left;
    return (screenWidth <= touchWidth);
    

    For ease of use in my projects, I wrapped all the received functions in the CTouchKeyboard class

    class CTouchKeyboard
    {
    public:
    	static bool IsVisible();
    	static bool Show();
    	static bool Hide();
    	static bool Dock();
    	static bool IsDocked();
    private:
    	static HWND FindKeyboardWindow();
    	static bool PostMessageToKeyboard(DWORD msg, WPARAM wParam, LPARAM lParam);
    };
    


    How to use in applications


    When working with text fields, the user expects an on-screen keyboard to appear in the field. How to implement this? When the focus is received by entering a text field, the parent window receives an EN_SETFOCUS notification , respectively, add a handler and call it in the handler of this notification

    CTouchKeyboard::Show(); 
    

    If the input focus is lost, the parent window receives a notification EN_KILLFOCUS , accordingly, it will be called there

    CTouchKeyboard::Hide();  
    

    We assemble, launch, enjoy the result - if you select the text field the keyboard appears, press the Tab key - the keyboard disappears.



    An example of use and source codes are available here .

    Also popular now: