Когда я запускаю приложение WinForms (или Delphi, см. в конце) в Windows 10 в режиме планшета, сенсорная клавиатура делает не открывается автоматически, когда поле ввода сфокусировано.
Я считаю, что это должно происходить автоматически, без какого-либо дополнительного кода/настройки.
Для теста у меня есть простейшее настольное приложение VS 2015 WinForms с одним TextBox
control.
Это просто проект Windows Forms Application С# по умолчанию, созданный Visual Studio. Код не добавлен, свойства не изменены. Добавлен только TextBox
, сбросив с панели инструментов (опять же никаких свойств не изменилось):
this.textBox1 = new System.Windows.Forms.TextBox();
this.textBox1.Location = new System.Drawing.Point(64, 27);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 0;
Чтобы проверить мое предположение, что всплывающее окно должно быть автоматическим:
Я попытался запустить Windows XP версии notepad.exe
в Windows 10. Он автоматически всплывает сенсорная клавиатура. Я сомневаюсь, что у Windows XP была явная поддержка сенсорных клавиш.
Я также пробовал некоторые древние приложения MFC (например, FileZilla 2.2.15 от 2005). Он также всплывает сенсорная клавиатура во всех своих вводах. Опять же, я уверен, у MFC не было явной поддержки сенсорных клавиш.
То же самое для приложений, построенных на wxWidgets (например, FileZilla 3.x).
Похоже, что в WinForms что-то сломалось, что предотвращает автоматическое всплывающее окно. Интересно, что автоматическое всплывающее меню работает:
ComboBox
с DropDownStyle = DropDown
)TextBox.PasswordChar
)RichTextBox
)Я видел все подсказки о явном всплывающем меню, запустив TabTip.exe
. Например:.
Большинство "решений" предлагают такой код:
var progFiles = @"C:\Program Files\Common Files\Microsoft Shared\ink";
var keyboardPath = Path.Combine(progFiles, "TabTip.exe");
this.keyboardProc = Process.Start(keyboardPath);
Но я не могу поверить, что это может быть "официальным" способом. Если ничего другого, то, потому что нет чистого способа скрыть клавиатуру, открытую при запуске TabTip.exe
(решения включают взломы, такие как убийство процесса или отправка ключа Esc).
И на самом деле вышеупомянутый хак, похоже, больше не работает в обновлении Windows 10 Anniversary:
Интересно, что я вижу такое же поведение с приложениями Delphi/С++ Builder/VCL. Клавиатура не появляется для полей редактирования (TEdit
). Он появляется для комбинированных ящиков (TComboBox
) и для полей редактирования в режиме пароля (PasswordChar
). Интересно, что не для TRichEdit
, что заметно отличается от .NET RichTextBox
, что, возможно, стоит исследовать.
Этот (неотвеченный) вопрос описывает одинаковое поведение:
Приложение, написанное Delphi XE8 touch в клавиатуре редактирования, не отображается в Windows 10.
Как намекнул Ofek Shilon answer, кажется, что сенсорная клавиатура может использовать интерфейс автоматизация.
Можно использовать реализацию автоматизации пользовательского интерфейса от UIAutomationClient.dll
.
Для автоматизации ввода пользовательского интерфейса в приложение должен запускаться инициализатор класса внутреннего класса сборки UiaCoreApi
.
On может достичь этого, например, вызывая no-op:
AutomationElement.FromHandle(IntPtr)(-1)
Еще один способ - явно реализовать интерфейс автоматизации. Для этого выполните ITextProvider
/IValueProvider
для соответствующего управления вводом.
Чтобы связать реализацию интерфейсов с элементом управления, откройте WM_GETOBJECT
сообщение окна с помощью lParam
= RootObjectId
.
Пример реализации см. в
Хотя интересно, элементы управления, для которых сенсорная клавиатура работает из коробки (например, поле со списком или окно редактирования пароля, см. ответ), не реализуйте WM_GETOBJECT
/RootObjectId
. За ними должен быть другой механизм.
Я несколько раз ездил по этой дороге и только когда-либо мог реализовать опцию taptip.exe
. И, в свою очередь, закройте окно, убив процесс. Я также узнал, что с некоторыми хаками реестра вы можете получить клавиатуру по умолчанию для панели рукописного ввода, если вы этого захотите. Но тогда это работает только в Win8 и терпит неудачу в Win10. Вот что я сделал в случае, если кто-то еще найдет это полезным:
RegistryKey registryKey = Registry.CurrentUser.CreateSubKey("Software\\Microsoft\\TabletTip\\1.7");
registryKey?.SetValue("KeyboardLayoutPreference", 0, RegistryValueKind.DWord);
registryKey?.SetValue("LastUsedModalityWasHandwriting", 1, RegistryValueKind.DWord);
Process.Start(@"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe");
Мне нужно отдать должное этому сообщению за идею реестра: Windows 8 Desktop App: Открыть tabtip.exe на вторичной клавиатуре (для числового текстового поля)
Основная причина, по-видимому, в том, что текстовый блок Winforms не является элементом AutomationElement, а остальные элементы управления (ComboBoxes и т.д.).
Цитирование Markus von und zu Heber принятый ответ здесь:
Мы нашли это в статье " Автоматическая сенсорная клавиатура для текстовых полей в Приложения WPF в Windows 8+", но он также работает очень хорошо (и даже проще!) для winforms. Спасибо, Дмитрий Лялин!
Вставьте ссылку на UIAutomationClient.dll в свой проект
В обработчике формы-приложения главного окна приложения вставьте следующий код:
var asForm = System.Windows.Automation.AutomationElement.FromHandle(this.Handle);
AutomationElement.FromHandle(handle)
действительно дает эффект, который я искал. Но это всего лишь побочный эффект. На самом деле вы можете передать в метод все что угодно, включая недопустимый дескриптор, такой как (IntPtr)(-1)
. Все, что имеет значение, - это то, что реализация метода использует внутренний класс UiaCoreApi
. Это инициализатор класса, который делает магию, которая заставляет сенсорную клавиатуру всплывающее окно для редактирования. Но это также делает миллионы других вещей и загружает много несвязанных сборок, все с неизвестными побочными эффектами, которые я не хочу слепо использовать.
Насколько я могу судить, запуск osk.exe
или tabtip.exe
в значительной степени является "стандартным" способом выполнения этой работы. До сих пор я не нашел "официального" решения.
Однако, если бы я это делал, я бы не стал убивать процесс или отправлять ключи, чтобы попытаться убрать клавиатуру. Вместо этого вы можете получить дескриптор окна при запуске процесса и использовать его для минимизации окна и скрыть его из панели задач.
Кто-то здесь получил дескриптор окна, чтобы закрыть его, но он дает вам идею: Показывать и скрывать Windows 8 на экранной клавиатуре из WPF
Если вам нужно, дайте мне знать, и я посмотрю, смогу ли я найти время, чтобы сделать полный пример.
Используйте RichTextBox вместо элемента управления TextBox. RichTextBox поддерживает сенсорную клавиатуру и автоматически всплывает на клавиатуре при достижении фокуса. (аналогично другим элементам управления ввода, например, поле со списком)
RichTextBox также поддерживает те же свойства, что и TextBox, поэтому в большинстве случаев это должно быть снижение. (Оба элемента управления получают из TextBoxBase)
Я заметил, что если сенсорная клавиатура была уволена после того, как она всплывает, вам может потребоваться дважды нажать на элемент управления, чтобы заставить его вернуться назад.