完全にVC++用のTipsです。Windows NT workstation 4.0 (Service Pack 5) + Visual Studio 5.0 Professional (Service Pack 3)でチェック済みです。
さらに,実は覚え書きだったりする。
UNICODEプログラムといっても,普通に書くだけです。少し書くときにコツがありますが。
従来文字コードを考えない場合です。
文字を扱うには,wchar_t型,またはWCHAR型を使います。文字列型としてはLPWSTRやLPCWSTRをつかいます。
文字定数や文字列定数を定義するときは,Lで修飾します。
'a' L'a' "テスト" L"テスト"
Lによる修飾を怠ると,"テスト"は0x83 0x65 0x83 0x58 0x83 0x67とコード化されます。これはUNICODEだと" 荘 "と取られてしまいます。
まず,コンパイラオプションやソースの先頭で,UNICODEという名前のシンボルを定義します。
#define UNICODE
これを行うと,lstrlenは"lstrlenW"に展開され,UNICODE文字列(LPCWSTR)を引数にとる関数になります。ちなみに,行っていない場合は"lstrlenA"に展開され,従来文字列(LPCSTR)を引数に取る関数になります。もちろん,直接lstrlenWと書けばいつでも関数は使えますし,UNICODEを定義していてもlstrlenAを使うことは可能です。
ランタイムライブラリをヘルプで引くとわかりますが,同一ヘッダファイルでUNICODE版の関数が呼び出せます。strlen→wcslen,printf→wprintf等。ちなみに,mainの変わりにwmainを使えばコマンドラインをUNICODEで取得できます。ただし,UNICODE版では標準出力へうまく出力できていないようです。
2001年7月31日追加
入出力関連を扱う場合は,ロケールを正しくセットする必要があります。なお,VC++の場合,全て従来文字コードに変換されて出力されています。Unicodeで出力したい場合は,WriteConsole APIを利用して下さい。
ここで一番躓くかも。メモリ確保に関しては,C++ではnewを使えば問題ないのですが,Cでmallocを使うときに,
LPWSTR ptr = malloc(wcslen(buf) + 1);
なんてやってしまうと,メモリ領域を破壊します。正しくは次のようになります。
LPWSTR ptr = malloc((wcslen(buf) + 1) * 2);
ポインタ操作でも,ポインタからサイズ計算するときにunsigned shortで扱っているのを忘れがちなので注意。
私の作成したDLLで,ANSI版(従来文字コード版)とUNICODE版を用意しているものがあります。これはソースは基本的に一つのファイルで,マクロで二つのオブジェクトファイルを作成するようにして手間を省いています。このとき,上に書いた以外のポイントがあります。
Win32 APIで定義したシンボルの他に,_UNICODEというシンボルを定義する必要があります。これは,Cランタイムライブラリと_Tマクロで利用します。UNICODEはWin32 APIとTEXTマクロで利用します。
#define UNICODE #define _UNICODE
CHAR(char)/WCHAR(wchar_t)の代わりにTCHARを,LPSTR/LPWSTRの代わりにLPTSTRを,LPCSTR/LPCWSTRの代わりにLPCTSTRを使います。
どちらも_TまたはTEXTマクロで囲みます。内容はどちらも同じで,非UNICODEの時はそのまま,UNICODEの時はLを付けるものです。
_T('a')
TEXT("あいうえお")
文字定数が_T,文字列定数がTEXTというわけではなく,逆の場合に使っても問題ないです。これは,私の癖ですので……。
前述の通りです。
UNICODE版のwcsやwが_tcsや_tになっているものを使います。_tmainってのも使えたと思います。tchar.hをインクルードする必要があります。
_tcslen(str);
_stpritnf (Buf, TEXT("%s - %s"), str1, str2);
面倒なのでmallocでの例を。
LPTSTR ptr = malloc ((_tcslen(buf) + 1) * sizeof(TCHAR));
sizeof(TCHAR)を使うことで,問題なくメモリを確保することが出来ます。C++なら
LPTSTR ptr = new TCHAR [_tcslen(buf) + 1];
で済むので楽ですが……。
Copyright © 大久保雄介(y-ookubo@246.ne.jp)