1

現在、このチュートリアルを使用してWin32を学習していますが、表示される文字に苦労しています。

たとえば、作成時にウィンドウにメニューを追加する次のコードを見てください。

    case WM_CREATE: {
            HMENU hMenu, hSubMenu;
            HICON hIcon, hIconSm;

            hMenu = CreateMenu();
            hSubMenu = CreatePopupMenu();

            AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "Exit");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "File");

            hSubMenu = CreatePopupMenu();
            AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&GO");
            AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Stuff");

            SetMenu(hwnd, hMenu);

            hIcon = LoadImage(NULL, "Stuff.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);

            if (hIcon)
                SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
            else
                MessageBox(hwnd, "Could not load large icon!", "Load Error", MB_OK | MB_ICONERROR);

            hIconSm = LoadImage(NULL, "Stuff.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);

            if(hIconSm)
                SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
            else
                MessageBox(hwnd, "Could not load small icon!", "Load Error", MB_OK | MB_ICONERROR);
        }
        break;

これは、メッセージループから受信したWindowsメッセージを処理する関数内のswitchブロック内にあります。WndProc

表示される各文字列:

"Exit"
"File"
"&GO"
"&Stuff"

コードページが適切ではなかったように、実行時に小さな正方形として表示されるため、読み取り不能です。チュートリアルを実行すると、すべての文字列が正しく表示されます。私は、チュートリアルが正しいことを理解するのに役立つと言っていることに正確に固執する傾向があり、その教育法は優れています。ともかく!...

私が使用しているもの:

  1. Microsoft VisualStudio2008チームシステム;
  2. RDPを使用するMicrosoftWindowsServer 2003;
  3. ローカルOSはWindowsVistaUltimateです。

誰かがそれについての手がかりを持っていますか?

4

2 に答える 2

8

UnicodeとWindowsANSIの文字エンコードに問題があります。歴史的に、Windowsは拡張ASCIIを使用していたため、ANSIという名前を間違えていました。これにより、コードページが必要になりました。これは、8ビット文字でさえ、他の世界はもちろん、ヨーロッパのすべての書記体系を表すのに十分なコードポイントを提供しないためです。Win32が開発されたとき、彼らは優先文字セットとしてUnicodeを採用しました。(実際、彼らはUnicode文字セットのUTF-16LEエンコーディングに落ち着きましたが、その詳細は今のところ完全には関連していません。)ただし、Win16からWin32への移植も必要になると考えるには、既存のコードが多すぎます。すべての文字列の文字エンコードを変更します。

彼らの解決策は賢いものでした(賢すぎると主張する人もいます)。文字列を受け取るすべてのWin32APIエントリポイントには、2つの種類があります。最初のフレーバーはANSI文字列を受け取り、UTF-16LEへの変換を内部で処理します。2番目の(そして現在推奨されている)フレーバーは、UTF-16LE文字列を直接使用します。また、Visual Cチームと協力wchar_tして、16ビット型として定義し、L""文字列リテラルがASCIIテキストからUTF-16LEへのマッピングを使用するようにしました。

既存のWin16コードからの移植を容易にするために、MessageBox関数と文字列を受け取る他のすべてのWin32 APIは、コンパイル時にマクロによって、またはプリプロセッサシンボルが定義されているかどうかに応じてMessageBoxAマップされます。MessageBoxWUNICODE

このマッピングでは文字列リテラルを修正できないため、に応じてナローまたはワイドになる文字列リテラルを指定するマクロとUNICODE、変数がそれらへのポインターを保持するように宣言できるように一致するtypedefも導入しました。

したがって、Win16との間で最適な移植性を実現するには、またはの代わりにを#include <tchar.h>使用し、テキストを含むすべての文字列リテラルをマクロでラップし、.のような接尾辞のない名前でWin32APIを呼び出します。TCHARcharwchar_t_T()MessageBox

ただし、これは完全な解決策ではありません。TCHARコードがユーザーに表示される文字列を操作または計算する必要がある瞬間、レジームで完全に移植可能なコードを作成するのは難しいことに気付きます。sを操作するすべての標準文字列関数の代替品がありますが、コードが定義されている場合と定義されTCHARていない場合の両方でコードが正しくコンパイルおよび動作するように、それらを正しく使用したことを自動テストで確認することは困難ですUNICODE

今日新しいWin32コードを作成する場合、プロジェクトでUNICODEを定義し、それが実際に共通ヘッダーファイルで定義されていることを確認するチェックを追加し、L""文字列とWラップされたすべての呼び出しのフレーバーを明示的に使用することをお勧めします。

最後に、このエッセイ全体は、欠落している文字のグリフを表示するコードによって促されます(空の四角いボックスの文字は、フォントに特定の文字が欠落しているときに表示されるグリフです)。これは、ASCII文字列リテラルがWin32コードによってUTF-16LEであるかのように解釈されているために発生しているため、文字列「Exit」は2つのUnicode文字と見なされますU+7845U+7469これらは両方ともUnifiedHanの表意文字です。Hanフォントがインストールされていない限り、システム上のどのフォントにも両方が存在する可能性は非常に低いため、代わりに欠落している文字のグリフが表示されます。

これは、ラッパーマクロをASCII文字列リテラルと混合しているために発生しています。あなたが持っている:

AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "Exit");

ただし、次のいずれかが必要です。

AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, _T("Exit"));
AppendMenuA(hSubMenu, MF_STRING, ID_FILE_EXIT, "Exit");
AppendMenuW(hSubMenu, MF_STRING, ID_FILE_EXIT, L"Exit");

最後の例をお勧めします。

于 2010-12-13T21:53:16.033 に答える
4

小さな正方形についてのすべての当然の奇妙さで、あなたのコードは間違っています。Unicodeに準拠していません。すべての文字列の前にLを付け(L "string"のように)、コンパイル設定をUnicodeに変更する必要があります(これにより、Windows関数はUTF-16エンコーディングを受け入れるようになります)。これはWindowsのネイティブエンコーディングであり、Windowsでテキストを実行するための方法です。

別のアプローチは、ワイドAPIを使用し、APIを呼び出すときにUTF-16に変換することです。http://utf8everywhere.orgで説明されています。

于 2010-12-13T21:22:36.033 に答える