ここでは、メッセージの入力、格納、および書式化を Win32 アプリケーション
で行う方法について説明します。

_______________________________________________________________
1.  メッセージの入力

メッセージは、テキスト ファイルに ASCII テキストとして入力されます。
このファイルの形式では、サポートする言語ごとに 1 つずつ、同じメッセージ 
テキストのバージョンを複数指定できます。また、記号定数を使ったメッセー
ジへのアクセスを目的としてアプリケーションで使う C 言語インクルード 
ファイルを生成するとともに、コード番号を各メッセージに自動的に割り当て
ることもできます。メッセージ テキスト ファイルの目的は、同じイメージ 
ファイルを使って複数の言語を簡単にサポートできるような書式で、アプリケー
ションに必要なすべてのメッセージを定義することにあります。

メッセージ テキスト ファイルは、MC プログラムによりバイナリ リソース 
ファイルに変換されます。その後、各バイナリ リソース ファイルは RC コン
パイラに入力され、アプリケーションまたは DLL 用のリソース テーブルに置
かれます。

メッセージ テキスト ファイルの形式 (デフォルトの拡張子は .mc) で、基本
となる構文は「キーワード=値」で、このとき等号の前後に空白があっても無視
されます。値と次の「キーワード=値」との間は空白で区切られます。キーワー
ド名で比較するときは大文字小文字の区別はありません。値の部分は、C 構文を
使った整数定数の {NUMBER}、C 識別子名の規則に従ったシンボル名の {NAME}、ま
たは FAT ファイル システムの規則に従った {FILENAME}(8 文字以下で、ピリ
オドなし) のいずれでもかまいません。

コメント行は、メッセージ テキスト ファイルに指定できます。コメント構文は 
WIN.INI の場合と同じで、コメントはセミコロン(;)で始まり、その行の終わり
まで続きます。行にコメントしかないときは、セミコロンを C の行末コメント
構文 (//) に変換して、出力の .h ファイルへそのままコピーします。

メッセージ テキスト ファイルは、全体として以下に示す 0 個以上のキーワード
が入ったヘッダー セクションで構成されます。

	MessageIdTypedef={NAME}
	SeverityNames=({NAME}={NUMBER}:{NAME})
	FacilityNames=({NAME}={NUMBER}:{NAME})
	LanguageNames=({NAME}={NUMBER}:{FILENAME})

次に、各キーワードの意味を説明します。

MessageIdTypedef
	MessageId の数値ごとに typedef 名として出力するシンボル名を
	指定します。デフォルト値は NULL で、これは MessageId のシンボル
	名を定義するときに型キャスト出力がないことを意味します。

SeverityNames
	メッセージ定義に Severity キーワードの値として指定できる名前の
	集合を定義します。集合はかっこで区切ります。Severity の各名前に
	関連付けられる値は、Facility 値と MessageId で論理和をとって、
	左に 30 ビットだけシフトしたときに、完全な 32 ビット メッセージ 
	コードに対応するビット パターンを指定する数値です。このキーワー
	ドのデフォルト値は以下のとおりです。

                SeverityNames=(Success=0x0
                               Informational=0x1
                               Warning=0x2
                               Error=0x3
                              )

	Severity 値は、32 ビット メッセージ コードの上位 2 ビットで表し
	ます。2 ビットに該当しない Sevirity 値はエラーになります。各値
	の後に :{NAME} を続けると、Sevirity コードにシンボル名を指定す
	ることができます。

FacilityNames
	メッセージ定義に Facility キーワードの値として指定できる名前の
	集合を定義します。集合はかっこで区切ります。各 Facility 名と関連
	付けられる値は、Severity 値と MessageId で論理和をとって、左に 
	16 ビットだけシフトしたときに、完全な 32 ビット メッセージ コード
	に対応するビット パターンを指定する数値です。このキーワードのデ
	フォルト値は以下のとおりです。

                FacilityNames=(System=0x0FF
                               Application=0xFFF
                              )

	Facility コードは、32 ビット メッセージ コードの上位 16 ビット
	のうちの下位 12 ビットで表します。12 ビットに該当しない  Facility 
	コードはエラーになります。ここでは、4096 の Facility コードを
	許可しています。最初の 256 コードは、システム ソフトウェアで使
	うために予約されています。

	各値の後に :{NAME} を続けると、 Facility コードにシンボル名を
	指定できます。

LanguageNames
	メッセージ定義に言語キーワード値として指定できる名前の集合を
	定義します。集合はかっこで区切ります。各言語名と関連があるのは、
	その言語に対応するすべてのメッセージ テキストが入るバイナリ出力
	ファイルの名前を指定するために使うファイル名と数値です。数値は、
	リソース テーブルで使う言語 ID に対応します。数値とファイル名は
	コロン (:) で区切ります。このキーワードの初期値は以下のとおりです。

                LanguageNames=(English=1:MSG00001)

	アプリケーションにより .mc ファイルに定義される新規の名前で、
	組み込み名を上書きしないものは、有効な言語一覧に追加されます。
	このため、アプリケーションでは記述名で専用の言語をサポートで
	きます。

ヘッダー セクションの後には、0 個以上のメッセージ定義が続きます。各メッ
セージ定義は、以下の 1 つ以上のキーワードで始まります。

	MessageId={|{NUMBER}|+{NUMBER}}
	Severity={SEVERITY_NAME}
	Facility={FACILITY_NAME}
	SymbolicName={NAME}

MessageId キーワードはメッセージ定義の先頭に印を付けるために必要ですが、
省略してもかまいません。値を指定しないときは、Facility に使った最後の
値に 1 を加えた値を使います。+{NUMBER} の値を指定したときは、Facilityに
使った最後の値にプラス記号の後の数値を加えた値を使います。そのほかの数
値を指定したときは、指定された値を使います。16 ビットに該当しない 
MessageId 値はすべてエラーになります。

Severity および Facility のキーワードは省略可能で、追加ビットを指定して
最終的に 32 ビット メッセージ コードへの論理和を取ることができます。どち
らの値も指定しないときは、デフォルトとしてメッセージ定義に最後に指定した
値をとります。最初のメッセージ定義を処理する前のこれらの変数の初期値は、
以下のとおりです。

	Severity=Success
	Facility=Application

これらのキーワードと関連する値は、FacilityNames キーワードおよび 
SeverityNames キーワードに指定した名前のいずれかと一致しなければなりま
せん。また SymbolicName キーワードを指定すると、ISV で、MessageId、
Severity および Facility の各ビットの論理和を取った結果である最後の 
32 ビット メッセージ コードと C の記号定数名とを関連付けることができ
ます。定数定義は、生成した .h ファイルに以下の書式で出力されます。

	//
	// {MESSAGETEXT}
	//

	#define CONSTANT_SYMBOL_NAME ((MessageIdTypedef) 0x12345678)

この場合、定義の前にあるコメントはメッセージ定義に指定した最初の言語で
のメッセージ テキストのコピーです。CONSTANT_SYMBOL_NAME は SymbolicName 
キーワード値です。この値がデフォルトの NULL のときには MessageIdTypedef 
は出力されません。

メッセージ定義キーワードの後には、1 つ以上のメッセージ テキストの定義が
続きます。各メッセージ テキストの定義は、どのバイナリ出力ファイルがこの
メッセージ テキストの出力先となるかを識別する言語キーワードで始まります。
その次の行がメッセージ テキストの 1 行目になります。先頭にピリオドが 
1 つある行がくると、その行でメッセージ テキストは終了します。その後には、
新しい行が続きます。キーワードの前後には空白は入りません。メッセージ 
テキスト内であれば、空白行および空白もメッセージの一部として保持されます。

	Language={LANGUAGE_NAME}
	{MESSAGETEXT}
	.

メッセージ テキスト内では、メッセージを動的に書式化するために複数のエ
スケープ シーケンスがサポートされています。エスケープ シーケンスは、
すべてパーセント記号 (%) で始まります。

    %0
	後続改行を入れずにメッセージ テキスト行を終了します。これにより、
	長いメッセージの作成または後続改行のないメッセージの終了が可能
	になります。入力を要求するメッセージに役立ちます。

    %n!printf format string!
	挿入を識別します。n には 1 から 99 までの値を指定できます。
	printf 書式文字列は感嘆符で囲んでください。これは省略可能で、
	特に指定のない限り、デフォルトとして !s! の値をとります。

	printf 書式文字列には、精度または幅の構成要素として * 指定子を
	指定してもかまいません。* 指定子を指定した場合には、実行時に挿入 
	%n+1 および %n+2 の値を使います。メッセージ テキストのほかの部
	分でこれらの挿入に対して明示的に参照を行うと、MC により警告メッ
	セージが画面出力されます。

挿入では、FormatMessage API 呼び出しへ渡されたパラメータを参照しなけれ
ばなりません。FormatMessage API 呼び出し書式文字列へ渡されなかった挿入
をメッセージで参照した場合には、エラーが戻されます。

パーセント記号に数字以外の文字が続くと、その文字はパーセント記号の付か
ない出力メッセージに書式化されます。次に、例を示します。

    %%
	書式化メッセージ テキストにのパーセント記号を 1 つ出力します。

    %n
	行末で発生した場合には、強制改行を出力します。FormatMessage で
	通常の改行を提供しているときに便利で、メッセージを特定の幅に納
	めることができます。

    %r
	強制復帰を出力します。後続の改行はありません。

    %b
	書式化メッセージ テキストに空白を出力します。これにより、メッ
	セージ テキスト行に後続空白を必要な数だけ確保できます。

    %t
	書式化メッセージ テキストにタブを出力します。

    %.
	書式化メッセージ テキストにピリオドを 1 つ出力します。これにより、
	メッセージ テキスト定義を終了することなく行頭にピリオドを 1 つ
	確保できます。

    %!
	書式化メッセージ テキストに簡単符 (!) を 1 つ出力します。これ
	により、 printf 書式文字列の開始と間違うことなく挿入の直後に
	簡単符 (!) を確保できます。

Unicode サポートについてはまだ定まっていません。入力ファイルが ASCII 
テキストの場合には、Unicode 値を入力可能にするためのエスケープ シーケン
スが必要となる可能性があります。また、適切な機能を備えたテキスト エディ
タがあると想定したとき、テキスト ファイル内で DBCS (ダブルバイト文字
セット) だけを使う必要があるかもしれません。


_______________________________________________________________
2.  メッセージ コンパイラ (MC)

このプログラムにより、.mc メッセージ テキスト ファイルはリソース コン
パイラを使って .RC ファイルへインクルードするのに適したバイナリ ファイ
ルへ変換されます。

コマンド行の構文

	MC [-v] [-w] [-s] [-h DirSpec] [-r DirSpec] filename[.mc] ...

ここで、各オプションは次のようになります。

    -v
	stderr へ詳細出力を行います。

    -w
	OS/2 mkmsgf でサポートする型のスーパーセットである挿入エスケー
	プ シーケンス (つまり、%0 および %n 以外) を認識するたびに警告
	メッセージを生成します。既存の OS/2 メッセージ ファイルをこの
	形式に変換するときに役立ちます。

    -s
	メッセージ ID に関連するシンボル名である各メッセージ テキストの
	先頭に補足行を追加します。

    -h DirSpec
	生成した .h ファイルの格納先ディレクトリを指定します。ファイル
	名は .mc ファイル名に .h 拡張子を付けたものです。

    -r DirSpec
	生成した .rc ファイルの格納先ディレクトリを指定します。ファイル
	名は .mc ファイル名に .rc 拡張子を付けたものです。

    filename.mc
	1 つ以上のバイナリ リソース ファイルへコンパイルする 1 つ以上
	の入力メッセージ ファイルを指定します。メッセージ ファイルに入っ
	ているメッセージ テキストの言語ごとに 1 つずつファイルを指定
	します。

メッセージ コンパイラでは .mc ファイルを読み取り、シンボル名定義がすべ
て入った .h ファイルを生成します。メッセージ テキストを指定するために
使った各 LanguageId に対しては、メッセージ テーブル リソースの入った
バイナリ ファイルを 1 つ出力します。また、適切な RC 構文の入った .rc 
ファイルを 1 つ出力して、適切な名前と型 ID で各バイナリ ファイル出力を
リソースとしてインクルードします。


_______________________________________________________________
3.  メッセージ Win32 API 呼び出し

DWORD
APIENTRY
FormatMessage(
    DWORD dwFlags,
    LPVOID lpSource,
    DWORD dwMessageId,
    DWORD dwLanguageId,
    LPSTR lpBuffer,
    DWORD nSize,
    va_list Arguments
    )

ルーチンの説明
	この関数によりメッセージ文字列を書式化します。この関数への入力
	がメッセージ定義となります。入力は、この関数へ渡されたバッファ
	から行えます。すでにロードされているモジュールのメッセージ テー
	ブル リソースからも行えます。つまり、システム メッセージ テー
	ブル リソースを検索してメッセージを見つけるように呼び出し元から
	この関数へ要求することもできるということです。この関数では、
	メッセージ ID および言語 ID をもとにメッセージ定義を探し、必要
	であれば任意の組み込み挿入シーケンスを処理しながらメッセージ 
	テキストを出力バッファへコピーします。

引数

    dwFlags
	書式化処理のオプションおよび lpSource パラメータを解釈する方法
	を指定します。このパラメータの下位 16 ビットは、文字単位の行の
	最大幅です。以下に可能な値を示します。

    FORMAT_MESSAGE_ALLOCATE_BUFFER
	lpBuffer は PVOID * で、nSize は最小割り当てサイズです。この関
	数は書式化メッセージを保持するのに十分な大きさのバッファを割り
	当て、lpBuffer で指す位置にバッファへのポインタを格納します。
	処理が終了したら、呼び出し元は LocalFree でバッファを解放しな
	ければなりません。

    FORMAT_MESSAGE_IGNORE_INSERTS
	メッセージ定義の挿入シーケンスは無視され、そのまま出力バッファ
	へ渡されます。後で書式化するためのメッセージを取り出すときに役
	立ちます。このフラグを設定すると、lpArguments パラメータは無視
	されます。

    FORMAT_MESSAGE_FROM_STRING
	lpSource は NULL で終了するメッセージ定義へのポインタです。.mc 
	ファイルのメッセージ テキストの場合と同様、挿入シーケンスにも
	指定できます。

    FORMAT_MESSAGE_FROM_HMODULE
	lpSourceは、検索の対象となるメッセージ テーブル リソースが入っ
	ているモジュール ハンドルです。このハンドルが NULL であれば、
	現在のプロセスのアプリケーション イメージ ファイルを検索します。

    FORMAT_MESSAGE_FROM_SYSTEM
	要求したメッセージが lpSource にないとき、また lpSource を調べ
	なかった (つまり、上記の 2 つのフラグを指定しなかった) とき、
	この関数はシステム メッセージ テーブル リソースを検索します。

    FORMAT_MESSAGE_ARGUMENT_ARRAY
	この引数を設定すると、渡される Arguments パラメータは va_list 
	構造体の代わりに引数を表す 32 ビット値配列のポインタであること
	を示します。

    FORMAT_MESSAGE_MAX_WIDTH_MASK
	下位 8 ビットで、出力バッファ内へ書式化された各行の最大幅を指
	定します。最大幅にゼロを指定すると、幅に関する制限はなくなり、
	メッセージ定義の改行だけが出力バッファに格納されます。ゼロ以外
	の値を指定すると、メッセージ定義テキストの改行は無視されます。
	代わりに改行で分割されていない文字列を区切っている空白コードを
	使い、最大幅をもとに改行コードを計算します。メッセージ定義テキ
	スト内で強制コーディングした改行は %n エスケープ シーケンスで
	識別しますが、この改行は常に出力バッファに出力されます。

	幅に FORMAT_MESSAGE_MAX_WIDTH_MASK を指定すると、メッセージ 
	ファイル内の改行は無視され、明示的にコーディングした改行が維持
	されます。改行が新しく生成されることはありません。

    lpSource
	メッセージ定義の検索元を指定します。このパラメータの型は、
	dwFlags パラメータの設定によって異なります。

	    FORMAT_MESSAGE_FROM_HMODULE
		lpSource は、検索の対象となるメッセージ テキストが入っ
		ているモジュールの hModule です。

	    FORMAT_MESSAGE_FROM_STRING
		lpSource は、書式化していないメッセージ テキストを指す 
		LPSTR です。適宜、挿入の走査、書式化を行います。

	いずれのオプションも指定しない場合は、このパラメータは無視
	されます。

    dwMessageId
	要求されているメッセージを識別する 32 ビット メッセージ識別子
	を指定します。FORMAT_MESSAGE_FROM_STRING フラグを指定した場合
	には、このパラメータは無視されます。

    dwLanguageId
	要求されているメッセージの言語を識別する 32 ビット言語識別子を
	指定します。FORMAT_MESSAGE_FROM_STRING フラグを指定した場合には、
	このパラメータは無視されます。

    lpBuffer
	書式化メッセージを書き込むバッファへのポインタを指定します。
	終了 NULL バイトも書き込まれます。FORMAT_MESSAGE_ALLOCATE_BUFFER 
	フラグを指定すると、メッセージのテキストを入れるために、この
	パラメータはこの呼び出しで埋められた 32 ビットのポインタ値を 
	LocalAlloc により割り当てたポインタを指します。

    nSize
	出力バッファに格納できる最大バイト数を指定します。
	FORMAT_MESSAGE_ALLOCATE_BUFFER フラグを指定したときは、この
	パラメータは無視されます。

    Arguments
	不定数の変数へのポインタを指定します。これらの引数を使って書式
	文字列での挿入要求を満たします。したがって、書式文字列の %1 は、
	Arguments パラメータで記述した不定数引数の中の最初の引数を指定し、
	%3 は 3 番目の引数を指定するといったぐあいです。

	各 32 ビット引数の値の解釈は、メッセージ定義の挿入に関連する
	書式化情報によって異なります。デフォルトでは、NULL で終わる文字
	列へのポインタとして各ポインタを処理します。

	デフォルトにより Arguments パラメータの型 はva_list に設定され
	ており、これは不定数引数を記述するための言語および実装固有の
	データ型です。型 va_list のポインタがあるときは、
	FORMAT_MESSAGE_ARGUMENT_ARRAY フラグを指定し、挿入値として書式
	化されたメッセージへ入力する 32 ビット値の配列へポインタを渡し
	ます。

戻り値

    DWORD
	出力バッファに実際に格納されたバイト数 (最後の NULL は除く) を
	戻します。エラーが発生したときには 0 を戻します。GetLastError 
	API により、詳細なエラー状態を入手することができます。
