30

对于我们的 WPF 应用程序,当它在触摸屏(Surface Pro .etc)上运行时,TextBox/控件在获得焦点时PasswordBox无法显示虚拟键盘。

在 WPF 中实现此功能的任何好方法?


更新:

我们最终想要实现的是这样的:

如果用户在 PC 上运行应用程序,我们不关心这个功能,这意味着用户是否有物理键盘,我们什么也不做,就像在 PC 上运行的普通 WPF 应用程序一样。

如果用户在 Surface Pro 上运行,当他点击 时TextBox,可以显示内置的虚拟键盘,并且应该是用户友好的,例如键盘永远不会掩盖输入元素。


更新2:

那么,WPF 不能轻易设置一些属性来实现这个功能吗?在我看来,这个功能应该是WPF内置的,我不明白为什么我找不到一个简单的方法来实现。

4

8 回答 8

31

尝试这个,

首先检查物理键盘是否存在:

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 链接 2

于 2013-10-06T15:58:01.133 回答
7

我已经发布了一个关于如何在用户单击文本框时触发 WPF 应用程序中的触摸键盘的示例,它在这里:

http://code.msdn.microsoft.com/Enabling-Windows-8-Touch-7fb4e6de

这是我几个月来一直在努力的事情,我很高兴最终将这个例子贡献给我们的社区。如果在示例问答窗格中有任何问题、建议、问题等,请告诉我

于 2013-12-13T19:28:02.380 回答
4

我创建了一个库来自动化 WPF 应用程序中有关 TabTip 集成的所有内容。

您可以在nuget上获得它,之后您只需要在应用程序启动逻辑中进行简单配置:

TabTipAutomation.BindTo<TextBox>();

您可以将 TabTip 自动化逻辑绑定到任何 UIElement。当指定类型的任何元素获得焦点时,虚拟键盘将打开,当元素失去焦点时,它将关闭。不仅如此,TabTipAutomation 还会将 UIElement(或 Window)移动到视图中,这样 TabTip 就不会阻塞焦点元素。

有关更多信息,请参阅项目站点

于 2016-08-26T06:41:03.830 回答
3

这个解决方案非常简单: http ://code.msdn.microsoft.com/windowsapps/Enabling-Windows-8-Touch-7fb4e6de

步骤在上面的链接中有详细说明,这里是简短的版本:

  • 添加 UIAutomationClient 引用
  • 使用托管代码中的 IFrameworkInputPane(链接处的 DLL 或将 inputpanelconfiguration.idl 转换为 DLL,请参见以下步骤)
  • 创建新类 InkInputHelper 以禁用墨迹支持(下面的代码)
  • 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 编译器工具构建类型库 TLB 文件
    • 例子:midl /tbld {filename}
  • 使用 TBIMP 工具将上面生成的类型库(TLB 文件)转换为 .NET 可以使用的 DLL,方法是运行以下命令
    • 例子: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 });
                }
            }
        }
    }
}
}

这应该有效。同样,链接中有更好的信息和可下载的示例。我只是出于存档目的复制粘贴了基础知识。

于 2014-10-03T14:17:43.840 回答
2

当定位.Net 4.6.2+ 你不需要做任何事情:

https://riptutorial.com/wpf/example/23104/showing-touch-keyboard-on-windows-8-and-windows-10

于 2018-12-12T08:44:31.593 回答
1

我在 TechEd 会话中看到了这一点,您需要首先禁用墨迹支持 (DisableWPFTabletSupport),然后您可以创建 InputPanelConfiguration (AutomationElement.FromHandle(new WindowsInteropHelper(this).Handle) 并调用 EnableFocusTracking。

禁用WPFTabletSupport:http: //msdn.microsoft.com/en-us/library/ee230087.aspx

EnableFocusTracking: http: //msdn.microsoft.com/en-us/library/windows/desktop/jj126268 (v=vs.85).aspx

于 2013-10-11T19:09:32.057 回答
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 是它的停靠版本。键盘执行器是我制作的一个程序,用作后备方法。

注意*我目前无法在触摸屏设备上进行测试。你必须自己尝试。

为了让这一切正常工作,我在主窗口中使用了这段代码:

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;
        //}

我包括了评论,因为如果出现错误,它可能对某人有用。

输入面板配置:

[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
{
}

我希望这可能对这个问题的未来访客有所帮助。

于 2016-05-11T08:57:09.427 回答
-2

当不需要 SecureString 输出时,最简单的选择是使用 TextBox 并使用 Wingdings 之类的字体作为字体。

于 2017-03-21T13:40:05.163 回答