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

时间:2016-03-23 13:44:00

标签: c# windows winforms delphi touch

当我在{10}中在Windows 10上运行WinForms(或Delphi,请参见最后的)应用程序时,当输入框被聚焦时,触摸键盘不会自动弹出。

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

对于测试,我有一个最简单的VS 2015 WinForms桌面应用程序,只有一个tablet mode

TextBox control

它只是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中出现了一些阻止自动弹出窗口的东西。有趣的是,自动弹出功能起作用:

  • for(可编辑)组合框(ComboBoxDropDownStyle = DropDown
  • 用于密码模式(enter image description here
  • 的文本框
  • 用于富文本框(RichTextBox
  • 当硬件键盘被移除时,输入框具有焦点" (我通过翻转联想瑜伽笔记本上的屏幕进行测试),但从未过后。

我通过运行TabTip.exe看到了有关显式弹出窗口的所有提示。 E.g:

大多数"解决方案"提供这样的代码:

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 键的黑客攻击)。 / p>

实际上,上述黑客攻击在Windows 10周年更新中似乎不再起作用了:

有趣的是,我在Delphi / C ++ Builder / VCL应用程序中看到了相同的行为。键盘不会弹出编辑框(Show touch keyboard (TabTip.exe) in Windows 10 Anniversary edition)。它会弹出组合框(TEdit)和密码模式下的编辑框(TComboBox)。有趣的是,不是PasswordChar,.NET RichTextBox的显着差异,可能值得研究。

这个(未答复的)问题描述了一个相同的行为:
TRichEdit

5 个答案:

答案 0 :(得分:9)

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

引用Markus von und zu Heber的accepted answer here

  

我们在文章“Automatic Touch Keyboard for TextBoxes in WPF Applications on Windows 8+”中找到了它,但它也非常好(甚至   更容易!)为winforms。谢谢Dmitry Lyalin!

     
      
  1. 将对UIAutomationClient.dll的引用插入项目

  2.   
  3. 在应用程序主窗口的form-load-handler中,插入以下代码:

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

答案 1 :(得分: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)

答案 2 :(得分:5)

据我所知,发起osk.exetabtip.exe几乎就是"标准"使这项工作的方式。我发现没有"官方"解决方案到目前为止。

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

这里的某个人已经拿到了窗口句柄来关闭它,但它给了你一个主意:Show & hiding the Windows 8 on screen keyboard from WPF

如果你需要我,请告诉我,我会看看我是否能抽出时间做一个完整的例子。

答案 3 :(得分:1)

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

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

我注意到如果触摸键盘在弹出后被解除,你可能需要在控件上点击两次以使其弹回。

答案 4 :(得分:0)

正如Ofek Shilon's answer暗示的那样,触控键盘似乎可以利用UI automation

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

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

On可以通过调用seeming no-op来实现:

AutomationElement.FromHandle(IntPtr)(-1)

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

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

有关实施的示例,请参阅

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