2010-12-13 2 views
1

私は現在、this tutorialを使ってWin32を学んでいますが、私は表示された文字で苦労しています。私のキャラクタセット(Win32 API)の問題

インスタンスの作成時に私の窓にメニューを追加するコードのこの部分を取る:

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メッセージを処理し、私のWndProc関数内switchブロックの内側にあること。

表示される各文字列:彼らはコードページが正しいものか、そのようなものではなかっただけのように、少しの正方形として表示されるよう

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

は、実行時に読めないですが。チュートリアルを実行すると、すべての文字列が正しく表示されます。私はチュートリアルが正しいことを手助けするために言っていることにちょうど固執する傾向があり、その教授法は良いです。 !とにかく...

は、私が使用しています:

  1. のMicrosoft Visual Studio 2008のチームシステム。
  2. RDPを使用するMicrosoft Windows Server 2003。
  3. ローカルOSはWindows Vista Ultimateです。

誰でも手掛かりがありますか?

答えて

6

UnicodeとWindowsのANSI文字エンコードに問題があります。歴史的に、Windowsは拡張ASCIIを使用して、ANSIと誤って名前を付けました。 8ビット文字でもヨーロッパのすべての書記体系を表現するのに十分なコードポイントが提供されていないため、これはコードページの必要性をもたらしました。 Win32が開発されたとき、彼らは好みの文字セットとしてUnicodeを解決しました。 (実際には、Unicode文字セットのUTF-16LEエンコーディングを解決しましたが、その詳細は現在のところ完全には関係ありません)。しかし、Win16からWin32への移植には、すべての文字列の文字エンコーディングを変更します。

彼らの解決策は賢明でした(賢明すぎると主張している人もいます)。文字列を受け取るすべてのWin32 APIエントリポイントには2つの味があります。最初のフレーバはANSI文字列を取り、内部的にUTF-16LEへの変換を処理します。 2番目の(そして現在好ましい)フレーバは、UTF-16LE文字列を直接受け取ります。また、Visual Cチームと協力して、wchar_tを16ビットタイプとして定義し、L""文字列リテラルがASCIIテキストからUTF-16LEへのマッピングを使用するようにしました。既存のWin16コードに簡単に移植するようにするに

MessageBox機能と文字列を取り、他のすべてのWin32 APIのは、プリプロセッサシンボルUNICODEが定義されているかどうかに応じて、MessageBoxAMessageBoxWのいずれかにマクロによってコンパイル時にマップされます。

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

だから、へとWin16のから最高の移植性のために、あなたは#include <tchar.h>_T()マクロ内のすべてのテキストを含む文字列リテラルをラップし、非接尾辞でのWin32 APIを呼び出して、charまたはwchar_tの代わりにTCHARを使用しますMessageBoxのような名前です。

しかし、これは完璧な解決策ではありません。あなたのコードがユーザに表示される文字列を操作または計算する必要がある瞬間、TCHAR体制で完全に移植可能なコードを書くのは難しいことがわかります。 TCHARを操作するすべての標準文字列関数の置き換えがありますが、コードが正しくコンパイルされ、UNICODEが定義されている場合とない場合の両方で正しく動作することを自動テストで検証することは困難です。

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

最後に、このエッセイ全体は、欠けている文字グリフを表示するコードによってプロンプトされます(空の四角いボックス文字は、フォントに特定の文字がないときに表示されるグリフです)。あなたのASCII文字列リテラルがUTF-16LEであるかのようにWin32コードによって解釈されているため、「Exit」という文字列が2つのUnicode文字、つまりU+7845およびU+7469であり、どちらも統一された半表意文字です。 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"); 

は、最後の例を推薦します。

+0

+1と回答が受け入れられました。クライアントが要求する以上に多くの詳細に回答しています。あなたのおかげで、私は今、 'A'と' W'の味でこれらの関数が何であるか知っています。したがって、この貴重な情報を反映するようにコードを変更します。どうもありがとう! –

4

小さな四角については、すべての違和感がありますが、コードは間違っています。 Unicodeに準拠していません。すべての文字列の前にL( "L"文字列のように)を置き、コンパイル設定をUnicodeに変更する必要があります(これにより、Windows関数はUTF-16エンコーディングを受け入れます)。これはWindowsのネイティブエンコーディングです。これは、テキストがウィンドウ上でどのように行われるかを示しています。

APIを呼び出すときに、広いAPIを使用してUTF-16に変換する方法もあります。それはhttp://utf8everywhere.orgに記載されています。

+0

なぜ、チュートリアルで悪いコードが表示されるのか理解できません。さらに、エンコーディングを除いて正常に動作します。あなたが言及しているように、私はエンコーディングに注目します。 –

+0

これは 'L '文字列' 'を書くときに機能します。 –

+1

Webページの著作権日付で判断すると、このチュートリアルは、UnicodeがWin32アプリケーションで標準となる前に書かれています。このコードは、プロジェクトがANSI文字セットに設定されている場合にコンパイルされます(VS内のプロジェクトを右クリックし、[プロパティ]、[一般])。コードがANSIとUnicodeの両方で大まかに動作する理由は、AppendMenuがANSIのAppendMenuAに#、Unicode(ワイド文字)のAppendMenuWがその設定に基づいて切り替わることです。 -A関数と-W関数の宣言を見ると、文字列パラメータ以外のパラメータは同じであることがわかります。 –

関連する問題