2

文字列テーブルを含む RC ファイルを作成しました。

文字: ö ü ú ő ű á é. そのため、文字列を UTF-8 エンコーディングで保存します。

しかし、cpp ファイルを呼び出すと、次のようになります。

LoadString("hu.dll", 12, nn, MAX_PATH);

私は奇妙な結果を得ます:

予期しない文字によるエラー メッセージ

この問題を解決するにはどうすればよいですか?

4

1 に答える 1

8

コメントで他の人が指摘しているように、Windows API は UTF-8 でエンコードされたテキストを直接サポートしていません。MessageBox関数 UTF-8 でエンコードされた文字列を渡して、期待する出力を取得することはできません。代わりに、ローカル コード ページの文字として解釈します。

Windows API 関数 (を含むMessageBox) に渡す UTF-8 文字列を取得するには、MultiByteToWideChar関数を使用して UTF-8 から UTF-16 (Windows が Unicode またはワイド文字列と呼ぶもの) に変換する必要があります。CP_UTF8最初のパラメーターにフラグを渡すことは、この変換を可能にする魔法です。例:

std::wstring ConvertUTF8ToUTF16String(const char* pszUtf8String)
{
    // Determine the size required for the destination buffer.
    const int length = MultiByteToWideChar(CP_UTF8,
                                           0,   // no flags required
                                           pszUtf8String,
                                           -1,  // automatically determine length
                                           nullptr,
                                           0);

    // Allocate a buffer of the appropriate length.
    std::wstring utf16String(length, L'\0');

    // Call the function again to do the conversion.
    if (!MultiByteToWideChar(CP_UTF8,
                             0,
                             pszUtf8String,
                             -1,
                             &utf16String[0],
                             length))
    {
        // Uh-oh! Something went wrong.
        // Handle the failure condition, perhaps by throwing an exception.
        // Call the GetLastError() function for additional error information.
        throw std::runtime_error("The MultiByteToWideChar function failed");
    }

    // Return the converted UTF-16 string.
    return utf16String;                    
}

次に、ワイド文字列を取得したら、MessageBox関数のワイド文字列バリアントを明示的に呼び出しますMessageBoxW

ただし、Windows のみをサポートする必要があり、どこでも UTF-8 を使用する他のプラットフォームをサポートする必要がない場合は、UTF-16 でエンコードされた文字列のみを使用する方がはるかに簡単です。これは、Windows が使用するネイティブ Unicode エンコーディングであり、これらの種類の文字列を任意の Windows API 関数に直接渡すことができます。Windows API 関数と文字列間の相互作用の詳細については、こちらの回答を参照してください。私が他の人にしたのと同じことをあなたに勧めます:

  • それぞれ、文字と文字列に固執しwchar_tますstd::wstring
  • およびWを含む Windows API 関数のバリアントを常に呼び出します。LoadStringWMessageBoxW
  • Windows ヘッダーを含める前に、またはプロジェクトのビルド設定でUNICODEおよびマクロが定義されていることを確認してください。_UNICODE
于 2013-03-22T23:24:59.113 に答える