VC6.0 または、もっと前に作られたツールをメンテナンスしていた時のことです。このプロジェクトでは、_MBCS が定義されています。このプロジェクトで、エラー文字列がすべてコード上に直書きされていたので、リソースに追い出したいなぁ、と思いました。
そこでリソースにいくつか書き出して、FormatMessage で取得しようとしたのですが、リソースが定義されていないというエラーが返ってきます。う~ん?こいつに渡すモジュール ハンドルって、_tWinMain の第一引数じゃないの?
まぁ、いいや。LoadString で取れるから。で、FormatMessage に、FORMAT_MESSAGE_FROM_STRING のオプションで引き渡して、展開してもらおう。。。
あかんやん。。。
たとえば、「"%1"は定義されていません。」という書式で、"ABC" を渡すとする。すると、「"ABC"は定義され・」のようになる。どうも、Shift_JIS でバイト数を計算すると27バイト必要で、27バイト(+1バイト)分の領域は確保してあるけど、16バイトしかコピーされていない。なんで?
そういえば、_tcsclen も、なんだか変な値を返してくれる。Shift_JIS のバイト数が欲しいのに、文字数を返してくる。どうも、バイト数で計算して領域を確保し、文字数でコピーしているようだ。
そういえば、_istleadbyte も、常に FALSE を返してくるようだ。なんで?
リファレンスを、よく読みましょう。>じぶん
_mbslen 関数と _mbstrlen 関数は、マルチバイト文字列のマルチバイト文字数を返します。_mbslen 関数は、現在使用中のマルチバイト コード ページに基づいて、マルチバイト文字のシーケンスを認識します。マルチバイト文字の有効性はテストしません。_mbstrlen 関数は、マルチバイト文字の有効性をテストし、現在のロケールの LC_CTYPE カテゴリ設定に基づいてマルチバイト文字のシーケンスを認識します。LC_CTYPE カテゴリの詳細については、「setlocale、_wsetlocale」を参照してください。
isleadbyte マクロは、引数がマルチバイト文字の最初のバイトの場合、0 以外の値を返します。isleadbyte は、任意の整数の引数が ?1 (EOF) ~ UCHAR_MAX (0xFF) の場合、意味のある結果を生成します。テストの結果は、現在のロケールの LC_CTYPE カテゴリの設定によって異なります。詳細については、「setlocale、_wsetlocale」を参照してください。
LC_CTYPE カテゴリ?そういえば大昔、UNIX でやってたときは、毎回きちんと書いていた^H^Hコピってたなぁ。完全に忘れてたよ。ついでに、当時は「せっとろーかるいー」と読んでいたっけ。
ということで、ロケールを "japanese_japan" に設定すれば、意図通りの動きになりました。じゃなくって、_tcsclen については、バイト数が欲しい場合は _tcslen ですね。あれ?C ロケールで、なんで Shift_JIS を理解するの?_istleadbyte は理解していないのに...謎だ。
でも、VS.NET 2003 で作った Win32 コンソールアプリは、setlocale していないのに意図通りの結果が返ってくるんだよなぁ?どこで細工してんだろ?
投稿日時 : 2007年8月20日 22:30