Автоматически всплывающая сенсорная клавиатура планшета на фокусе ввода WinForms

32

Когда я запускаю приложение WinForms (или Delphi, см. в конце) в Windows 10 в режиме планшета, сенсорная клавиатура делает не открывается автоматически, когда поле ввода сфокусировано.

Я считаю, что это должно происходить автоматически, без какого-либо дополнительного кода/настройки.


Для теста у меня есть простейшее настольное приложение VS 2015 WinForms с одним TextBox control.

Изображение 686

Это просто проект 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)
  • когда поле ввода имеет фокус в момент удаления аппаратной клавиатуры (я проверяю это, перелистывая экран на ноутбуке Lenovo Yoga), но никогда не после.

Я видел все подсказки о явном всплывающем меню, запустив 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.

  • 0
    Вы пробовали это с 2 текстовыми полями и изменением фокуса? Когда-то у меня было нечто подобное, когда было поле ввода, которое фокусировалось при запуске. Каким-то образом это событие было пропущено «ОС (?)». Исправлено это путем установки начального фокуса на другой элемент управления.
  • 0
    @ Стефан Конечно. Мне действительно нужно это для большого приложения. Я просто свел проблему к простому тестовому приложению только для целей этого вопроса.
Показать ещё 2 комментария
Теги:
winforms
touch

5 ответов

0
Лучший ответ

Как намекнул Ofek Shilon answer, кажется, что сенсорная клавиатура может использовать интерфейс автоматизация.


Можно использовать реализацию автоматизации пользовательского интерфейса от UIAutomationClient.dll.

Для автоматизации ввода пользовательского интерфейса в приложение должен запускаться инициализатор класса внутреннего класса сборки UiaCoreApi.

On может достичь этого, например, вызывая no-op:

AutomationElement.FromHandle(IntPtr)(-1)

Еще один способ - явно реализовать интерфейс автоматизации. Для этого выполните ITextProvider/IValueProvider для соответствующего управления вводом.

Чтобы связать реализацию интерфейсов с элементом управления, откройте WM_GETOBJECT сообщение окна с помощью lParam= RootObjectId.

Пример реализации см. в


Хотя интересно, элементы управления, для которых сенсорная клавиатура работает из коробки (например, поле со списком или окно редактирования пароля, см. ответ), не реализуйте WM_GETOBJECT/RootObjectId. За ними должен быть другой механизм.

8

Я несколько раз ездил по этой дороге и только когда-либо мог реализовать опцию 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 на вторичной клавиатуре (для числового текстового поля)

  • 0
    Спасибо за Ваш ответ. Но, как я уже прокомментировал другой ответ: так почему это работает для MFC / wxWidgets или для поля со списком?
  • 0
    @MartinPrikryl - я не могу комментировать это, поскольку я никогда не использовал эти виджеты. Можно подумать, что есть более простой способ открыть встроенную экранную клавиатуру, но, как вы выяснили, это не выглядит возможным.
Показать ещё 1 комментарий
6

Основная причина, по-видимому, в том, что текстовый блок Winforms не является элементом AutomationElement, а остальные элементы управления (ComboBoxes и т.д.).

Цитирование Markus von und zu Heber принятый ответ здесь:

Мы нашли это в статье " Автоматическая сенсорная клавиатура для текстовых полей в Приложения WPF в Windows 8+", но он также работает очень хорошо (и даже проще!) для winforms. Спасибо, Дмитрий Лялин!

  • Вставьте ссылку на UIAutomationClient.dll в свой проект

  • В обработчике формы-приложения главного окна приложения вставьте следующий код:

    var asForm = System.Windows.Automation.AutomationElement.FromHandle(this.Handle);
    
  • 2
    Вызов AutomationElement.FromHandle(handle) действительно дает эффект, который я искал. Но это всего лишь побочный эффект. На самом деле вы можете передать в метод все что угодно, включая недопустимый дескриптор, такой как (IntPtr)(-1) . Все, что имеет значение, - это то, что реализация метода использует внутренний класс UiaCoreApi . Это инициализатор класса, который делает магию, которая заставляет сенсорную клавиатуру всплывающее окно для редактирования. Но это также делает миллионы других вещей и загружает много несвязанных сборок, все с неизвестными побочными эффектами, которые я не хочу слепо использовать.
  • 0
    Спасибо, в любом случае. Может быть, кто-то может опираться на эту информацию. Я потратил много часов, пытаясь выяснить, что же такое настоящий триггер, но мне это не удалось.
Показать ещё 1 комментарий
5

Насколько я могу судить, запуск osk.exe или tabtip.exe в значительной степени является "стандартным" способом выполнения этой работы. До сих пор я не нашел "официального" решения.

Однако, если бы я это делал, я бы не стал убивать процесс или отправлять ключи, чтобы попытаться убрать клавиатуру. Вместо этого вы можете получить дескриптор окна при запуске процесса и использовать его для минимизации окна и скрыть его из панели задач.

Кто-то здесь получил дескриптор окна, чтобы закрыть его, но он дает вам идею: Показывать и скрывать Windows 8 на экранной клавиатуре из WPF

Если вам нужно, дайте мне знать, и я посмотрю, смогу ли я найти время, чтобы сделать полный пример.

  • 1
    Спасибо за Ваш ответ. Так почему же это работает для MFC / wxWidgets или для поля со списком?
1

Используйте RichTextBox вместо элемента управления TextBox. RichTextBox поддерживает сенсорную клавиатуру и автоматически всплывает на клавиатуре при достижении фокуса. (аналогично другим элементам управления ввода, например, поле со списком)

RichTextBox также поддерживает те же свойства, что и TextBox, поэтому в большинстве случаев это должно быть снижение. (Оба элемента управления получают из TextBoxBase)

Я заметил, что если сенсорная клавиатура была уволена после того, как она всплывает, вам может потребоваться дважды нажать на элемент управления, чтобы заставить его вернуться назад.

  • 0
    Благодарю. Это интересное наблюдение, хотя и не приемлемое решение. Я все равно добавил эту информацию в свой вопрос.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню