Home > Blockchain >  Why GetKeyboardLayoutName return same name after layout change?
Why GetKeyboardLayoutName return same name after layout change?

Time:12-03

In this program written below, used GetKeyboardLayoutName from user32.dll. When i type first symbol using "English USA" layout i get 00000409. This is fine. But when i change my layout to something else like "English UK" or "Russian" GetKeyboardLayoutName return code for "English USA" - 00000409.

I tested and if i input first symbol in "Russian" it return 00000419 and if i switch back to "English USA" and input second symbol, GetKeyboardLayoutName still return code for "Russian" - 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);
        }
    }
}

CodePudding user response:

The problem is that a console application doesn't allow you to handle windows messages.
You could convert your application to application, make the main form hidden and subclass WndProc to handle the WM_INPUTLANGCHANGE message that triggers on the keyboard layout change:

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

Another approach is to create a hidden window via WinAPI in the console application that will receive messages. But i'd personally prefer the first approach.

CodePudding user response:

If you just need a keyboard layout identifier (KLID) specifically, an you just need a way to identify keyboard layouts then you can use the following to get the HKL (input locale identifier):

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