在周年更新之前的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 – 无事可做
2 + 3 – 通过COM激活
4 – 最有趣的场景。 在一些设备启动TabTip过程打开触摸键盘,在一些 – 不。 因此,我们必须启动TabTip进程,等待出现窗口“IPTIP_Main_Window”,检查它的可见性,如果有必要,通过COM激活它。
我为我的项目制作小型图书馆,你可以使用它 – osklib
这个问题似乎是与Windows操作系统的设置。 我遇到了与我正在开发的应用程序相同的问题。 随着Windows 8和10(更新之前)称为键盘的代码工作正常,但更新后失败的工作。 看完这篇文章后 ,我做了以下工作:
按下Win + I打开设置应用程序
点击Devices> Typing
打开“ 没有键盘连接到设备时,在窗口应用程序中自动显示触摸键盘 ”。
在那之后,键盘开始出现在Windows 10中。
关于Windows 10周年更新如何设置触摸键盘,还有一些疑问。 我实际上有完全相同的问题,这里是我找到的最新信息:
Windows 10 1607有两种模式:桌面和平板电脑。 在桌面模式下,可以调用TabTip.exe,但不会显示。 在平板电脑模式下,一切工作正常:TabTip.exe时显示自己被调用。 因此,100%的解决方法是将您的电脑设置为平板电脑模式,但是希望他的台式机/笔记本电脑在平板电脑模式下工作? 不是我!
您可以使用“ EnableDesktopModeAutoInvoke
”键(HKCU,DWORD设置为1),在运行1607的某些计算机上,在桌面模式下工作良好。 但由于某些未知的原因,这不适用于我的惠普触摸板。
请注意,此注册表值是“Windows参数”>“touch”中的“如果没有连接键盘,则在桌面模式下显示触摸键盘”选项
到目前为止在4个不同的电脑上测试,我无法得到的东西工作正常…
在您的控件中实现IValueProvider / ITextProvider是实现此目的的正确方法,如下所述: https ://stackoverflow.com/a/43886052/1184950