004:クロスプラットフォームに対応する

クロスプラットフォームに対応する

今日はWindows Mobile特有の文字の取り扱いについて説明します。

Windows MobileUnicodeプラットフォームです。文字はUnicodeとして取り扱うのが基本となります。そのためにはUnicodeに対応した文字列関数を使用する必要があります。使用するデータ型はchar型ではなく、wchar_tとなります。

結論から言うと文字列型にはTCHAR LPTSTR を使用すれば問題ありません。
これらの関数は、環境によって切り替える(UNICODE環境ではUnicode対応のデータ型を使用してくれる)汎用テキスト型です。環境に依存するCHAR と LPSTR は使用しません。

文字列定数の場合、Unicodeであれば、
WCHAR szStr = L"こんにちは世界";
と、L接頭辞を指定します。

しかし実際の文字列定数と文字定数には _T() マクロを使用します。たとえば、_T("string") や _T(‘s’) を使用し、L"string" や L’s’ は使用しません。
_T() マクロは、UnicodeであればL接頭辞をつけてくれ、そうでなければそのままの文字として解釈します。そのためL接頭辞を使用するより_T() マクロを使用したほうが他のWindows環境への移植性が上がるわけです。

Windows Mobile環境のみで使用するコードであることが明白であれば、これらを考慮する必要はありませんが移植可能なコーディングの慣例に従うように心がけておくことは無駄ではないでしょう。

では先ほどのwin01を修正してみましょう。
_T() マクロを使用するために、

#include <tchar.h>

を追加します。

WNDCLASSWは、WNDCLASSに変更
RegisterClassWは、RegisterClassに変更
CreateWindowWはCreateWindowに変更します。UNICODEマクロが定義されているのでそれぞれW付きの関数に展開されます。

変更点を赤文字で示します。

// win02.cpp

#include <windows.h>
#include <tchar.h>     //追加

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);

WCHAR szClassName = _T("win02"); // ウィンドウクラス。UNICODEとしての文字列定数

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,int nShowCmd)
{
 MSG msg;
 BOOL bRet;

 if (!InitApp(hInstance))
  return FALSE;
 if (!InitInstance(hInstance,nShowCmd))
  return FALSE;
 while*1 != 0) {
  if (bRet == -1){
   break;
  } else {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }
 return (int)msg.wParam;
}

// ウィンドウクラスの登録

ATOM InitApp(HINSTANCE hInst)
{
 WNDCLASS wc;
 wc.style  = CS_HREDRAW|CS_VREDRAW;
 wc.lpfnWndProc = WndProc; // プロシージャ名
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hInstance = hInst;
 wc.hIcon  = NULL;  // 未サポート
 wc.hCursor  = NULL;  // 未サポート
 wc.hbrBackground= (HBRUSH) COLOR_WINDOW;
 wc.lpszMenuName = NULL;  // 未サポート
 wc.lpszClassName=(LPCTSTR) szClassName;

 return (RegisterClass(&wc));
}

// ウィンドウの生成
BOOL InitInstance(HINSTANCE hInst, int nShowCmd)
{
 HWND hWnd;

 hWnd = CreateWindow(szClassName,_T("Window Title"),
  WS_CLIPCHILDREN, // ウィンドウの種類
  CW_USEDEFAULT,  // x座標
  CW_USEDEFAULT,  // y座標
  CW_USEDEFAULT,  // 幅
  CW_USEDEFAULT,  // 高さ
  NULL,    // 親ウィンドウのハンドル。親を作るのでNULL
  NULL,    // メニューハンドルまたは子ウィンドウID
  hInst,    // インスタンスハンドル
  NULL);
 if (!hWnd)
  return FALSE;
 ShowWindow(hWnd, nShowCmd);
 UpdateWindow(hWnd);
 return TRUE;
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
 switch (msg){
  case WM_DESTROY:
   PostQuitMessage(0);
   break;
  default:
   return (DefWindowProc(hWnd, msg, wp, lp));
 }
 return 0;
}

今日はここまで。

*1:bRet = GetMessage(&msg, NULL, 0, 0

上部へスクロール