在 MessageBox 中显示区域字符而不设置所需的语言环境

Posted

技术标签:

【中文标题】在 MessageBox 中显示区域字符而不设置所需的语言环境【英文标题】:Show regional characters in MessageBox without setting required locale 【发布时间】:2014-09-09 09:53:32 【问题描述】:

我需要显示带有ISO/IEC 8859-13 代码页中描述的区域字符的MessageBox,而不将Windows 语言环境设置为此区域。我很天真,试图用一个字节字符显示 ASCI 表:

void showCodePage()



    char *a = new char[10000];
    char *aa = new char[10000];
    int f=0;
    int lines =0;
    for (int i=1; i<255;i++ )
    
        sprintf(a,"%c %0.3d ",i,i);
        sprintf(aa,"%c",i);
        f++;
        a+=6;
        aa++;

        if (f==8)
        
            f=0;
            sprintf(a,"%c",0x0d);
            a++;
            lines++;
        

    

    *aa=0;
    *a=0;
    a-=254*6+lines;
    aa-=254;


    MessageBox(NULL, aa , "Hello!", MB_ICONEXCLAMATION | MB_OK);
    MessageBox(NULL, a  , "Hello!", MB_ICONEXCLAMATION | MB_OK);

    delete [] a;
    delete [] aa;


好的,这不能正确显示 ISO/IEC 8859-13,如果不更改语言环境,这是不可能的:

现在我决定制作 unicode wstring。从单字节 char 转换为 unicode wchar 函数:

wstring convert( const std::string& as )

    // deal with trivial case of empty string
    if( as.empty() )    return std::wstring();

    // determine required length of new string
    size_t reqLength = ::MultiByteToWideChar( CP_UTF8, 0, as.c_str(), (int)as.length(), 0, 0 );

    // construct new string of required length
    std::wstring ret( reqLength, L'\0' );

    // convert old string to new string
    ::MultiByteToWideChar( CP_UTF8, 0, as.c_str(), (int)as.length(), &ret[0], (int)ret.length() );

    // return new string ( compiler should optimize this away )
    return ret;

并改变 MessageBox'es:

MessageBoxW(NULL, convert(aa).c_str(), L"Hello!", MB_ICONEXCLAMATION | MB_OK);
MessageBoxW(NULL, convert(a).c_str() , L"Hello!", MB_ICONEXCLAMATION | MB_OK);

结果还是悲哀:

另一方面,我期待什么?我需要以某种方式告诉系统它应该使用哪个代码页来显示可能的字符。怎么做?

【问题讨论】:

【参考方案1】:

您的解决方案的问题是带有CodePage 参数CP_UTF8 的函数MultiByteToWideChar 不会将您的特定ASCII 代码页转换为UTF-16,它将UTF-8 转换为UTF-16,这不是你需要的。

您要查找的是从ISO/IEC 8859-13 中的字符到WideChar 的转换表。您可以从https://en.wikipedia.org/wiki/ISO/IEC_8859-13 中的表格手动制作一个,例如160 变为 00A0161 变为 201D,以此类推。

【讨论】:

以上是关于在 MessageBox 中显示区域字符而不设置所需的语言环境的主要内容,如果未能解决你的问题,请参考以下文章

MessageBox没有关注MessageBoxButton

如何在iOS中显示大按钮而不单击按钮(单击该按钮周围的区域)

区域在 .net 核心中显示为查询字符串

MessageBox 隐藏不显示

如何修复从Delphi应用程序调用它时在C ++ DLL中的MessageBox中显示的无效字符?

MessageBox置顶的方法