リスト2●Javaを使ってイベントを記述する例。
ここでは二つのイベントを登録している。一つはボタンがクリックされたときの処理。もう一つは終了イベントが発生したときの処理である。いずれもクラスを登録するという形で実装される。実際にはそのクラスの定められた名前のイベントが呼び出される
 一方Javaでも基本は同じだ。ボタン“ActionListener”に追加するという形でイベント・ハンドラを登録している(リスト2[拡大表示])。ただよく見ると細かい違いはある。.NET Frameworkの場合,イベント・ハンドラはメソッドである。ユーザが定義したメソッド名でも構わない。これに対しJavaはイベントを処理するクラスという形で実装している。ただJavaの場合も,実際に呼び出されるのはactionPerfomedという特殊な名称のメソッドである。

メッセージ・ループはどこに消えた?

 さてこのようにプログラムを見ても,どこにも「イベント通知を待つループ」は存在しない。これらは「クラス・ライブラリ」の見えないところですでに実装されているからだ。「ほとんどWin32 APIが見えている」と言われるMFCでさえ,メッセージ・ループ(Windowsにおけるイベント待ちループ)は存在しない(リスト3[拡大表示])。MFCを利用したプロジェクトを生成すると,それぞれメッセージのハンドラを実装するよう指示される。

 では実際のメッセージ・ループも見ておこう。ソース・コードそのものはかなり以前のWindowsプログラムのものだが,その基本は変わっていない(リスト4[拡大表示])。こう見ると,Windowsのプログラムは大きく二つに分かれている。メッセージを処理するメッセージ・ハンドラの部分と,メッセージ待ちをする部分である。メッセージ待ちをする部分はもともとプログラム実行の主体となる部分で,「WinMain」というエントリ・ポイント注5)を持つ。

リスト3●MFC(Microsoft Foundation Class)を使った場合のイベント処理。
ウィザードを使うと自動的に生成されるコードを抜粋した。MFCでは「Document-Viewモデル」を採用している。データ本体にかかわる部分を「Document」,ウインドウの見かけにかかわる部分を「View」として定義する。例えば再描画要求が発生すると,Viewを定義したクラス(ここではCmfcapp1View)の「OnDraw」というメソッドが呼び出される。また新規文書作成に相当するイベントには,Documentを定義したクラス(Cmfcapp1Docクラス)の「OnNewDocument」メソッドが対応する
 
リスト4●メッセージ・ループの実体。
メッセージ・ループは大きく二つのルーチンから成る。メッセージ・ループ本体と,メッセージ・ハンドラは別のルーチンに実装される。メッセージ・ループ本体を実行する前に,そのメッセージを処理するメッセージ・ハンドラをあらかじめ登録しておく。メッセージ・ループはその情報に基づいて,Windowsにメッセージの割り当てを依頼する。メッセージ・ハンドラはWindowsから呼び出される。そのメッセージの値から種類を判別して処理を実行する。最後にデフォルトのハンドラを呼び出す

 この手続きでメイン・ウインドウの生成とそのウインドウに対するメッセージ・ハンドラの登録,およびメッセージ待ちを実施する。

 一方現実に処理を担当するのがメッセージ・ハンドラである。Windowsはイベントが発生すると,各プロセスごとに用意した「メッセージ・キュー」にメッセージを積んでいく。これをメッセージ・ループが取り出す。そして今度は,メッセージの割り当て(dispatch)をWindowsに依頼する。一見ややこしく感じられるかもしれないが,仮にメッセージをメッセージ・ループ部で処理する構造になっていると,複数のウインドウを使ったプログラムの実現が難しくなる。

 メッセージはフィールドの値で識別する。Windowsが発行する主なメッセージには,ウインドウの再描画を依頼する「WM_PAINT」,メニュー・コマンドのクリックなどを通知する「WM_COMMAND」,終了処理である「WM_QUIT」などがある。すべてのWindowsのメッセージを知っておく必要はないが,特にMFCを利用する場合などはメッセージそのものと対応しているので,基本的な仕組みは理解しているべきだろう。

「そうですよね。OSがアプリケーションにイベントを通知する仕組みが必要ですよね。今まで見たことなかったですけど」
「今さらそんなところを見る必要もないからね」
「でも,ようやく仕組みが理解できたような気がします」
「仕組みをわかっていると,動作を想像しやすくなるよね。メモリのイメージがあるとポインタが理解しやすいのと一緒かな」
「あの…。ポインタは自信ないんですが…」
「今日はこんなところで。それはまた別の機会にしよう」

(北郷 達郎、八木 玲子)