Как использовать экранную клавиатуру Windows в С# WinForms
- VS 2010
- Разработка 32-разрядного приложения, работающего на 64-разрядной ОС (Windows 7, Windows 8 - приложение для настольных компьютеров)
- С#
- .NET 4.0
- WinForms
Я обнаружил много потоков при запуске экранной клавиатуры Windows (osk.exe
) из приложения, но у меня возникают некоторые проблемы. Это происходит потому, что я запускаю 32-битное приложение на 64-битной ОС. Я попробовал код, опубликованный WooCaSh здесь: клавиатура на экране в WinForms
Но ни один из трех разных путей не работает для меня. Для sysnative
пути Process.Start
завершается с ошибкой "Не удается найти указанный путь". Для путей system32
и osk.exe
я получаю диалоговое окно с сообщением об ошибке "Не удалось запустить экранную клавиатуру".
Я нашел здесь возможный обходной путь, который немного сложнее, чем я искал (сообщение от eryang): http://social.msdn.microsoft.com/Forums/en-US/netfx64bit/thread/10ebc62f-e6d7 -4072-9fd1-ea3784a0966f/
- Есть ли более простой или правильный способ сделать это?
- Я надеялся, что запуск моего приложения на планшете автоматически запустит экранную клавиатуру, когда пользователь выберет текстовое поле, но не повезло. Это нормально или я что-то упустил? Я обнаружил, что клавиатура не запускается автоматически в Windows 8 в режиме рабочего стола (которым является мое приложение): http://www.bleepingcomputer.com/forums/t/480250/keyboard-does-not-pop-up -автоматически/по- видимому, это работает на планшетах Windows 7, но я не могу проверить, потому что у меня есть только планшеты Windows 8 здесь.
Ответы
Ответ 1
Сейчас я запускаю "Сенсорную клавиатуру", а не "Экранную клавиатуру" (это клавиатура, которую я хотел в Windows 8 в любом случае) с:
string progFiles = @"C:\Program Files\Common Files\Microsoft Shared\ink";
string keyboardPath = Path.Combine(progFiles, "TabTip.exe");
this.keyboardProc = Process.Start(keyboardPath);
Это работает на моих Win7 и Win8, независимо от моего 32-битного приложения на 64-битной ОС. Тем не менее, у меня все еще есть проблема программного закрытия клавиатуры, когда я закончу. Процесс this.keyboardProc
, похоже, не получает дескриптор и сразу же имеет свойство HasExited = true
. Это означает, что мои попытки закрыть или убить его не удаются.
Согласно этой теме, если пользователь вручную открывает клавиатуру (или я запускаю ее программно), клавиатура не будет автоматически закрываться/скрываться, когда текстовое поле теряет фокус: Windows 8 - Как отменить сенсорную клавиатуру? Я попробовал обходной путь установки фокуса на скрытую кнопку, но так как я сам запустил клавиатуру, она не закрывается автоматически.
Ответ 2
У меня были проблемы с закрытием экранной клавиатуры. Вы можете запустить сенсорную клавиатуру с
string progFiles = @"C:\Program Files\Common Files\Microsoft Shared\ink";
string onScreenKeyboardPath = System.IO.Path.Combine(progFiles, "TabTip.exe");
onScreenKeyboardProc = System.Diagnostics.Process.Start(onScreenKeyboardPath);
и закройте все клавиатуры с
//Kill all on screen keyboards
Process[] oskProcessArray = Process.GetProcessesByName("TabTip");
foreach (Process onscreenProcess in oskProcessArray)
{
onscreenProcess.Kill();
}
По какой-то причине onScreenKeyboardProc.Kill() или.Close() не работает.
Ответ 3
Чтобы клавиатура открывалась автоматически, элементы управления должны реализовывать некоторые шаблоны элементов управления UI Automation, в частности, ITextProvider/IValueProvider. Это неприятно, но это работает (и это более чистый способ, чем запуск некоторых *.exe)
Я написал пример приложения и небольшую статью здесь: http://blog.tombam.net/implementing-textbox-with-on-screen-touch-keyboard-part-1/
Ответ 4
Сенсорная клавиатура использует автоматизацию пользовательского интерфейса. По некоторым причинам, которые для меня загадка, стандартное окно редактирования Windows не реализует автоматический интерфейс, в то время как другие элементы управления, такие как комбинированное окно, делают это.
Можно использовать реализацию автоматизации пользовательского интерфейса из UIAutomationClient.dll
.
Чтобы автоматизация пользовательского интерфейса была волшебным образом внедрена в приложение, должен быть запущен инициализатор класса внутреннего класса сборки UiaCoreApi
.
Это можно сделать, например, с помощью вызова no-op:
AutomationElement.FromHandle(IntPtr)(-1)
Другой способ - реализовать интерфейс автоматизации в явном виде. Для этого необходимо реализовать интерфейсы ITextProvider
/ IValueProvider
для соответствующего IValueProvider
управления вводом.
Для привязки реализации интерфейсов к WM_GETOBJECT
управления обработайте сообщение окна WM_GETOBJECT
с помощью lParam
= RootObjectId
.
Пример реализации см.
Интересно, что элементы управления, для которых сенсорная клавиатура работает "из коробки" (например, поле со списком или окно редактирования пароля, см. Ответ), не реализуют WM_GETOBJECT
/RootObjectId
. За ними должен быть другой механизм.
Наиболее распространенное "решение" этой проблемы - явное всплывающее окно клавиатуры с помощью TabTip.exe
или osk.exe
- вряд ли приемлемо.
Если ни для чего другого, то потому, что нет чистого способа скрыть открытую клавиатуру, запустив TabTip.exe
(решения включают в себя такие хаки, как уничтожение процесса или отправка клавиши Esc).
И на самом деле вышеупомянутый хак больше не работает в Windows 10 Anniversary Update: Показать сенсорную клавиатуру (TabTip.exe) в Windows 10 Anniversary Edition.
Ответ 5
Запуск TabTip.exe больше не работает в Widnows 10 Anniversary Edition. Я обнаружил недокументированный COM-интерфейс для управления сенсорной клавиатурой. Проверьте код здесь fooobar.com/info/166376/...