【问题标题】:How to use Windows On-Screen Keyboard in C# WinForms如何在 C# WinForms 中使用 Windows 屏幕键盘
【发布时间】:2013-03-11 09:23:36
【问题描述】:
  • VS 2010
  • 开发在 64 位操作系统上运行的 32 位应用程序(Windows 7、Windows 8 - 桌面应用程序)
  • C#
  • .NET 4.0
  • WinForms

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

但是这三种不同的路径都不适合我。对于 sysnative 路径,Process.Start 失败并显示 “找不到指定的路径。” 对于 system32osk.exe 路径,我得到 “无法启动 on -屏幕键盘”错误对话框。

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

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

【问题讨论】:

  • 只需将您的 EXE 项目的平台目标设置更改为“AnyCPU”。
  • 不幸的是,它需要 x86 才能用于与之交互的某些 3rd 方软件。
  • 只是为了测试,我继续更改为“AnyCPU”。键盘仍然无法在我的 Win7 64 位桌面上启动,但在 Win8 64 位平板电脑上启动。有什么想法吗?
  • 我已经实现了 [这里][1] 描述的方法。它也适用于Win7。 [1]:stackoverflow.com/questions/15183720/wpf-windows-8-tabtip-close

标签: c# windows winforms 32bit-64bit on-screen-keyboard


【解决方案1】:

我现在正在启动“触摸键盘”而不是“屏幕键盘”(无论如何,这是我在 Windows 8 上想要的键盘):

string progFiles = @"C:\Program Files\Common Files\Microsoft Shared\ink";
string keyboardPath = Path.Combine(progFiles, "TabTip.exe");

this.keyboardProc = Process.Start(keyboardPath);

无论我在 64 位操作系统上的 32 位应用程序如何,这都适用于我的 Win7 和 Win8。但是,完成后我仍然遇到以编程方式关闭键盘的问题。进程this.keyboardProc 似乎没有得到句柄,并立即拥有属性HasExited = true。这意味着我尝试关闭或杀死它失败了。

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

【讨论】:

  • 干得好!我在这个废话上浪费了至少一个小时。您的解决方案帮助了我。
  • 在 Windows 10 平板电脑上也为我工作。没有什么比让恐龙活着...
  • 请注意,您可能没有安装“Tablet PC 组件”windows 功能...如果没有转到“控制面板”、“程序”和“关闭或打开 Windows 功能”
  • 似乎现在可能需要在 Windows10 上才能使其在桌面模式下工作:Registry.SetValue("HKEY_CURRENT_USER\Software\Microsoft\TabletTip\1.7", "EnableDesktopModeAutoInvoke", 1);
【解决方案2】:

我无法关闭屏幕键盘。您可以使用

启动触控键盘
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() 不起作用。

【讨论】:

    【解决方案3】:

    要让键盘自动打开,控件必须实现一些 UI 自动化控制模式,特别是 ITextProvider/IValueProvider。这很麻烦,但它可以工作(而且它比启动一些 *.exe 更干净)

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

    【讨论】:

    • 很棒的文章!您是否找到了强制使用数字键盘的方法?
    【解决方案4】:

    触摸键盘利用 UI 自动化。由于某些对我来说很神秘的原因,标准的 Windows 编辑框没有实现 UI 自动化,而其他控件(如组合框)可以实现。


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

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

    On 可以实现这一点,例如通过调用似乎无操作:

    AutomationElement.FromHandle(IntPtr)(-1)
    

    另一种方法是显式实现自动化 UI。为此,为相应的输入控件实现ITextProvider/IValueProvider 接口。

    要将接口的实现绑定到控件,请将WM_GETOBJECT window message 处理为lParam = RootObjectId

    有关实现示例,请参阅

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


    对此问题最常见的“解决方案”,即通过运行TabTip.exeosk.exe 显式弹出键盘,是难以接受的。

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

    实际上,上述 hack 在 Windows 10 周年更新中似乎不再适用:Show touch keyboard (TabTip.exe) in Windows 10 Anniversary edition

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        我在这里和其他地方冲浪然后我实现了这个:

        using System.Diagnostics; // remember use this
        
        public partial class Window1 : Window
        {
        
            public Process _p = null;
           
            public Window1()
            {
                InitializeComponent();          
            }
        
            public void Button_Click(object sender, RoutedEventArgs e)
            {
                if (_p != null)
                {
                    _p.Kill();
                    _p.Dispose();
                    _p = null;
                }
                _p = Process.Start(@"C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe");    
            }
        
            private void Acceso_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            {
                if (_p != null)
                {
                    _p.Kill();
                    _p.Dispose();
                    _p = null;
                }
            }
        }
        

        它工作正常,所以我在这里分享它,以防你的信息对我有所帮助。

        【讨论】:

        • 感谢您包含缺失的行,您是对的,这里已经存在的信息和其他网络对我有帮助,我只是以适合我的情况的方式收集它们,我希望它可以帮助其他人。感谢您的反馈。
        猜你喜欢
        • 2012-03-07
        • 2012-12-17
        • 2013-08-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多