在Windows 10周年纪念版中显示触摸键盘(TabTip.exe)

在周年更新之前的Windows 8和Windows 10中,可以通过启动来显示触摸键盘

C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe 

它不再适用于Windows 10周年更新; TabTip.exe进程正在运行,但键盘未显示。

有没有一种方法来显示它编程?

UPDATE

我发现一个解决方法 – 假的鼠标点击系统托盘中的触摸键盘图标。 这是delphi的代码

 // Find tray icon window function FindTrayButtonWindow: THandle; var ShellTrayWnd: THandle; TrayNotifyWnd: THandle; begin Result := 0; ShellTrayWnd := FindWindow('Shell_TrayWnd', nil); if ShellTrayWnd > 0 then begin TrayNotifyWnd := FindWindowEx(ShellTrayWnd, 0, 'TrayNotifyWnd', nil); if TrayNotifyWnd > 0 then begin Result := FindWindowEx(TrayNotifyWnd, 0, 'TIPBand', nil); end; end; end; // Post mouse click messages to it TrayButtonWindow := FindTrayButtonWindow; if TrayButtonWindow > 0 then begin PostMessage(TrayButtonWindow, WM_LBUTTONDOWN, MK_LBUTTON, $00010001); PostMessage(TrayButtonWindow, WM_LBUTTONUP, 0, $00010001); end; 

更新2

我发现另一件事是设置此registry项恢复旧的function,当启动TabTip.exe显示触摸键盘

 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\TabletTip\1.7\EnableDesktopModeAutoInvoke=1 

好的,我反向设计了当用户按下系统托盘中的按钮时,浏览器执行的操作。

基本上它创建了一个未ITipInvocation接口ITipInvocation的实例,并调用其Toggle(HWND)方法,将桌面窗口作为参数传递。 顾名思义,该方法根据当前状态显示或隐藏键盘。

请注意 ,资源管理器会在每次点击按钮时创建一个ITipInvocation实例。 所以我相信这个实例不应该被缓存。 我也注意到,资源管理器从不在所获得的实例上调用Release() 我不太熟悉COM,但是这看起来像一个bug。

我在Windows 8.1,Windows 10和Windows 10周年纪念版中进行了测试,效果非常好。 在C中,这是一个很小的例子,显然缺少一些错误检查。

 #include <initguid.h> #include <Objbase.h> #pragma hdrstop // 4ce576fa-83dc-4F88-951c-9d0782b4e376 DEFINE_GUID(CLSID_UIHostNoLaunch, 0x4CE576FA, 0x83DC, 0x4f88, 0x95, 0x1C, 0x9D, 0x07, 0x82, 0xB4, 0xE3, 0x76); // 37c994e7_432b_4834_a2f7_dce1f13b834b DEFINE_GUID(IID_ITipInvocation, 0x37c994e7, 0x432b, 0x4834, 0xa2, 0xf7, 0xdc, 0xe1, 0xf1, 0x3b, 0x83, 0x4b); struct ITipInvocation : IUnknown { virtual HRESULT STDMETHODCALLTYPE Toggle(HWND wnd) = 0; }; int WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HRESULT hr; hr = CoInitialize(0); ITipInvocation* tip; hr = CoCreateInstance(CLSID_UIHostNoLaunch, 0, CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER, IID_ITipInvocation, (void**)&tip); tip->Toggle(GetDesktopWindow()); tip->Release(); return 0; } 

以下是C#版本:

 class Program { static void Main(string[] args) { var uiHostNoLaunch = new UIHostNoLaunch(); var tipInvocation = (ITipInvocation)uiHostNoLaunch; tipInvocation.Toggle(GetDesktopWindow()); Marshal.ReleaseComObject(uiHostNoLaunch); } [ComImport, Guid("4ce576fa-83dc-4F88-951c-9d0782b4e376")] class UIHostNoLaunch { } [ComImport, Guid("37c994e7-432b-4834-a2f7-dce1f13b834b")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface ITipInvocation { void Toggle(IntPtr hwnd); } [DllImport("user32.dll", SetLastError = false)] static extern IntPtr GetDesktopWindow(); } 

更新:每@EugeneK评论,我相信tabtip.exe是有问题的COM组件的COM服务器,所以如果您的代码获取REGDB_E_CLASSNOTREG ,它应该可能运行tabtip.exe并再试一次。

我发现唯一的解决办法是发送PostMessage,就像你在回答1中提到的那样。这是C#版本,以防万一需要。

 [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern IntPtr FindWindow(string sClassName, string sAppName); [DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle); [DllImport("User32.Dll", EntryPoint = "PostMessageA")] static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam); var trayWnd = FindWindow("Shell_TrayWnd", null); var nullIntPtr = new IntPtr(0); if (trayWnd != nullIntPtr) { var trayNotifyWnd = FindWindowEx(trayWnd, nullIntPtr, "TrayNotifyWnd", null); if (trayNotifyWnd != nullIntPtr) { var tIPBandWnd = FindWindowEx(trayNotifyWnd, nullIntPtr, "TIPBand", null); if (tIPBandWnd != nullIntPtr) { PostMessage(tIPBandWnd, (UInt32)WMessages.WM_LBUTTONDOWN, 1, 65537); PostMessage(tIPBandWnd, (UInt32)WMessages.WM_LBUTTONUP, 1, 65537); } } } public enum WMessages : int { WM_LBUTTONDOWN = 0x201, WM_LBUTTONUP = 0x202, WM_KEYDOWN = 0x100, WM_KEYUP = 0x101, WH_KEYBOARD_LL = 13, WH_MOUSE_LL = 14, } 

当在Windows 10周年更新中尝试打开触摸键盘时,检测到4种情况

  1. 键盘是可见的 – 当“IPTIP_Main_Window”存在时,不禁用和可见
  2. 键盘不可见 – 当“IPTIP_Main_Window”存在但禁用时
  3. 键盘不可见 – 当“IPTIP_Main_Window”存在但未禁用且不可见时
  4. 键盘不可见 – 当“IPTIP_Main_Window” 存在时

1 – 无事可做

2 + 3 – 通过COM激活

4 – 最有趣的场景。 在一些设备启动TabTip过程打开触摸键盘,在一些 – 不。 因此,我们必须启动TabTip进程,等待出现窗口“IPTIP_Main_Window”,检查它的可见性,如果有必要,通过COM激活它。

我为我的项目制作小型图书馆,你可以使用它 – osklib

这个问题似乎是与Windows操作系统的设置。 我遇到了与我正在开发的应用程序相同的问题。 随着Windows 8和10(更新之前)称为键盘的代码工作正常,但更新后失败的工作。 看完这篇文章后 ,我做了以下工作:

  1. 按下Win + I打开设置应用程序

  2. 点击Devices> Typing

  3. 打开“ 没有键盘连接到设备时,在窗口应用程序中自动显示触摸键盘 ”。

    在那之后,键盘开始出现在Windows 10中。

关于Windows 10周年更新如何设置触摸键盘,还有一些疑问。 我实际上有完全相同的问题,这里是我找到的最新信息:

  • Windows 10 1607有两种模式:桌面和平板电脑。 在桌面模式下,可以调用TabTip.exe,但不会显示。 在平板电脑模式下,一切工作正常:TabTip.exe时显示自己被调用。 因此,100%的解决方法是将您的电脑设置为平板电脑模式,但是希望他的台式机/笔记本电脑在平板电脑模式下工作? 不是我!

  • 您可以使用“ EnableDesktopModeAutoInvoke ”键(HKCU,DWORD设置为1),在运行1607的某些计算机上,在桌面模式下工作良好。 但由于某些未知的原因,这不适用于我的惠普触摸板。

请注意,此注册表值是“Windows参数”>“touch”中的“如果没有连接键盘,则在桌面模式下显示触摸键盘”选项

  • 你可以使用Torvin的代码来显示TabTip.exe(如提到的TabTip.exe应该在你做COM的时候运行),它在运行1607的某些计算机上工作正常(包括我的惠普触摸板!耶!)但它什么也不做在一些其他与相同的Windows Build版本。

到目前为止在4个不同的电脑上测试,我无法得到的东西工作正常…

在您的控件中实现IValueProvider / ITextProvider是实现此目的的正确方法,如下所述: https ://stackoverflow.com/a/43886052/1184950