Работа с экранной клавиатурой в desktop приложениях

Поработав некоторое время с Windows 8 на планшете и ультрабуке с сенсорным экраном я столкнулся с одной интересной особенностью. При работе с полями ввода в десктоп приложениях экранная клавиатура не появляется автоматически, приходится каждый раз вызывать ее путем касания ее значка в системном лотке, а потом закрывать нажатие на крестик в правом верхнем углу.

В Windows UI приложениях такой проблемы нет, клавиатура автоматически появляется как только поле ввода получает фокус ввода и исчезает когда в ней отпадает необходимость.

Так как я не только пользователь. но и разработчик я подумал, а что если перенести это поведение клавиатуры и в свои десктоп приложения? Задача поставлена, ищем решение.

Задача номер 1 - отобразить клавиатуру.

 

Tablet PC Input Panel это приложение. которое, собственно и отображает экранную клавиатуру. Запустим его и посмотрим, что получится

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

Если выполнить этот код на экране появится экранная клавиатура.

Задача номер 2 - скрыть клавиатуру.

 

После того как пользователь нажал Enter или поле ввода потеряло фокус неплохо было бы скрыть клавиатуру, чтобы ему не пришлось делать это самостоятельно. Сделать это еще проще, так как клавиатура отображается в окне то реализовать это можно путем программного закрытия или сворачивания окна. Но для начала его необходимо как-то найти. Я запустил клавиатуру и проверил свойства окна с помощью утилиты Spy++, входящей в состав Visual Studio и нашел то, что меня интересовало, а именно класс окна IPTip_Main_Window . Остальное дело техники, используя класс находим окно и сворачиваем его, путем отправки соответствующего сообщения.

HWND kbd = ::FindWindow(_T("IPTip_Main_Window"), NULL);

if(kbd != NULL)
{
	::PostMessage(kbd, WM_SYSCOMMAND, SC_CLOSE, 0);
}

Для простоты использования в своих проектах я обернул обе полученные функции в класс CTouchKeyboard.

Как использовать в приложениях

 

При работе с текстовыми полями пользователь ожидает, что переходе в него появится экранная клавиатура. Как это реализовать? При получении фокуса ввода текстовым полем родительское окно получает уведомление EN_SETFOCUS, соответственно добавляем обработчик и в обработчике этого уведомления вызываем

CTouchKeyboard::Show(); 
 

При потере фокуса ввода родительское окно получает уведомление EN_KILLFOCUS, соответственно там будет вызываться

CTouchKeyboard::Show();  
 

Собираем, запускаем, наслаждаемся результатом - если выбрать тектовое поле клавиатура появляется, нажимаем клавишу Tab - клавиатура исчезает.

Пример использования и исходники доступны здесь.

Para obtener información más completa sobre las optimizaciones del compilador, consulte nuestro Aviso de optimización.