繁体   English   中英

在 WinForms 输入焦点上自动弹出平板触摸键盘

[英]Automatically pop up tablet touch keyboard on WinForms input focus

当我以平板电脑模式在 Windows 10 上运行 WinForms(或 Delphi,见文末)应用程序时,当输入框聚焦时,触摸键盘不会自动弹出。

我相信这应该自动发生,没有任何额外的代码/设置。


为了测试,我有一个最简单的 VS 2015 WinForms 桌面应用程序,带有一个TextBox控件

在此处输入图片说明

它只是 Visual Studio 创建的默认 Windows 窗体应用程序 C# 项目。 未添加代码,未更改任何属性。 通过从工具箱中删除(同样没有更改属性),只添加了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 10 上运行 Windows XP 版本的notepad.exe 。它会自动弹出触摸键盘。 我怀疑 Windows XP 是否明确支持触摸键盘。

  • 我还尝试了一些古老的 MFC 应用程序(例如 2005 年的 FileZilla 2.2.15)。 它还会在其所有输入框上弹出触摸键盘。 同样,我很确定,MFC 也没有明确支持触摸键盘。

  • 构建在 wxWidgets 上的应用程序(例如 FileZilla 3.x)也是如此。


看起来 WinForms 中的某些东西阻止了自动弹出窗口。 有趣的是,自动弹出的工作原理是:

  • 对于(可编辑的)组合框( ComboBox with DropDownStyle = DropDown
  • 用于密码模式下的文本框 ( TextBox.PasswordChar )
  • 对于富文本框 ( RichTextBox )
  • 当输入框在硬件键盘被“移除”的那一刻有焦点时(我通过在联想瑜伽笔记本上翻转屏幕来测试),但永远不会。

我已经通过运行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键之类的黑客攻击)。

实际上,上述 hack 在 Windows 10 周年更新中似乎不再起作用:


有趣的是,我在 Delphi/C++ Builder/VCL 应用程序中看到了相同的行为。 键盘不会弹出编辑框( TEdit )。 它确实会弹出组合框 ( TComboBox ) 和密码模式下的编辑框 ( PasswordChar )。 有趣的是,对于TRichEdit ,与 .NET RichTextBox什么显着区别,这可能值得研究。

这个(未回答的)问题描述了一个相同的行为:
在编辑框键盘中编写的应用程序 Delphi XE8 touch 不会出现在 Windows 10 中

我已经在这条路上走了几次,但只能实现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 桌面应用程序:打开 tabtip.exe 到辅助键盘(用于数字文本框)

根本原因似乎是 Winforms 的 textBox 不是 AutomationElement,而其余提到的控件(ComboBoxes 等)是。

在这里引用 Markus von und zu Heber 接受的答案

我们在“ Windows 8+ 上的 WPF 应用程序中的文本框的自动触摸键盘”一文中找到了它,但它对于 winforms 也非常有效(甚至更容易!)。 谢谢你,德米特里莱林!

  1. 将 UIAutomationClient.dll 的引用插入到您的项目中

  2. 在应用程序主窗口的表单加载处理程序中,插入以下代码:

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

据我所知,启动osk.exetabtip.exe几乎是完成这项工作的“标准”方式。 到目前为止,我还没有找到“官方”解决方案。

但是,如果是我这样做,我不会终止进程或发送键来尝试关闭键盘。 相反,您可以在启动进程时获取窗口句柄,并使用它来最小化窗口并将其从任务栏中隐藏。

这里有人得到了窗口句柄只是为了关闭它,但它给了你一个想法: 从 WPF 在屏幕键盘上显示和隐藏 Windows 8

如果你需要我,让我知道,我会看看我是否能找到时间做一个完整的例子。

正如Ofek Shilon 的回答所暗示的那样,触摸键盘似乎可以利用UI 自动化


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

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

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

AutomationElement.FromHandle(IntPtr)(-1)

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

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

有关实现的示例,请参阅


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

使用 RichTextBox 而不是 TextBox 控件。 RichTextBox 支持触摸键盘,获得焦点时会自动弹出键盘。 (类似于组合框等其他输入控件)

RichTextBox 还支持与 TextBox 相同的属性,因此在大多数情况下它应该是一个变化。 (两个控件都源自 TextBoxBase)

我注意到如果触摸键盘在弹出后被关闭,您可能需要在控件上点击两次才能让它重新弹出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM