背景:
コントロール内のコントロール内にネストされたコントロールを持つかなり複雑な C# gui アプリケーションがいくつかあります。これには、ホットキーをグローバルに処理する必要があります (つまり、フォーカスがどこにあるかに関係なく、キーの押下をキャッチできるトップレベルのハンドラーが必要です)。は)。
ホットキーのいくつかは、文字やスペースバーのような一般的に押されるキーであるため、私の要件はおそらくここでは少し普通ではありません. スペースバーのようなキーが押されると、明らかにそれを処理するテキストボックスのような特定のコントロールがあります。フォーカスされたコントロールがキーを処理する場合、グローバル ホットキー ハンドラーの呼び出しを避けたいと考えています。
私の現在の解決策は、PreFilterMessage を使用してホットキーをグローバルに処理することです。PreFilterMessage呼び出しの内部には、フォーカスされたコントロールがそのキーを処理することがわかっている場合、グローバル ホットキーをバイパスするコードがあります。(しかし、IsInputKeyは保護されているため、コントロールがキーを処理するかどうかをコントロールに尋ねることはできません。そのため、どのコントロール内でホットキーをバイパスする必要があるかについて、独自の厄介なロジックを持っているだけです)。
私は PreFilterMessage ソリューションにあまり満足していません。より洗練された方法であるべきだと思われます。概念的には、私が望む動作は非常に単純です。フォーカスされたコントロールが KeyDown を処理する場合、他にそれを処理する必要はありません。それ以外の場合、親コントロールはそれを処理しようとする必要があり、そのコントロールがキーを処理しない場合は、フォームの KeyDown ハンドラーに到達するまで、その親を試行する必要があります。
質問:
次の場合にのみイベントを受信するように、コントロールに KeyDown ハンドラーを設定する方法はありますか?
- コントロールまたはその子孫の 1 つがフォーカスされている。
- どの子孫コントロールにもフォーカスがないか、フォーカスされたコントロールが KeyDown イベントを処理しません。
私はこれについてできる限り多くの調査を行いました。私はPreFilterMessageとForm.KeyPreviewを認識していますが、私が知る限り、より具体的なコントロールによって処理されるはずのキーを無視する明確な方法はありません。前にイベントを取得するためです。フォーカスされたコントロールがそれを取得します。私が本当に望んでいるのは、ほとんど逆です。フォーカスされたコントロールがそれを処理するかどうかを決定するまで、フォームは KeyDown を取得しません。