更改 EnableDesktopModeAutoInvoke 注册表值并使 TabTip.exe 接受更改
Change EnableDesktopModeAutoInvoke registry value and make TabTip.exe to accept change
Windows 10 有设置 "Show the touch keyboard when not in tablet mode and there's no keyboard attached",它允许 Windows 在您触摸文本框时显示触摸键盘。
由于 Windows 处理此逻辑相当糟糕(它在 WPF 应用程序中很容易被破坏),我想为我的应用程序关闭此选项,我试图通过更改注册表值 EnableDesktopModeAutoInvoke
,对应这个选项(简单的Registry.SetValue
方法)。但是有一个问题 - 触摸键盘应用程序 TabTip.exe
由于某种原因并没有真正 "hook up" 更改注册表,并且在重新启动之前一直显示触摸键盘。反之亦然 - 一旦我恢复注册表值,我需要重新启动应用程序以应用更改。
这就是这种方法的主要问题所在 - 启用 auto-invoke 选项后,一旦 TabTip 进程启动,它会立即显示键盘。显然我不喜欢这样的视觉效果 side-effects 我的应用程序逻辑。
另一点是,在以通常方式更改此设置时,通过 Windows 设置应用程序、TabTip 或任何相关应用程序或服务不会重新启动。这意味着设置应用程序以某种方式设法更新 TabTip 进程。我真的很想弄清楚它是如何做到这一点的,以及我是否可以在 C# 中重现相同的行为,但我不知道如何实现。
所以,我的问题是 - 如何以编程方式更改 EnableDesktopModeAutoInvoke
注册表值或 "Show the touch keyboard when not in tablet mode and there's no keyboard attached" Windows 选项,并使 TabTip 应用程序接受此更改,而无需任何可能的视觉side-effects?
UPD:
我知道可以通过使用特定的自动化对等创建自定义文本框来使键盘忽略文本框,但这需要替换整个应用程序中的所有文本框,并且始终牢记我们需要使用新的文本框,所以这不是可行的解决方案。我也试图消除为 main window 的 children 获取自动化对等点的可能性,但这不起作用。
我在黑暗中为你开枪...
这里有一种方法可以通过 Windows 设置而不是您通知 TabTip 注册表更改:如果 TabTip 使用类似 WMI RegistryKeyChangeEvent class internally, it's possible that the TabTip application is only monitoring the parent registry key and not monitoring the key value you're actually changing (which is why TapTip not updated when you change the value). But, the Windows Settings application could be setting the whole key
(and it's corresponding valueName
and value
) via something like SetExpandedStringValue 的东西,这将触发密钥更改TabTip 可能正在观看。
对此进行测试的方法是以编程方式一次性设置 key
、valueName
和 value
,而不是仅设置 value
。
所以我看了很多相同的不同实现
大多数情况下使用
终止进程
foreach (Process tabTipProcess in Process.GetProcessesByName(TabTipProcessName))
tabTipProcess.Kill();
或使用
关闭键盘
void closeKeyboard()
{
uint WM_SYSCOMMAND = 274;
uint SC_CLOSE = 61536;
IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
PostMessage(KeyboardWnd.ToInt32(), WM_SYSCOMMAND, (int)SC_CLOSE, 0);
}
所以,我认为您已经拥有的是已知的最佳选择
不是很好的解决方案,但您可以尝试连接到显示事件 https://docs.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.inputpane
并在出现show事件时立即调用一个TryHide来抑制它。
Windows 10 有设置 "Show the touch keyboard when not in tablet mode and there's no keyboard attached",它允许 Windows 在您触摸文本框时显示触摸键盘。
由于 Windows 处理此逻辑相当糟糕(它在 WPF 应用程序中很容易被破坏),我想为我的应用程序关闭此选项,我试图通过更改注册表值 EnableDesktopModeAutoInvoke
,对应这个选项(简单的Registry.SetValue
方法)。但是有一个问题 - 触摸键盘应用程序 TabTip.exe
由于某种原因并没有真正 "hook up" 更改注册表,并且在重新启动之前一直显示触摸键盘。反之亦然 - 一旦我恢复注册表值,我需要重新启动应用程序以应用更改。
这就是这种方法的主要问题所在 - 启用 auto-invoke 选项后,一旦 TabTip 进程启动,它会立即显示键盘。显然我不喜欢这样的视觉效果 side-effects 我的应用程序逻辑。
另一点是,在以通常方式更改此设置时,通过 Windows 设置应用程序、TabTip 或任何相关应用程序或服务不会重新启动。这意味着设置应用程序以某种方式设法更新 TabTip 进程。我真的很想弄清楚它是如何做到这一点的,以及我是否可以在 C# 中重现相同的行为,但我不知道如何实现。
所以,我的问题是 - 如何以编程方式更改 EnableDesktopModeAutoInvoke
注册表值或 "Show the touch keyboard when not in tablet mode and there's no keyboard attached" Windows 选项,并使 TabTip 应用程序接受此更改,而无需任何可能的视觉side-effects?
UPD:
我知道可以通过使用特定的自动化对等创建自定义文本框来使键盘忽略文本框,但这需要替换整个应用程序中的所有文本框,并且始终牢记我们需要使用新的文本框,所以这不是可行的解决方案。我也试图消除为 main window 的 children 获取自动化对等点的可能性,但这不起作用。
我在黑暗中为你开枪...
这里有一种方法可以通过 Windows 设置而不是您通知 TabTip 注册表更改:如果 TabTip 使用类似 WMI RegistryKeyChangeEvent class internally, it's possible that the TabTip application is only monitoring the parent registry key and not monitoring the key value you're actually changing (which is why TapTip not updated when you change the value). But, the Windows Settings application could be setting the whole key
(and it's corresponding valueName
and value
) via something like SetExpandedStringValue 的东西,这将触发密钥更改TabTip 可能正在观看。
对此进行测试的方法是以编程方式一次性设置 key
、valueName
和 value
,而不是仅设置 value
。
所以我看了很多相同的不同实现
大多数情况下使用
终止进程foreach (Process tabTipProcess in Process.GetProcessesByName(TabTipProcessName))
tabTipProcess.Kill();
或使用
关闭键盘void closeKeyboard()
{
uint WM_SYSCOMMAND = 274;
uint SC_CLOSE = 61536;
IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
PostMessage(KeyboardWnd.ToInt32(), WM_SYSCOMMAND, (int)SC_CLOSE, 0);
}
所以,我认为您已经拥有的是已知的最佳选择
不是很好的解决方案,但您可以尝试连接到显示事件 https://docs.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.inputpane
并在出现show事件时立即调用一个TryHide来抑制它。