KeyDownイベントに応答しないフォーム


82

私はしばらくの間Windowsフォームプロジェクトに取り組んできましたが、キーボードショートカットを試すことにしました。少し読んだ後、イベントハンドラーを作成して、フォームのKeyDownイベントにバインドする必要があると考えました。

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.Alt && e.KeyCode == Keys.O)
    {
        MessageBox.Show("Ctrl+Alt+O: magic!");
    }
}

Visual Studioデザイナの[プロパティ]パネルを開き、フォームのKeyDownイベントをダブルクリックして、Form1_KeyDownイベントハンドラーを生成するという古き良き方法を実行しました。しかし、私のアプリケーションをテストするには、フォームはにまったく応答しないCtrl+ Alt+Oキーボードショートカット。ただし、Visual Studioデザイナーは、イベントハンドラーをフォームにバインドするコードを生成しました。

private void InitializeComponent()
{
    // ...

    this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);

    // ...
}

そこでConsole.WriteLine()、ハンドラーに呼び出しを追加して、呼び出されていることを確認しようとしましたが、それもうまくいきませんでした。

また、イベントバインディング呼び出し(すぐ上に表示)にブレークポイントを設定しようとしましたが、プログラムがそのブレークポイントに問題なく到達することがわかりました。ただし、メソッド定義自体に設定したブレークポイントには到達しません。

最初のいくつかの手順を正しく実行していることを確認するために、次の手順で繰り返してみました。

  • 同じソリューションの新しいフォーム。
    同じ問題:Ctrl+ Alt+Oキーボードショートカットを押してもフォームが応答せず、デバッガーがイベントハンドラーにステップインしません。 これをもう一度試してみましたが、機能します。

  • まったく新しいWinFormsソリューション。
    完全に機能します。メッセージダイアログが表示されます(Console.WriteLine()呼び出しも機能します)。

だから私はここでかなり迷っています。この1つのプロジェクトのすべてのフォームがKeyDownイベントを受信するのを妨げているのは何ですか?

回答:


174

フォームのKeyPreviewプロパティがtrueに設定されていますか?

Form.KeyPreviewプロパティ

イベントがフォーカスのあるコントロールに渡される前に、フォームがキーイベントを受信するかどうかを示す値を取得または設定します。

http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx


19
これはハックであり、VB6プログラマーを満足させるために利用できるようになっています。実行順序の問題があります。代わりにProcessCmdKey()をオーバーライドしてください。
ハンスパッサント2010

@HansPassant、実行順序の問題を説明するものが見つかりません。KeyDown + KeyPreviewはすべてのキーを表示しません。これは十分な問題ですが、実行順序の問題は何ですか?
kdbanman 2015

1
ショートカットキーストロークを検出するためのオーバーライドはたくさんあります。順番に実行すると、KeyPreview + KeyDownは最後に停止します。
ハンスパッサント2015

54

StackOverflowとMSDNでこの問題のためのアドバイスの中で最も一般的な作品12(ここでは受け入れ答えを含む)は、迅速かつ簡単です。

KeyDownプロパティがに設定されてFormいる限り、イベントはでトリガーKeyPreviewされますtrue

これはほとんどの目的には十分ですが、次の2つの理由でリスクがあります。

  1. KeyDownハンドラーはすべてのキーを見るわけではありません。具体的には、「ナビゲーションに使用されるキーストロークの種類は表示されません。ダイアログのカーソルキーやTab、Escape、Enterなどです。」

  2. 重要なイベントをインターセプトする方法はいくつかあり、それらはすべて順番に発生します。 最後にKeyDown処理されます。したがって、これはプレビューの多くではなく、途中の数か所でイベントが沈黙する可能性があります。KeyPreview

(これらのポイントについては、@ HansPassantへのクレジット。)

代わりに、:をオーバーライドProcessCmdKeyしますForm

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
    if (keyData == Keys.Up)
    {
        // Handle key at form level.
        // Do not send event to focused control by returning true.
        return true;
    }
  return base.ProcessCmdKey(ref msg, keyData);
}

そうすれば、すべてのキーがメソッドに表示され、メソッドが最初にイベントを確認します。

フォーカスされたコントロールがKeyDownイベントを表示するかどうかは、引き続き制御できることに注意してください。イベントハンドラーのように設定するのではなくtrue、戻って後続のKeyDownイベントをブロックするだけです。 詳細については、こちらの記事をご覧ください。KeyPressEventArgs.HandledtrueKeyDown


1
これは正解です。特に、KeyPreviewがtrueに設定されているとPreviewKeyDownがまったく起動しない場合はそうです。
ティム

23

KeyPreviewフォームのプロパティをtrueに設定してみてください。これは、キーの押下を登録するために私のために働きました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.