メッセージのディスパッチ
メッセージ処理機構の概要 への移動
アプリケーションでウィンドウを作成するときは、Windows カーネルにウィンドウ プロシージャを登録します。 ウィンドウ プロシージャは、ウィンドウに送られるメッセージを処理するルーチンです。 従来、ウィンドウ プロシージャには、そのウィンドウで処理する必要があるメッセージごとにエントリを持つ巨大な case 文が含まれています。 なお、ここでは "ウィンドウ" という用語は、各ウィンドウ、各コントロールなど、画面に表示されるほとんどあらゆるものを表しています。 新しい種類のウィンドウを作成するたびに、完全なウィンドウ プロシージャを作成する必要があります。
VCL では、以下の方法でメッセージ ディスパッチを簡略化しています。
- 各コンポーネントが完全なメッセージ ディスパッチ機構を継承する。
- ディスパッチ機構にはデフォルトの処理が用意されている。ユーザーは、特別な応答をする必要があるメッセージに対してのみ、ハンドラを定義する。
- 継承したメソッドにメッセージ処理の大半を任せる一方、処理の一部を変更することができる。
このメッセージ ディスパッチ機構の最大の利点は、いつでもどのようなコンポーネントにでもどのようなメッセージでも安全に送信できることです。問題となるメッセージのハンドラがコンポーネントに定義されていない場合、そのメッセージはデフォルトの方法で処理されます(通常はメッセージが無視されます)。
メッセージ フローの追跡
VCL では、アプリケーションに含まれるコンポーネントの種類ごとに MainWndProc という名前のメソッドをウィンドウ プロシージャとして登録します。MainWndProc には例外処理ブロックが含まれており、そこでは、Windows からのメッセージ構造体を WndProc という仮想メソッドに渡すほか、アプリケーション クラスの HandleException メソッドを呼び出すことであらゆる例外を処理します。
MainWndProc は、特定のメッセージに対する特別な処理を含まない非仮想メソッドです。各コンポーネント型ではそれぞれのニーズに合わせて WndProc メソッドをオーバーライドできるので、カスタマイズはこのメソッドで行われます。
WndProc メソッドでは、不要なメッセージを "トラップ" できるように、処理に影響を及ぼすような特別な状況になっていないかどうかを調べます。たとえば、コンポーネントは、ドラッグされている間、キーボード イベントを無視します。そのため、TWinControl の WndProc メソッドでは、コンポーネントがドラッグされていない場合にのみ、キーボード イベントを転送します。最終的に、WndProc では、TObject から継承した非仮想メソッドである Dispatch を呼び出します。どのメソッドを呼び出してメッセージを処理するかは、このメソッドで決定されます。
Dispatch では、メッセージ構造体の Msg フィールドを使用して、特定のメッセージをディスパッチする方法を決定します。そのメッセージのハンドラがコンポーネントに定義されている場合、Dispatch はそのメソッドを呼び出します。そのメッセージのハンドラがコンポーネントに定義されていない場合には、Dispatch は DefaultHandler を呼び出します。