如何获取当前键盘布局的代码页?

发布于 2024-08-01 16:11:25 字数 332 浏览 10 评论 0原文

我的非 Unicode 应用程序需要能够处理 Unicode 键盘输入(WM_CHAR/等),从而接收 8 位字符代码,然后在内部将其转换为 Unicode。 需要 9x 兼容性,因此不能选择使用大多数 Unicode API。

目前,它查看 PRIMARYLANGID(GetKeyboardLayout(0)) 返回的语言,并在硬编码表中查找相关代码页。 我找不到获取特定语言或键盘布局使用的代码页的函数。 然后可以使用 MultiByteToWideChar 来转换字符/字符串。

有没有办法获取当前键盘布局的代码页? GetACP 返回默认的系统代码页,该代码页不受当前键盘布局的影响。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

落墨 2024-08-08 16:11:25

虽然这是一个旧线程,但我今天早上的大部分时间都在寻找一种方法,用于在给定特定字符集 ID(当当前键盘布局/区域设置时)的情况下识别 Windows 代码页未设置为该字符集)。 我认为示例代码可能对其他寻找类似信息的人有用。

就我而言,我想将字符集值(例如 161(希腊语))映射到等效的 Windows 代码页 1253。经过大量挖掘后,我得出以下结论:

/*
 * Convert a font charset value (e.g. 161 - Greek) into a Windows codepage (1253 for Greek)
 */

UINT CodepageFromCharset(UINT nCharset)
{
    UINT nCodepage = CP_ACP;
    CHARSETINFO csi = {0};

    // Note, the symbol charset (2, CS_SYMBOL) translates to the symbol codepage (42, CP_SYMBOL).
    // However, this codepage does NOT produce valid character translations so the ANSI charset
    // (ANSI_CHARSET) is used instead. This appears to be a known problem.
    // See this discussion: "More than you ever wanted to know about CP_SYMBOL"
    // (http://www.siao2.com/2005/11/08/490495.aspx)

    if (nCharset == SYMBOL_CHARSET) nCharset = 0;
    DWORD* lpdw = (DWORD*)nCharset;

    // Non-zero return value indicates success...
    if (TranslateCharsetInfo(lpdw, &csi, TCI_SRCCHARSET) == 0)
    {
        // This should *not* happen but just in case make sure we use a valid default codepage.
    #ifdef _UNICODE
        csi.ciACP = 1200;
    #else
        csi.ciACP = CP_ACP;
    #endif
    }

    return csi.ciACP;
}

希望这对其他人有用!

约翰

Although this is an old thread, I just spent most of this morning searching for a method for identifying the Windows codepage given a specific charset ID (when the current keyboard layout/locale is NOT set to that charset). I figured that the sample code might be of use to others looking for similar information.

In my case I wanted to map a charset value such as 161 (Greek) to equivalent Windows codepage, 1253. After a lot of digging I came up with the following:

/*
 * Convert a font charset value (e.g. 161 - Greek) into a Windows codepage (1253 for Greek)
 */

UINT CodepageFromCharset(UINT nCharset)
{
    UINT nCodepage = CP_ACP;
    CHARSETINFO csi = {0};

    // Note, the symbol charset (2, CS_SYMBOL) translates to the symbol codepage (42, CP_SYMBOL).
    // However, this codepage does NOT produce valid character translations so the ANSI charset
    // (ANSI_CHARSET) is used instead. This appears to be a known problem.
    // See this discussion: "More than you ever wanted to know about CP_SYMBOL"
    // (http://www.siao2.com/2005/11/08/490495.aspx)

    if (nCharset == SYMBOL_CHARSET) nCharset = 0;
    DWORD* lpdw = (DWORD*)nCharset;

    // Non-zero return value indicates success...
    if (TranslateCharsetInfo(lpdw, &csi, TCI_SRCCHARSET) == 0)
    {
        // This should *not* happen but just in case make sure we use a valid default codepage.
    #ifdef _UNICODE
        csi.ciACP = 1200;
    #else
        csi.ciACP = CP_ACP;
    #endif
    }

    return csi.ciACP;
}

Hope this is useful for others!

John

韬韬不绝 2024-08-08 16:11:25

这是另一种方法:

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

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);
傲影 2024-08-08 16:11:25

我在需要在 Windows 9X 上运行的应用程序上遇到了类似的问题。 我最终想出的解决方案是监听 WM_INPUTLANGCHANGE 通知消息,当用户更改输入语言时,这些消息会发送到顶级窗口。 在我的消息过程中,我有这样的内容:

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

其中 m_codePage 是一个初始化的单元,然后

  m_codePage = CP_ACP;

我在调用 MultiByteToWideChar() 时使用 m___codePage 来处理来自 WM_CHAR 等的键。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文