非常にマルチスレッド化された Delphi 6 アプリケーションがあります。TWinControl から派生したコンポーネントを作成しました。私が最初にそれを構築したとき、私は非表示のウィンドウを使用しました.AllocateHwnd()で割り当てられたメッセージを処理するのはWndProcです。最近、コード内の WndProc のクリーンアップを開始し、補助的な WndProc() を削除することにしました。コンポーネントを変更して、代わりに基本クラスの WndProc() メソッドをオーバーライドし、そこからカスタム Windows メッセージ処理を行いました。その WndProc() では、継承されたハンドラーを最初に呼び出してから、カスタム メッセージ (WM_USER オフセット) を処理し、カスタム メッセージの 1 つが見つかって処理された場合は、メッセージの Result フィールドを 1 に設定しました。
重要な注意事項が 1 つあります。現在のスレッド ID が VCL メイン スレッドでない場合に例外をスローするコード行を WndProc() オーバーライドの先頭に追加しました。WndProc() がメイン VCL スレッドのコンテキストでのみ実行されるようにしたかったのです。
これを行ってプログラムを実行した後、本当に奇妙に思えることに遭遇しました。プログラムを通常どおり実行し、さまざまなタスクをエラーなしで実行しました。次に、TWinControl の子孫と同じページにある TMemo コントロールに移動したとき。その TMemo コントロール内をクリックすると、WndProc() オーバーライドのメイン スレッド チェックがトリガーされます。ブレークポイントが設定されていて、コール スタックに移動したとき、WndProc() オーバーライドの上には何もありませんでした。
私が知る限り、再確認したところ、WndProc() オーバーライドを明示的に呼び出していません。それは私が決してすることではありません。しかし、私の TWinControl コンポーネントが他のすべてのコンポーネントと同様にメインの VCL スレッドで作成されることを考えると、バックグラウンド スレッドのコンテキストで WndProc() オーバーライドがどのように実行されるかはわかりません。マウスクリックが発生します。すべての子ウィンドウが最上位ウィンドウ WndProc() からぶら下がっているため、WndProc() が TMemo コントロールにどのように関連付けられているかを理解しています。少なくともそれは私の理解です。しかし、すべてのコンポーネント ウィンドウがメイン VCL スレッドで作成されているため、すべてのメッセージ キューもそのコンテキストで実行されているはずですよね?
では、WndProc() をバックグラウンド スレッドのコンテキストで実行するために、どのような状況を作り出すことができるでしょうか?