【问题标题】:Why does GetKeyboardLayoutName return the same name after a layout change?为什么 GetKeyboardLayoutName 在布局更改后返回相同的名称?
【发布时间】:2022-01-09 09:16:57
【问题描述】:

在下面编写的这个程序中,使用来自 user32.dll 的 GetKeyboardLayoutName。 当我使用“美国英语”布局键入第一个符号时,我得到 00000409。这很好。 但是,当我将布局更改为其他内容时,例如“English UK”或“Russian”,GetKeyboardLayoutName 会返回“English USA”的代码 - 00000409。

我对此进行了测试,如果我在“俄语”中输入第一个符号,它会返回 00000419,如果我切换回“美国英语”并输入第二个符号,GetKeyboardLayoutName 仍会返回“俄语”的代码 - 00000419。

using System;
using System.Runtime.InteropServices;
using System.Text;

namespace ConsoleApp2
{

    class Program
    {

        const int KL_NAMELENGTH = 9;

        [DllImport("user32.dll")]
        private static extern long GetKeyboardLayoutName(StringBuilder pwszKLID);
        public static string GetLayoutCode()
        {
            var name = new StringBuilder(KL_NAMELENGTH);
            GetKeyboardLayoutName(name);

            return name.ToString();
        }

        static void Main(string[] args)
        {
            Console.ReadKey();
            var res = GetLayoutCode();
            Console.WriteLine("\n" + res);

            Console.ReadKey();
            res = GetLayoutCode();
            Console.WriteLine("\n" + res);
        }
    }
}

【问题讨论】:

    标签: c# winapi dll dllimport user32


    【解决方案1】:

    问题在于控制台应用程序不允许您处理 Windows 消息。
    您可以将您的应用程序转换为 应用程序,隐藏主窗体并子类WndProc 来处理在键盘布局更改时触发的WM_INPUTLANGCHANGE 消息:

    public class MyHiddenForm : Form
    {
        ...
    
        protected override void WndProc(ref Message m)
        {
            const int WM_INPUTLANGCHANGE = 0x0051;
            if (m.Msg == WM_INPUTLANGCHANGE)
            {
                Console.WriteLine("{0:X8} {1:X8}", m.WParam.ToInt64() , m.LParam.ToInt64());
            }
            base.WndProc(ref m);
        }
    }
    

    另一种方法是通过 WinAPI 在控制台应用程序中创建一个隐藏窗口来接收消息。但我个人更喜欢第一种方法。

    【讨论】:

      【解决方案2】:

      如果您不需要专门的 KLID(键盘布局标识符),而您只需要一种识别键盘布局的方法,那么您可以使用以下方法获取 HKL(输入语言环境标识符):

      var focusedHWnd = GetForegroundWindow();
      var activeThread = GetWindowThreadProcessId(focusedHWnd, IntPtr.Zero);
      var hkl = GetKeyboardLayout(activeThread);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-22
        • 2015-03-17
        • 1970-01-01
        相关资源
        最近更新 更多