can't get current keyboard layout
Asked Answered
A

2

6

I have tried GetKeyboardLayoutName() and GetKeyboardLayout() for getting the current keyboard layout, but they both give me the default layout and changing the layout doesn't affect the output!

while(1)
{
    Sleep(5);
    for(int i = 8; i < 191; i++)
    {
        if(GetAsyncKeyState(i)&1 ==1)
        {
            TCHAR szKeyboard[KL_NAMELENGTH];
            GetKeyboardLayoutName(szKeyboard);

            if(GetAsyncKeyState(i)&1 ==1)
            {
                TCHAR szKeyboard[KL_NAMELENGTH];
                GetKeyboardLayoutName(szKeyboard);
                cout << szKeyboard << endl ;
            }
        }
    }
}

It always gives me "00000409" when the default layout is set to English, while I expect it to be "00000429" when I change the layout to Farsi.

My first question here, I used to find all my answers by just searching. But right now I'm driving crazy after hours of searching around and getting nothing...

Arlenarlena answered 12/9, 2012 at 0:25 Comment(5)
Not sure this will help.. Try GetKeyboardLayoutList to see if the layout you want is at least loaded.. msdn.microsoft.com/en-us/library/windows/desktop/…Sodalite
@MohamedNuur: already tried that and it is loaded.Arlenarlena
I don't see the code that change the keyboard layout. I can only guess that it failed it change and you didn't check its error code.Kilo
Be aware that keyboard layout in Windows is a per-process setting, so make sure you are changing the layout for the right process before you are running the checks.Drawknife
Actually I wanted to know if the user manually changes the layout, though it's not changed programmatically. For getting the layout of current process I tried GetKeyboardLayout(GetCurrentThreadId()) and I though it would work. And still I don't know what's wrong with that.Arlenarlena
J
9

one thing that you need to notice is that ::GetKeyboardLayout (..) gets the lang for the passed thread identifer as a param.

each input thread can have different input locale lang. for instance if you put lets IE in the foreground and press Alt+Shift the lang changes to UK. ( you can see it in the taskbar )

now if you will Alt+Tab to another window ( which will be in foregorund ) you will see that lang dont have to stay UK.

so what you need to check is what is the thread id you are passing.

look at this code it will get you the lang for the current active window:

GUITHREADINFO Gti;
::ZeroMemory ( &Gti,sizeof(GUITHREADINFO));
Gti.cbSize = sizeof( GUITHREADINFO );
::GetGUIThreadInfo(0,&Gti);
DWORD dwThread = ::GetWindowThreadProcessId(Gti.hwndActive,0);
HKL lang = ::GetKeyboardLayout(dwThread);

to use GUITHREADINFO you need to define WINVER 0x500. put this in the stdafx.h before all the include.

#ifdef WINVER
#undef WINVER
#endif 
#define WINVER 0x500

source: GetKeyboardLayout not returning correct language ID (WINXP)

Jobber answered 12/9, 2012 at 7:41 Comment(1)
Thanks bro, it works as cahrm ;) I had used GetKeyboardLayout(GetCurrentThreadId()) and I thought it would do that...Arlenarlena
R
2

The following code is simple and works fine. If you write a command line program, the GetKeyboardLayout API does't work in windows cmd or powershell, you can test it in babun(an open source windows shell).

#include <Windows.h>
int getInputMethod() {
  HWND hwnd = GetForegroundWindow();
  if (hwnd) {
    DWORD threadID = GetWindowThreadProcessId(hwnd, NULL);
    HKL currentLayout = GetKeyboardLayout(threadID);
    unsigned int x = (unsigned int)currentLayout & 0x0000FFFF;
    return ((int)x);
  }
  return 0;
}
Riannon answered 29/5, 2018 at 2:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.