Как программно управлять панелью ввода текста (TabTip.exe) в Windows Vista / 7
я адаптирую приложение для интерфейса сенсорного экрана, и мы хотим использовать панель ввода текста планшета, включенную в Windows Vista / 7, в частности его клавиатуру. Я хочу показать и скрыть его в соответствии с моим приложением. В основном я хочу!--0--> и HideKeyboard()
функции. Как лучше всего это контролировать?
Я посмотрел на API ITextInputPanel, но я не смог напрямую управлять клавиатурой (может быть, я что-то пропустил?). Я также безуспешно пытался отправить окно сообщения в его окно.
приложение написано на языке C++ / MFC.
любые указатели вообще очень ценятся.
2 ответов
я решил проблему. Оказывается, Spy++ действительно является лучшим другом программистов Windows.
во-первых, класс окна окна панели ввода оказывается "IPTip_Main_Window". Я использую это, чтобы получить дескриптор окна так:
HWND wKB = ::FindWindow(_TEXT("IPTip_Main_Window"), NULL);
оказывается, я могу просто публиковать те же сообщения WM_COMMAND, которые отправляет собственное меню. Большинство операций доступны из меню: док-станция сверху, док-станция снизу и поплавок. Код для отправки этих сообщений являются:
::PostMessage(wKB, WM_COMMAND, MAKEWPARAM(X,0) , 0);
где X 10021 для дна стыковки, 10023 для верхней части стыковки и 10020 для плавать. Значение 0 в верхнем слове означает, что сообщение отправляется из меню.
наконец, я хотел, чтобы иметь возможность показывать и скрывать панель ввода. Я заметил, что могу включить полосу стола, которая включает только одну кнопку для переключения видимости панели ввода. Spy++ing в сообщениях, опубликованных с этой кнопки, показал, что он отправляет глобальное зарегистрированное сообщение окна который называется "TabletInputPanelDeskBandClicked". Отправка этого сообщения на панель ввода заставляет его переключать видимость.
функция HideKeyboard () теперь выглядит так:
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() реализована аналогично, но она также запустит клавиатуру, если она не запущена.
обновление:
похоже, что этот обмен сообщениями между процессами запрещен в Windows Vista / 7. При выполнении этой команды в режиме без повышенных процесс он потерпит неудачу с "access denied". Я предполагаю, что это вызвано защитой изоляции процессов пользовательского интерфейса (UIPI), найденной в Windows Vista/7. Поскольку панель ввода Tablet PC работает как дочерний процесс службы, она имеет более высокий уровень целостности, чем пользовательские программы, и поэтому не может быть отправлена никаких (или очень ограниченный набор) сообщений.
обновление:
получается, что панель ввода планшетного ПК действительно работает на высоком уровне целостности, а процессы начали с ограниченной учетной записью пользователя-средний уровень целостности.
Для Windows 8:
Примечание: как и решение Windows 7, это требует повышенного процесса.
панель ввода не является потомком HWND_DESKTOP. (Это, вероятно, какое-то окно метро.) Чтобы получить дескриптор окна, выполните серию горизонтальных разверток в сетчатом тестировании шаблона с помощью WindowFromPoint (). Для каждого теста проверьте класс window родительского окна, чтобы узнать, является ли он "IPTip_Main_Window".
Показать панель ввода, запуск "C:\Program Files\Common Files\microsoft shared\ink\tabtip.exe"
. Чтобы определить, находится ли он уже в закрепленном режиме, прочитайте раздел реестра:
HKEY_CURRENT_USER\Software\Microsoft\TabletTip.7\EdgeTargetDockedState
значение 0 указывает, что панель ввода находится в плавающем режиме. Если это так, отправьте следующее сообщение, чтобы переключить закрепленное состояние:
DWORD WM_DOCK_BUTTON_PRESSED = ::RegisterWindowMessage(_TEXT("IPTipDockButtonPressed"));
PostMessage(hwndInputPanel, WM_DOCK_BUTTON_PRESSED, 0, 0);
чтобы скрыть клавиатуру, разместите следующее:
PostMessage(hwndInputPanel, WM_SYSCOMMAND, SC_CLOSE, 0);