对于我们的WPF应用程序,当它在触摸屏(Surface Pro .etc)上运行时,TextBox
/ PasswordBox
控件无法显示虚拟键盘强大>当他们集中注意力时。
在WPF中实现此功能的任何好方法吗?
我们最终想要达到的目标是:
如果用户在PC上运行应用程序,我们不关心此功能,这意味着用户是否有物理键盘,我们什么都不像在PC上运行的普通WPF应用程序那样。
如果用户在Surface Pro上运行,当他点击TextBox
时,内置的虚拟键盘会显示出来,而且应该是用户友好的,例如键盘会永远不会掩盖输入元素。
那么,WPF不能轻易设置一些属性来实现这个功能吗?在我看来,这个功能应该是内置的WPF,我不明白为什么我找不到一个简单的方法来实现。
答案 0 :(得分:26)
试试这个,
首先检查物理键盘的存在:
KeyboardCapabilities keyboardCapabilities = new Windows.Devices.Input.KeyboardCapabilities();
return keyboardCapabilities.KeyboardPresent != 0 ? true : false;
如果找不到物理键盘,请使用Windows的内置虚拟键盘:
Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.System) + Path.DirectorySeparatorChar + "osk.exe");
答案 1 :(得分:6)
我发布了一个示例,说明当用户点击文本框时如何在WPF应用程序中触发触控键盘,其位于:
http://code.msdn.microsoft.com/Enabling-Windows-8-Touch-7fb4e6de
这是我多年来一直在努力的事情,我很高兴最终为我们的社区贡献这个榜样。如果示例Q& A窗格中有任何问题,建议,问题等,请告诉我们
答案 2 :(得分:3)
此解决方案非常简单: http://code.msdn.microsoft.com/windowsapps/Enabling-Windows-8-Touch-7fb4e6de
上面的链接详细介绍了这些步骤,以下是简短版本:
InkInputHelper.DisableWPFTabletSupport();
构造函数或类似的MainWindow
using System.Windows.Interop;
添加到MainWindow_Loaded或类似名称:
System.Windows.Automation.AutomationElement asForm =
System.Windows.Automation.AutomationElement.FromHandle(new WindowInteropHelper(this).Handle);
InputPanelConfigurationLib.InputPanelConfiguration inputPanelConfig = new InputPanelConfigurationLib.InputPanelConfiguration();
inputPanelConfig.EnableFocusTracking();
将inputpanelconfiguration.idl转换为DLL
在Windows 8.1上: c:\ Program Files(x86)\ Windows Kits \ 8.1 \ Include \ um \ inputpanelconfiguration.idl
要从IDL构建DLL,请使用以下步骤:
midl /tbld {filename}
TLBIMP.exe InputpanelConfiguration.tlb /publickey:{pathToKey} /delaysign
InkInputHelper类:
using System;
using System.Reflection;
using System.Windows.Input;
namespace ModernWPF.Win8TouchKeyboard.Desktop
{
public static class InkInputHelper
{
public static void DisableWPFTabletSupport()
{
// Get a collection of the tablet devices for this window.
TabletDeviceCollection devices = System.Windows.Input.Tablet.TabletDevices;
if (devices.Count > 0)
{
// Get the Type of InputManager.
Type inputManagerType = typeof(System.Windows.Input.InputManager);
// Call the StylusLogic method on the InputManager.Current instance.
object stylusLogic = inputManagerType.InvokeMember("StylusLogic",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, InputManager.Current, null);
if (stylusLogic != null)
{
// Get the type of the stylusLogic returned from the call to StylusLogic.
Type stylusLogicType = stylusLogic.GetType();
// Loop until there are no more devices to remove.
while (devices.Count > 0)
{
// Remove the first tablet device in the devices collection.
stylusLogicType.InvokeMember("OnTabletRemoved",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic,
null, stylusLogic, new object[] { (uint)0 });
}
}
}
}
}
}
这应该有效。同样,更好的信息和链接中的可下载示例。我只复制粘贴基础知识以进行存档。
答案 3 :(得分:2)
我创建了一个库来自动化WPF应用程序中TabTip集成的所有内容。
你可以在nuget上获得它,然后你需要的只是你的应用启动逻辑中的简单配置:
TabTipAutomation.BindTo<TextBox>();
您可以将TabTip自动化逻辑绑定到任何UIElement。当指定类型的任何元素将获得焦点时,虚拟键盘将打开,并且当元素将失去焦点时,它将关闭。不仅如此,TabTipAutomation还会将UIElement(或Window)移动到视图中,这样TabTip就不会阻止聚焦元素。
有关详细信息,请参阅project site。
答案 4 :(得分:1)
我在TechEd会话中看到了这一点,您需要首先禁用Inking支持(DisableWPFTabletSupport),然后您可以创建一个InputPanelConfiguration(AutomationElement.FromHandle(新的WindowsInteropHelper(this).Handle)并调用EnableFocusTracking。
DisableWPFTabletSupport:http://msdn.microsoft.com/en-us/library/ee230087.aspx
EnableFocusTracking:http://msdn.microsoft.com/en-us/library/windows/desktop/jj126268(v=vs.85).aspx
答案 5 :(得分:1)
定位到.Net 4.6.2
+时,您无需执行任何操作:
https://riptutorial.com/wpf/example/23104/showing-touch-keyboard-on-windows-8-and-windows-10
答案 6 :(得分:0)
public static class InkInputHelper
{
public static void DisableWPFTabletSupport()
{
// Get a collection of the tablet devices for this window.
TabletDeviceCollection devices = System.Windows.Input.Tablet.TabletDevices;
if (devices.Count > 0)
{
// Get the Type of InputManager.
Type inputManagerType = typeof(System.Windows.Input.InputManager);
// Call the StylusLogic method on the InputManager.Current instance.
object stylusLogic = inputManagerType.InvokeMember("StylusLogic",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, InputManager.Current, null);
if (stylusLogic != null)
{
// Get the type of the stylusLogic returned from the call to StylusLogic.
Type stylusLogicType = stylusLogic.GetType();
// Loop until there are no more devices to remove.
while (devices.Count > 0)
{
// Remove the first tablet device in the devices collection.
stylusLogicType.InvokeMember("OnTabletRemoved",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic,
null, stylusLogic, new object[] { (uint)0 });
}
}
}
}
}
使用该类来确定是否存在可能更适合您需求的物理键盘或类似方式。
我用这个类打开和关闭键盘,无论我想要什么。
class KeyboardManager
{
public static void LaunchOnScreenKeyboard()
{
var processes = Process.GetProcessesByName("osk").ToArray();
if (processes.Any())
return;
string keyboardManagerPath = "KeyboardExecuter.exe";
Process.Start(keyboardManagerPath);
}
public static void KillOnScreenKeyboard()
{
var processes = Process.GetProcessesByName("osk").ToArray();
foreach (var proc in processes)
{
proc.Kill();
}
}
public static void killTabTip()
{
var processes = Process.GetProcessesByName("TabTip").ToArray();
foreach (var proc in processes)
{
proc.Kill();
}
}
public static void LaunchTabTip()
{
Process.Start("TabTip.exe");
}
}
请记住以下内容: 我添加了osk.exe和tabtip.exe的副本。 在我的程序中添加这个解决了tabtip或osk无法在32/64位上工作的问题。
osk是键盘,tabtip是它的停靠版本。 keyboardexecuter是我制作的一个程序,用作后备方法。
注意*我目前无法在触摸屏设备上进行测试。你必须自己尝试。
为了这一切正常工作我在我的主窗口中使用了这段代码:
public int selectedTableNum;
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
// Disables inking in the WPF application and enables us to track touch events to properly trigger the touch keyboard
InkInputHelper.DisableWPFTabletSupport();
//remove navigationbar
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
{
var navWindow = Window.GetWindow(this) as NavigationWindow;
if (navWindow != null) navWindow.ShowsNavigationUI = false;
}));
KeyboardManager.LaunchTabTip();
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//Windows 8 API to enable touch keyboard to monitor for focus tracking in this WPF application
InputPanelConfiguration cp = new InputPanelConfiguration();
IInputPanelConfiguration icp = cp as IInputPanelConfiguration;
if (icp != null)
icp.EnableFocusTracking();
mainFrame.Content = new LoginPage();
}
//public bool HasTouchInput()
//{
// foreach (TabletDevice tabletDevice in Tablet.TabletDevices)
// {
// //Only detect if it is a touch Screen not how many touches (i.e. Single touch or Multi-touch)
// if (tabletDevice.Type == TabletDeviceType.Touch)
// return true;
// }
// return false;
//}
我包含了评论,因为如果出现错误,可能对某人有用。
inputpanel配置:
[Guid("41C81592-514C-48BD-A22E-E6AF638521A6")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInputPanelConfiguration
{
/// <summary>
/// Enables a client process to opt-in to the focus tracking mechanism for Windows Store apps that controls the invoking and dismissing semantics of the touch keyboard.
/// </summary>
/// <returns>If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns>
int EnableFocusTracking();
}
[ComImport, Guid("2853ADD3-F096-4C63-A78F-7FA3EA837FB7")]
class InputPanelConfiguration
{
}
我希望这可以帮助未来的访问者解决这个问题。
答案 7 :(得分:-2)
不需要SecureString输出时最简单的选择是使用TextBox并使用类似Wingdings的字体作为字体。