ダイアログボックスを作る(3)

前回の続きです。
今回は、WinMain()関数を見ます。
ここてやっていることは、「ダイアログを作成する」ことだけです。それにしては、 やたら複雑になっていますが、実は、32ビットに限れは、以下のような単純な 記述で済んでしまいます。
int PASCAL WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdshow){
	DialogBox(hinst, "EASYPLAY", NULL, easyplay);
	return 0;
}
DialogBox APIは、ダイアログボックスを生成します。ダイアログがクローズされると、 APIからリターンしてWinMain()に戻ってきます。
Dialogbox APIの第一引数は、ダイアログボックステンプレートが存在するプロセス のインスタンスハンドルです。通常はWinMainの第一引数をそのまま渡します。
第二引数は、ダイアログボックステンプレートの名前を渡します。
第三引数は、親ウィンドウのハンドルですが、今回の場合、今作ろうとしている ダイアログボックスがメインウインドウのため、親ウィンドウは存在しません。 よってNULLを渡します。
第四引数は、コールバック関数へのポインタです。つまりここでコールバック関数を OSに登録します。C言語で、easyplay()ではなくeasyplayというふうに、関数名だ けを記述した場合、その関数へのポインタという意味になります。

16ビットの場合、単に関数へのポインタを渡すだけでは、うまく動作しません。 これは、OSがプログラム中の関数を呼び出す場合に、どのプログラム(インス タンス)の関数か区別しないといけない(そうしないとグローバル変数に正しく アクセスできない)のに、16ビットWindowsではすべてのプログラムがアドレス 空間を共有しているという構造に由来するものです。 そのために、MakeProcInstance() と FreeProcInstance()が必要になります。 これは関数へのポインタに細工をして、個々のプログラム(インスタンス)を 区別させると考えれば良いでしょう。(正確なことを知りたい方は、 「インスタンスサンク」をキーワードに文献をあたってみてください。)

32ビットではこの二つの関数は「何もしない関数」としてwindows.h内でマクロ定義 されているので、ソースを共通化するために32ビットでもこの二つの関数を呼び出す ように記述して何ら問題ありません。(FreeProcInstance()は本当に何もしない。 MakeProcInstance()は第一引数を戻り値にコピーするだけ。) ただしそのせいで、C言語モードで「コードは効果を持たない」という警告を出す コンパイラが存在するようです。

なお、16ビットでも「スマートコールバック」オプションのあるコンパイラを使えば MakeProcInstance()、FreeProcInstance()は不要になります。

16ビットでは、コールバック関数はexportする必要があります。 これはDEFファイルで行う場合とCソース中でexportキーワードを使って行う場合があります。 これを忘れると、奇妙な動作をして別のバグと勘違いすることがあります。 これも正確に説明しようとするとマシン語コードをもちださなければならなくなるので、 「関数をプロセスの外から呼び出せるようにするためのおまじない」ぐらいに 考えておいてください。

ダイアログボックスを作る(まとめ)

まとめると、ダイアログボックスを出すために必要なのは、以下の五つ。
  1. ダイアログボックステンプレート
    (DLGファイルに記述してRCファイルで#includeする。もしくは直接RCファイル に記述してもよい)ダイアログボックスのデザインを定義した物です。
  2. ダイアログプロシージャ
    WM_INITDIALOGメッセージへの応答は、省略できません。 また、IDCANCELコントロールからのWM_COMMANDメッセージで必ずEndDialog()を呼び出す必要があります。
  3. DialogBox() API呼び出し
  4. MakeProcInstance() と FreeProcInstance()
    (16ビットで、スマートコールバックを使わない場合)
  5. export宣言
    (16ビットの場合)

前のページ

次のページ

一つ上のページに戻る