2016-03-23 1 views
32

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

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


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

enter image description here

Это просто по умолчанию, как созданный Visual Studio # проект приложения Windows Forms C. Код не добавлен, свойства не изменены. Только TextBox был добавлен, понижая из Toolbox (опять же никаких свойств не изменилось):

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

B Я не могу поверить, что это может быть «официальным» способом. Если ни для чего другого, то, потому что нет чистого способа скрыть клавиатуру, открытую, запустив TabTip.exe (решения включают взломы, такие как убийство процесса или отправка Esc).

И на самом деле выше хак не кажется больше работать в ОС Windows 10 Anniversary Update:


Интересно, что я вижу такое же поведение с Delphi/C++ Builder/VCL. Клавиатура не отображается для полей редактирования (TEdit). Он появляется для комбинированных полей (TComboBox) и для полей ввода в режиме пароля (PasswordChar). Интересно, что не для TRichEdit, что примечательная разница с .NET RichTextBox, что, возможно, стоит исследовать.

Этот вопрос (вопрос без ответа) описывает то же поведение:
Application written Delphi XE8 touch in edit boxes keyboard not appear in Windows 10.

+0

Вы пробовали это с 2 текстовыми полями и сменой фокуса? У меня было что-то подобное однажды, когда появился ящик ввода, который получил фокус при запуске. Как-то это событие было упущено «ОС (?)». Исправлено, установив фокус запуска на другой элемент управления. – Stefan

+0

@Stefan Конечно. Мне действительно нужно это для большого приложения. Я просто уменьшил проблему до простого тестового приложения только для целей этого вопроса. –

+0

На каком устройстве вы работаете? Windows 10 имеет некоторые внутренние эвристики, чтобы решить, нужно ли им на самом деле показывать клавиатуру или нет, в зависимости от ряда факторов. Режим таблеток недостаточно, чтобы «заставить» клавиатуру отображать. В моей Книге Поверхностей я должен физически отсоединить клавиатуру для OSK, чтобы она показывалась автоматически (или была принудительной с использованием трюков и обходных решений) – o0rebelious0o

ответ

0

Как подсказывает Ofek Shilon's answer, кажется, что сенсорная клавиатура может использовать UI automation.


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

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

В можно добиться того, что, например, по телефону не представляясь не-оп:

AutomationElement.FromHandle(IntPtr)(-1) 

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

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

Для примера реализации, см ответ


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

5

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

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

Кто здесь получил дескриптор окна просто закрыть его, но это дает вам идею: Show & hiding the Windows 8 on screen keyboard from WPF

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

+1

Спасибо за ваш ответ. Так почему он работает для MFC/wxWidgets или для комбинированного поля? –

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: Open tabtip.exe to secondary keyboard (for numeric textbox)

+0

Спасибо за ваш ответ. Но поскольку я уже прокомментировал другой ответ: почему он работает для MFC/wxWidgets или для комбо-поля? –

+0

@MartinPrikryl - я не могу комментировать это, поскольку я никогда не использовал эти виджеты. Хотелось бы подумать, что есть более простой способ всплывать встроенной экранной клавиатуры, но как вы исследовали, похоже, что это невозможно. – jaredbaszler

6

Основная причина, кажется, что TextBox WinForms' не является элементом AutomationElement, а остальные элементы управления (ComboBoxes и т. д.).

Цитирование Markus фон унд цу Хибера accepted answer here:

Мы нашли его в статье «Automatic Touch Keyboard for TextBoxes in WPF Applications on Windows 8+», но он также работает очень хорошо (и даже проще!) Для WinForms. Спасибо, Дмитрий Лялин!

  1. Вставьте ссылку на UIAutomationClient.dll вашего проект

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

    var asForm = System.Windows.Automation.AutomationElement.FromHandle(this.Handle); 
    
+2

Вызов 'AutomationElement.FromHandle (handle)' действительно имеет эффект, который я искал. Но это всего лишь побочный эффект. Фактически вы можете передать что-либо методу, включая недопустимый дескриптор типа '(IntPtr) (- 1)'. Все, что имеет значение, заключается в том, что реализация метода использует внутренний класс 'UiaCoreApi'. Это инициализатор класса делает некоторую магию, что делает всплывающее окно сенсорной клавиатуры для полей редактирования. Но он также делает множество других вещей и загружает множество несвязанных сборок, все с неизвестными побочными эффектами, которые я не желаю слепо использовать. –

+0

Спасибо в любом случае. Может быть, кто-то может построить эту информацию. Я потратил много часов, пытаясь найти, что такое настоящий триггер, но мне это не удалось. –

+0

На самом деле, возможно, сенсорная клавиатура может фактически использовать автоматизацию пользовательского интерфейса, если она реализована приложением. И это то, что делает инициализатор 'UiaCoreApi'. Может быть, кто-то может это подтвердить. –

1

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

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

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

+0

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