如何在C#WinForms中使用Windows屏幕键盘

  • VS 2010
  • 开发在64位操作系统上运行的32位应用程序(Win7,Win8 – 桌面应用程序)
  • C#
  • .NET 4.0
  • 的WinForms

我从应用程序启动Windows屏幕键盘(osk.exe)时发现了许multithreading,但遇到了一些问题。 这似乎是因为我在64位操作系统上运行32位应用程序。 我已经尝试过WooCaSh发布的代码: WinForms屏幕上的键盘

但这三种不同的路径都不适合我。 对于“sysnative”路径,Process.Start“找不到指定的路径”。 对于system32和osk.exe路径,我得到“无法启动屏幕键盘”错误对话框。

我在这里找到了一个可能的解决方法,这比我想要的更复杂一点(由eryang发布): http ://social.msdn.microsoft.com/Forums/en-US/netfx64bit/thread/10ebc62f-e6d7 -4072-9fd1-ea3784a0966f /

  1. 有没有更简单或正确的方法来做到这一点?
  2. 我希望在平板电脑上运行我的应用程序会在用户选择文本框时自动启动屏幕键盘,但没有运气。 这是正常还是我错过了什么? 编辑 :发现在桌面模式(我的应用程序是)时,键盘不会在Win8中自动启动: http : //www.bleepingcomputer.com/forums/t/480250/keyboard-does-not-pop-up-automatically /显然它适用于Win7平板电脑,但我无法测试,因为我这里只有Win8平板电脑。

我正在推出“触摸键盘”而不是“屏幕键盘”(这是我在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,无论我在64位操作系统上的32位应用程序如何。 但是,当我完成时,我仍然遇到以编程方式关闭键盘的问题。 进程this.keyboardProc似乎没有获取句柄,并立即具有属性HasExited = true。 这意味着我关闭或杀死它的尝试失败了。

根据这个post,如果用户手动打开键盘(或者我以编程方式启动它),当文本字段失去焦点时,键盘将不会自动关闭/隐藏: Windows 8 – 如何关闭触摸键盘? 我尝试了将焦点设置为隐藏按钮的解决方法,但由于我自己启动了键盘,因此它不会自动关闭。

我无法关闭屏幕键盘。 您可以使用启动触摸键盘

  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()不起作用。

要使键盘自动打开,控件必须实现一些UI自动化控件模式,特别是ITextProvider / IValueProvider。 这是一个麻烦,但它的工作原理(它比启动一些* .exe更简洁)

我在这里写了一个示例应用程序和一篇简短的文章: http : //blog.tombam.net/implementing-textbox-with-on-screen-touch-keyboard-part-1/

触摸键盘利用UI自动化。 由于某些原因对我来说是个谜,标准的Windows编辑框不会自动实现UI,而其他控件(如combobox)也可以。


可以使用UIAutomationClient.dll实现UI自动化。

为了将UI自动化神奇地注入到应用程序中,必须触发程序集内部类UiaCoreApi类初始化程序。

On可以实现这一点,例如通过调用seeming no-op:

 AutomationElement.FromHandle(IntPtr)(-1) 

另一种方法是明确地实现自动化UI。 对于该实现, ITextProvider / IValueProvider接口用于相应的输入控件。

要将接口的实现绑定到控件,请使用lParam = RootObjectId处理WM_GETOBJECT窗口消息 。

有关实现的示例,请参阅

  • tombam对这个问题的回答 ;
  • 或直接海报的文章用屏幕触摸键盘实现TextBox 。

虽然有趣的是,触摸键盘开箱即用的控件(如combobox或密码编辑框,请参阅答案),但不实现WM_GETOBJECT / RootObjectId 。 它们背后必定有不同的机制。


这个问题最常见的“解决方案”是通过运行TabTip.exeosk.exe来显式弹出键盘,这是不可接受的。

如果没有别的,那么因为没有干净的方法来隐藏通过运行TabTip.exe打开的键盘(解决方案包括杀死进程或发送Esc键等黑客攻击)。

实际上,在Windows 10周年纪念版更新中,上述黑客攻击似乎不再起作用: 在Windows 10周年纪念版中显示触控键盘(TabTip.exe) 。

启动TabTip.exe不再适用于Widnows 10周年纪念版。 我发现了一个用于控制触摸键盘的未记录的COM接口。 检查代码https://stackoverflow.com/a/40921638/332528