使用C#在通用Windows应用程序中未检测到键盘布局更改

时间:2017-03-02 20:33:57

标签: c# windows uwp keyboard-layout

我想用C#检测每个键盘布局的变化。无论是通过win + space还是alt + shift或使用鼠标切换它都无关紧要...... 我为桌面应用编写了一个相当好的代码(见下文)。但它对UWP应用程序并不起作用。如果我在UWP应用程序内切换布局,则无法检测到,如果我切换到桌面应用程序,则立即检测到更改...如何检测布局中的任何更改?有什么其他方法可以找出在任何给定时刻哪个布局处于活动状态,无论哪个窗口处于活动状态? 我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Globalization;

namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        string lastLang = "";
        while (true)
        {
            string langSuffix = GetKeyboardLayoutIdAtTime();

            if (!langSuffix.Equals(lastLang))
            {
                // do something
                Console.WriteLine(getCurrentTimeStamp() + ": Changing '" + lastLang + "' to '" + langSuffix + "'.");
                lastLang = langSuffix;
            }
            System.Threading.Thread.Sleep(1000);

        }

    }


    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern int GetWindowThreadProcessId(IntPtr handleWindow, out int lpdwProcessID);

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern IntPtr GetKeyboardLayout(int WindowsThreadProcessID);

    public static string GetKeyboardLayoutIdAtTime()
    {
        IntPtr hWnd = GetForegroundWindow();
        int lpdwProcessId;
        InputLanguageCollection installedInputLanguages = InputLanguage.InstalledInputLanguages;
        CultureInfo currentInputLanguage = null;
        int WinThreadProcId = GetWindowThreadProcessId(hWnd, out lpdwProcessId);

        IntPtr KeybLayout = GetKeyboardLayout(WinThreadProcId);
        // this remain unchanged when I switch layouts in UWP
        Console.WriteLine("KL IntPtr: " + KeybLayout);

        for (int i = 0; i < installedInputLanguages.Count; i++)
        {
            if (KeybLayout == installedInputLanguages[i].Handle) currentInputLanguage = installedInputLanguages[i].Culture;

        }
        if(currentInputLanguage == null)
        {
            Console.WriteLine(getCurrentTimeStamp() + "current input language is null...");
        }
        return currentInputLanguage.TwoLetterISOLanguageName;
    }

    private static string getCurrentTimeStamp()
    {
        return DateTime.Now.ToString("yyyyMMddHHmmssffff");
    }
}

}

1 个答案:

答案 0 :(得分:1)

在桌面中,我们使用Input Method Manager与作为服务运行的输入法编辑器(IME)进行通信。在UWP中,我们应该能够使用文本服务框架。有一个关于Alternatives to Windows APIs in Universal Windows Platform (UWP) apps的文档。

因此我们应该能够使用Windows​.UI​.Text​.Core命名空间,它提供了访问Windows核心文本API和文本输入服务器的类型。 Windows核心文本是一种客户端 - 服务器系统,它将键盘输入的处理集中到单个服务器中。

我们可以在InputLanguageChanged课程中找到CoreTextServicesManager事件。它在当前输入语言发生变化时发生。当我们通过win + space或alt + shift或鼠标切换输入法时,InputLanguageChanged将被触发。

例如:

public MainPage()
{
    this.InitializeComponent();
    CoreTextServicesManager textServiceManager = CoreTextServicesManager.GetForCurrentView();
    textServiceManager.InputLanguageChanged += TextServiceManager_InputLanguageChanged;
}

private void TextServiceManager_InputLanguageChanged(CoreTextServicesManager sender, object args)
{
    Debug.WriteLine("Keyboard layout is changed!");
}