在WPF中显示和隐藏Windows 8屏幕键盘

13

我正在为 Windows 8 平板编写 WPF 应用程序。它是完整的 Windows 8 而不是 ARM/RT。

当用户输入文本框时,我使用以下代码显示屏幕键盘:

System.Diagnostics.Process.Start(@"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe");

这个可以正常运行,但我不知道如何再次隐藏键盘?

有人知道怎么做吗?

此外,是否有办法调整我的应用程序大小,以便在键盘出现时将焦点控件向上移动? 类似于 Windows RT 应用程序的做法。

非常感谢

8个回答

19

我可以使用以下的C#代码成功关闭屏幕键盘。

[DllImport("user32.dll")]
public static extern int FindWindow(string lpClassName,string lpWindowName);

[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);

public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;

private void closeOnscreenKeyboard()
{
    // retrieve the handler of the window  
    int iHandle = FindWindow("IPTIP_Main_Window", "");
    if (iHandle > 0)
    {
        // close the window using API        
        SendMessage(iHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
    }  
}

private void Some_Event_Happened(object sender, EventArgs e)
{
    // It's time to close the onscreen keyboard.
    closeOnscreenKeyboard();
}

我希望这能帮助到你。


6
稍微晚了一些,我将改进 tasaki 的示例,以便完整地展示我在 Windows 8 平板电脑的 WPF 应用程序中启用 gotFocus/LostFocus 事件时如何实现文本框的显示/隐藏。我希望这能帮助那些有类似烦恼的人,因为如果您想使用触摸事件滚动,则禁用 InkHelper 不是一个很好的选择...
首先,您必须将以下引用添加到 App.Xaml.cs 文件中。
using System.Management;
using System.Runtime.InteropServices;

代码如下:
    protected override void OnStartup(StartupEventArgs eventArgs)
    {
        EventManager.RegisterClassHandler(typeof(TextBox), UIElement.GotFocusEvent,
                                new RoutedEventHandler(GotFocus_Event), true);
        EventManager.RegisterClassHandler(typeof(TextBox), UIElement.LostFocusEvent,
                                new RoutedEventHandler(LostFocus_Event), true);

       MainApplication.Show();
    }

    private static void GotFocus_Event(object sender, RoutedEventArgs e)
    {
       // TestKeyboard();
        OpenWindows8TouchKeyboard(sender, e);
    }
    //http://www.c-sharpcorner.com/UploadFile/29d7e0/get-the-key-board-details-of-your-system-in-windows-form/
    private static bool IsSurfaceKeyboardAttached()
    {
        SelectQuery Sq = new SelectQuery("Win32_Keyboard");
        ManagementObjectSearcher objOSDetails = new ManagementObjectSearcher(Sq);
        ManagementObjectCollection osDetailsCollection = objOSDetails.Get();
        //Windows 8 tablet are returnign 2 device when keyboard is connecto
        //My application won't be used for Desktop so this condition is fine
        //But u might want to see if keyboard is usb and == 1 so you are 
        //returning true or not on tablet.  
        return osDetailsCollection.Count <= 1 ? true : false;
    }

    private static void OpenWindows8TouchKeyboard(object sender, RoutedEventArgs e)
    {
        var textBox = e.OriginalSource as TextBox;        
        if (textBox != null && IsSurfaceKeyboardAttached())
        {
            var path = @"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe";
            if (!File.Exists(path))
            {
                // older windows versions
                path = Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\osk.exe";
            }
            Process.Start(path);
            textBox.BringIntoView();//SetFocus so u dont lose focused area
        }
    }
    [DllImport("user32.dll")]
    public static extern int FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll")]
    public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);

    public const int WM_SYSCOMMAND = 0x0112;
    public const int SC_CLOSE = 0xF060;
    public const int SC_MINIMIZE = 0xF020;

    private void CloseOnscreenKeyboard()
    {
        // retrieve the handler of the window  
        int iHandle = FindWindow("IPTIP_Main_Window", "");
        if (iHandle > 0)
        {
            // close the window using API        
            SendMessage(iHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
        }
    }

    private void LostFocus_Event(object sender, EventArgs e)
    {
        // It's time to close the onscreen keyboard.
        CloseOnscreenKeyboard();
    }

3
我将我的项目开源,以自动化与WPF应用程序中的TabTip集成有关的一切事宜。
您可以在nuget上获取它,在此之后,您只需要在应用程序启动逻辑中进行简单的配置即可:
TabTipAutomation.BindTo<TextBox>();

您可以将TabTip自动化逻辑绑定到任何UI元素。虚拟键盘将在任何此类元素获得焦点时打开,并且当元素失去焦点时,它将关闭。不仅如此,TabTipAutomation还将移动UIElement(或窗口)到视图中,以便TabTip不会阻塞聚焦的元素。

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


可以请你查看一下如何提供个人开源库?吗? - Martijn Pieters

0

我不确定如何在程序中编程地隐藏键盘,但正如你所知道的,我最近刚刚发布了一个示例,演示了如何在WPF应用程序中触发(即显示)触摸键盘,当用户点击文本框时,它在这里:

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

这个示例的酷之处在于,它不需要使用进程,而是使用支持的Windows 8 API通过自动化来触发文本框控件的触摸键盘。

这是我多个月来一直在研究的东西,我很高兴能够终于为我们的社区做出贡献。如果在示例Q&A窗格中有任何问题、建议、问题等,请告诉我。


0

试试这个

System.Diagnostics.Process.Start("TabTip.exe");

希望这能对你有所帮助。


0

0

我会尝试这样做

Process myProcess = Process.Start(@"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe");
myProcess.CloseMainWindow();
myProcess.Close();

谢谢回复,有关键盘出现时将屏幕向上移动的任何想法吗? - Sun
@user1131657,这话说得有点过了吧... 你不想用更简单的方法吗?应该会有一些... 比如看看WPF触摸屏键盘... 还有其他更好的解决方案,看起来比你现在尝试的要好。 - Kapitán Mlíko
维克托,我已经进一步尝试了一下,并且更愿意使用内置的触摸屏键盘。为什么要重新发明轮子呢!我尝试了你的代码,但它不起作用。当CloseMainWindow行运行时,我收到以下错误:进程已退出,因此请求的信息不可用。 - Sun
好的...那我对你没有帮助了。抱歉。我最后找到的是这个问题,它被标记为win7,但可能会对你有所帮助。祝你好运 ;) - Kapitán Mlíko
这个不起作用。Tabtip 有特殊的行为,Windows 将一个主实例回收到它自己启动的 TabTip 中。因此,您启动的实例是瞬态的,并立即消失。Windows 将显示任何现有的实例或根据需要启动一个新的实例。来自@tasasaki 的答案完美地解决了这个问题。 - donovan

-1

这应该可以打开,然后终止进程。

Process proc = Process.Start(@"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe");
proc.Kill();

终止进程将会关闭它。

然而,如果您在调试并逐步执行这两行代码,上述相同的错误会发生 - “进程已退出,因此请求信息不可用。”

如果您在调试时没有逐步执行这两行代码,则不会抛出任何异常,并且屏幕键盘将被关闭。

如果您使用CloseMainWindow(),则键盘将无法关闭。 CloseMainWindow() 适用于具有 UI 的进程, 因此您可能认为它对此有效,但由于键盘是操作系统的一部分,所以它不起作用。

确认它可以工作后,将proc.Kill()放入 try-catch 中进行错误记录,以确保安全。


正如另一个评论中所指出的,tabtip是特殊的,因此这不起作用。 - donovan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接