views:

478

answers:

2

My non-Unicode application needs to be able to process Unicode keyboard input (WM_CHAR/etc.), thus receive the 8-bit character code then internally convert it to Unicode. 9x-compatibility is required, so using most Unicode APIs is not an option.

Currently it looks at the language returned by PRIMARYLANGID(GetKeyboardLayout(0)), and looks up the relevant code page in a hard-coded table. I couldn't find a function to get the code page used by a particular language or keyboard layout. Converting a character/string can then be done with MultiByteToWideChar.

Is there a way to get the current keyboard layout's code page? GetACP returns the default system code page, which isn't affected by the current keyboard layout.

+1  A: 

I've had a similar problem on an application that needed to run on Windows 9X. The solution I eventually came up with was to listen for WM_INPUTLANGCHANGE notifications messages, which are sent to top-level windows when the user changes the input language. In my message procedure I have something like this:

case WM_INPUTLANGCHANGE:
  {
    CHARSETINFO cs;
    if (TranslateCharsetInfo((DWORD*)wParam,&cs,TCI_SRCCHARSET))
      m_codePage = cs.ciACP;
    return DefWindowProc(WM_INPUTLANGCHANGE,wParam,lParam);
  }
  break;

where m_codePage is a UNIT that is initialized as

  m_codePage = CP_ACP;

I then use m___codePage in calls to MultiByteToWideChar() to handle keys from WM_CHAR etc.

DavidK
This method has a flaw: if the default keyboard layout doesn't correspond to the system code page (CP_ACP), then the codepage will not be correct when the application starts.
CyberShadow
+2  A: 

Here's another way to do it:

WORD languageID = LOWORD(GetKeyboardLayout(0));
char szLCData[6+1];
GetLocaleInfoA(MAKELCID(languageID, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE,
               szLCData, _countof(szLCData));
int codepage = atoi(szLCData);
Deadcode