6

基本的に、私はカスタムコントロールを備えたフォームを持っています(そして他には何もありません)。カスタムコントロールは完全に空であり、フォームのKeyPreviewはtrueに設定されています。

この設定では、矢印キーまたはタブのKeyDownイベントを受信して​​いません。キーボードにある他のすべてのキーは機能します。KeyDownイベントハンドラーをそのようなイベントを持つすべてのものに接続しているので、何も見逃していないと確信しています。

また、(完全に空の)カスタムコントロールを削除すると、矢印キーイベントが発生することにも注意してください。

一体何がここで起こっているのですか?

編集:

これをフォームとコントロールの両方に追加しましたが、まだ矢印キーを取得していません。

protected override void WndProc(ref Message m) {
    switch (m.Msg) {
        case 0x100: //WM_KEYDOWN
            //this is the control's version. In the form, it's this.Text
            ParentForm.Text = ((Keys)m.WParam).ToString();
            break;
    }
    base.WndProc(ref m);
}

また、Spy ++で確認したところ、フォーム自体にWM_KEYDOWNメッセージが表示されておらず、すべてコントロールに送信されていることがわかりました。ただし、それでも、コントロールは矢印キーWM_KEYDOWNメッセージを取得しています。はぁ。

編集2:このバージョンでZIPファイルも更新しました。あなたが助けたいなら、それを見てください...

編集3:

私はこれを理解しました、ある種。フォームは、おそらくその子供たちの間で焦点を維持しようとして、矢印キーを食べています。これは、フォームが空の場合にイベントを取得するという事実によって証明されています。

とにかく、このコードをフォームに追加すると、イベントの取得が再開されます。

public override bool PreProcessMessage(ref Message msg) {
    switch (msg.Msg) {
        case 0x100: //WM_KEYDOWN
            return false;
    }
    return base.PreProcessMessage(ref msg);
}

これをオーバーライドすると、フォームはダーティな作業を行う機会がないため、期待どおりにKeyDownイベントを取得します。これの副作用は、キーボードを使用してフォームをナビゲートできなくなることだと思います(この場合、ゲームであるため、大したことではありません。この演習の全体的な目的は、キーボードナビゲーションを実装することです!)

方法があれば、これを「適切に」無効にする方法についてはまだ疑問が残ります...

4

2 に答える 2

10

私はいくつかの広範なテストを行い、すべてを理解しました。解決策を詳しく説明したブログ投稿を書きました。

つまり、次の形式でProcessDialogKeyメソッドをオーバーライドする必要があります。

protected override bool ProcessDialogKey(Keys keyData) {
    return false;
}

これにより、矢印キー(およびタブ)が通常のKeyDownイベントとして配信されます。でも!これにより、通常のダイアログキー機能(Tabを使用してコントロールをナビゲートするなど)も失敗します。それを保持したいが、それでもKeyDownイベントを取得したい場合は、代わりにこれを使用してください。

protected override bool ProcessDialogKey(Keys keyData) {
    OnKeyDown(new KeyEventArgs(keyData));
    return base.ProcessDialogKey(keyData);
}

これにより、通常のダイアログナビゲーションを実行しながら、KeyDownメッセージが配信されます。

于 2010-07-21T19:52:23.320 に答える
0

フォーカスが問題であり、ユーザーコントロールにフォーカスを取得して維持させることができない場合、簡単な回避策は、懸念している主要なイベントのユーザーコントロールにイベントをエコーすることです。フォームのkeydownまたはkeypressイベントをサブスクライブしてから、そのイベントでユーザーコントロールにイベントを発生させます。

したがって、基本的に、Form1_KeyPressは、Form1_KeyPressからの送信者とイベントの引数を使用してUserControl1_KeyPressを呼び出します。

protected void Form1_KeyPress(object sender, KeyEventArgs e)
{
    UserControl1_KeyPress(sender, e);
}

そうしないと、必要な機能を取得するために、長いルートをたどり、WndProcイベントをオーバーライドする必要がある場合があります。

于 2010-07-21T15:40:59.507 に答える