Automatically pop up tablet touch keyboard on WinForms input focus
Solution 1
As hinted by Ofek Shilon's answer, it seems that the touch keyboard can leverage the UI automation.
One can use implementation of UI automation from UIAutomationClient.dll
.
For the UI automation to be magically injected into an application, class initializer of the assembly internal class UiaCoreApi
have to be triggered.
On can achieve that for example by calling seeming no-op:
AutomationElement.FromHandle(IntPtr)(-1)
Another way is to implement automation UI explicitly. For that implement the ITextProvider
/IValueProvider
interfaces for the respective input control.
To bind the implementation of the interfaces to the control, handle WM_GETOBJECT
window message with lParam
= RootObjectId
.
For an example of implementation, see
- tombam's answer to How to use Windows On-Screen Keyboard in C# WinForms
- or directly poster's article Implementing TextBox with on-screen touch keyboard.
Though interestingly, controls, for which touch keyboard works out-of-the-box (like combo box or password edit box, see the answer), do not implement the WM_GETOBJECT
/RootObjectId
. There must be a different machinery behind them.
Solution 2
The root cause seems to be that Winforms' textBox is not an AutomationElement, while the rest of the mentioned controls (ComboBoxes etc) are.
Quoting Markus von und zu Heber's accepted answer here:
We found it in the article "Automatic Touch Keyboard for TextBoxes in WPF Applications on Windows 8+", but it also works very good (and even easier!) for winforms. Thank you, Dmitry Lyalin!
Insert a reference to UIAutomationClient.dll to your project
In the form-load-handler of the application's main window, insert the following code:
var asForm = System.Windows.Automation.AutomationElement.FromHandle(this.Handle);
Solution 3
I've been down this road a few times and have only ever been able to implement the taptip.exe
option. And in turn close the window by killing the process. I also found out that with some registry hacks you can get the keyboard to default to the handwriting panel if you so choose. But then that only works in Win8 and fails in Win10. Here is what I've done in case anyone else finds this useful:
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");
I need to give credit to this post for the registry idea: Windows 8 Desktop App: Open tabtip.exe to secondary keyboard (for numeric textbox)
Solution 4
As far as I can tell, launching osk.exe
or tabtip.exe
pretty much is the "standard" way of making this work. I've found no "official" solution so far.
However, if it were me doing this, I wouldn't be killing the process or sending keys to try and dismiss the keyboard. Instead, you can obtain the window handle when you launch the process, and use that to minimize the window and hide it from the taskbar.
Someone here has gotten the window handle just to close it, but it gives you the idea: Show & hiding the Windows 8 on screen keyboard from WPF
If you need me to, let me know and I'll see if I can find the time to do up a full example.
Martin Prikryl
The author of WinSCP SFTP, FTP, WebDAV and S3 client.
Updated on July 09, 2022Comments
-
Martin Prikryl almost 2 years
When I run a WinForms (or Delphi, see at the end) application on Windows 10 in a tablet mode, a touch keyboard does not pop up automatically, when an input box is focused.
I believe that this should happen automatically, without any additional code/setup.
For a test, I have the simplest VS 2015 WinForms desktop application with a single
TextBox
control.It's simply the default Windows Forms Application C# project as created by Visual Studio. No code added, no properties changed. Just the
TextBox
was added, by dropping from the Toolbox (again no properties changed):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;
To verify my assumption that the pop up should be automatic:
-
I've tried to run Windows XP version of
notepad.exe
on Windows 10. It automatically pops up the touch keyboard. I doubt the Windows XP had any explicit support for touch keyboards. -
I've also tried some ancient MFC applications (for example FileZilla 2.2.15 from 2005). It also pops up the touch keyboard on all its input boxes. Again, I'm pretty sure, the MFC had no explicit support for touch keyboards either.
-
The same for applications built on wxWidgets (for example FileZilla 3.x).
It looks like there's something broken in WinForms that prevents the automatic popup. Interestingly, the automatic pop up works:
- for (editable) combo boxes (
ComboBox
withDropDownStyle = DropDown
) - for text boxes in a password mode (
TextBox.PasswordChar
) - for rich text boxes (
RichTextBox
) - when the input box has focus at the moment the hardware keyboard is "removed" (I test this by flipping the screen on Lenovo Yoga notebook), but never after.
I've seen all the hints about an explicit popup by running the
TabTip.exe
. E.g.:- How to use Windows On-Screen Keyboard in C# WinForms
- Open and close Windows 8 touch keyboard tabtip under desktop
- How do I close the on-screen keyboard process from C# winform correctly?
- Keyboard Winforms on Windows 10 (surface)
Most of the "solutions" offer a code like this:
var progFiles = @"C:\Program Files\Common Files\Microsoft Shared\ink"; var keyboardPath = Path.Combine(progFiles, "TabTip.exe"); this.keyboardProc = Process.Start(keyboardPath);
But I cannot believe this could be the "official" way. If for nothing else, then because there's no clean way to hide the keyboard opened by running the
TabTip.exe
(solutions include hacks like killing the process or sending Esc key).And actually the above hack does not seem to work anymore in Windows 10 Anniversary Update:
Interestingly, I see the same behavior with Delphi/C++ Builder/VCL applications. The keyboard does not pop up for edit boxes (
TEdit
). It does pop up for combo boxes (TComboBox
) and for edit boxes in a password mode (PasswordChar
). Interestingly not forTRichEdit
, what is notable difference to .NETRichTextBox
, that maybe worth investigating.This (unanswered) question describes an identical behavior:
Application written Delphi XE8 touch in edit boxes keyboard not appear in Windows 10. -
-
Martin Prikryl about 8 yearsThanks for your answer. So why does it work for MFC/wxWidgets or for combo box?
-
Martin Prikryl about 8 yearsThanks for your answer. But as I commented to the other answer already: So why does it work for MFC/wxWidgets or for combo box?
-
jaredbaszler about 8 years@MartinPrikryl - I can't comment on that as I've never used those widgets. One would like to think there is an easier way to pop-up the built in, on-screen keyboard but as you've researched, it doesn't look like that's possible.
-
Martin Prikryl over 7 yearsCalling the
AutomationElement.FromHandle(handle)
has indeed the effect I was looking for. But it's just a side effect. You can actually pass anything to the method, including an invalid handle like(IntPtr)(-1)
. All that matters is that the method implementation uses an internal classUiaCoreApi
. It's class initializer does some magic, that makes the touch keyboard popup for edit boxes. But it also does zillions of other things and loads many unrelated assemblies, all with unknown side effects that I'm not willing to blindly use. -
Martin Prikryl over 7 yearsThanks anyway. Maybe someone can built upon this information. I've spent many hours trying to find what the real trigger is, but I didn't succeed.
-
Martin Prikryl over 7 yearsActually it might be that the touch keyboard can actually leverage the UI automation, if implemented by the application. And that's what the
UiaCoreApi
initializer does. Maybe some one can confirm this. -
Martin Prikryl almost 7 yearsThanks. This is an interesting observation, though not an acceptable solution. I've added this information to my question anyway.
-
jaredbaszler over 5 years@MartinPrikryl - I stumbled across this answer for getting this to work in Win10. I'm in the situation that I need it to work in Win10 so I found this. I haven't tried it yet but looks popular enough that others have had success with it. stackoverflow.com/questions/38774139/…
-
Grant Johnson over 4 yearsThanks for diving into this Martin. I ended up using this solution here. These are the kind of things that drive me nuts and I would have spent enormous amounts of time chasing this down. I wish I could +10 this post.