Aufwärts-, Abwärts-, Links- und Rechtspfeiltasten lösen kein KeyDown-Ereignis aus

74

Ich erstelle eine Anwendung, in der alle Schlüsseleingaben von den Fenstern selbst verarbeitet werden müssen.

Ich habe Tabstop für jedes Steuerelement auf false gesetzt, das den Fokus außer einem Bedienfeld erfassen kann (aber ich weiß nicht, ob es Auswirkungen hat).

Ich habe KeyPreview auf true gesetzt und behandle das KeyDown-Ereignis in diesem Formular.

Mein Problem ist, dass die Pfeiltaste manchmal nicht mehr reagiert:

  • Das Keydown-Ereignis wird nicht ausgelöst, wenn ich nur eine Pfeiltaste gedrückt habe.

  • Das Keydown-Ereignis wird ausgelöst, wenn ich mit dem Steuermodifikator eine Pfeiltaste drücke.

Haben Sie eine Idee, warum meine Pfeiltaste plötzlich aufhört, ein Ereignis auszulösen?

Martin Delille
quelle
Können Sie den Code veröffentlichen, den Sie in Ihrem KeyDown-Ereignishandler haben?
ChrisF
Vielleicht hilft dir das? stackoverflow.com/questions/902767/…
Maxim Zaslavsky
2
@Max, ich bin mir ziemlich sicher, dass die Schlüsselereignisse für Pfeiltasten unterdrückt werden, wenn ein Fenster untergeordnete Steuerelemente enthält. Die Frage, mit der Sie verlinkt haben, hat sich mit einem Formular ohne Steuerelemente befasst. Daniel Waltrips Problem war nicht wirklich dasselbe.
Snarf
@ Snarfblam Ich bin mir nicht sicher, ob ich das verstehe - warum sollte das hier ein Problem sein?
Maxim Zaslavsky

Antworten:

60
    protected override bool IsInputKey(Keys keyData)
    {
        switch (keyData)
        {
            case Keys.Right:
            case Keys.Left:
            case Keys.Up:
            case Keys.Down:
                return true;
            case Keys.Shift | Keys.Right:
            case Keys.Shift | Keys.Left:
            case Keys.Shift | Keys.Up:
            case Keys.Shift | Keys.Down:
                return true;
        }
        return base.IsInputKey(keyData);
    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        switch (e.KeyCode)
        {
            case Keys.Left:
            case Keys.Right:
            case Keys.Up:
            case Keys.Down:
                if (e.Shift)
                {

                }
                else
                {
                }
                break;                
        }
    }
Alpha
quelle
2
Beachten Sie, dass alle Tabulatoren für Steuerelemente falsch sein sollten (ich hatte ein solches Problem: D)
Iman
4
Dies ist eigentlich ein Hack. Überprüfen Sie die Antwort von Rodolfo Neuber auf die richtige Antwort.
Ghigo
76

Ich hatte genau das gleiche Problem. Ich dachte über die Antwort nach, die @Snarfblam gegeben hatte. Wenn Sie jedoch die Dokumentation zu MSDN lesen, soll die ProcessCMDKey-Methode wichtige Ereignisse für Menüelemente in einer Anwendung überschreiben.

Ich bin kürzlich auf diesen Artikel von Microsoft gestoßen, der ziemlich vielversprechend aussieht: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx . Laut Microsoft ist es am besten, e.IsInputKey=true;das PreviewKeyDownEreignis nach dem Erkennen der Pfeiltasten einzustellen . Andernfalls wird das KeyDownEreignis ausgelöst.

Dies hat für mich ganz gut funktioniert und war weniger hackig als das Überschreiben des ProcessCMDKey.

Rodolfo Neuber
quelle
1
Dies sollte die gewählte Antwort sein, es ist viel sauberer und es funktioniert wunderbar.
AStackOverflowUser
Ja, es funktioniert! Die Antwort ist ziemlich klar, aber ich möchte angeben, dass das IsInputKeyin der eKlasse ist : e.IsInputKey=true.
T30
2
(Was passiert, wenn Sie es für alle Tasten tun, ohne die Pfeile zu erkennen?)
T30
@ T30 Sie verlieren die Alt für die Menüs
Google Dev
18

Ich benutze PreviewKeyDown

    private void _calendar_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e){
        switch (e.KeyCode){
            case Keys.Down:
            case Keys.Right:
                //action
                break;
            case Keys.Up:
            case Keys.Left:
                //action
                break;
        }
    }
Marcel
quelle
2
Arbeitete wunderbar für mich, keine Notwendigkeit zu erben / überschreiben
Paul Kapustin
1
das hat sehr gut funktioniert, danke. verhält sich genau so, wie ich es von einem Schlüsselereignis erwarten würde.
Dave Cousineau
Dies sollte die akzeptierte Antwort sein !!! Verwenden Sie einfach das PreviewKeyDown-Ereignis. Funktioniert ohne Hacking. Könnte nicht sauberer oder einfacher sein.
Joe Gayetty
17

Siehe Rodolfo Neuber Antwort für die beste Antwort


(Meine ursprüngliche Antwort):

Leiten Sie von einer Steuerungsklasse ab und Sie können die ProcessCmdKey-Methode überschreiben. Microsoft hat diese Schlüssel in KeyDown-Ereignissen weggelassen, da sie sich auf mehrere Steuerelemente auswirken und den Fokus verschieben. Dies macht es jedoch sehr schwierig, eine App auf andere Weise auf diese Schlüssel reagieren zu lassen.

Snarf
quelle
Es scheint, dass ProcessCmdKey die einzige Möglichkeit ist, die Tastatur genau zu handhaben. Vielen Dank!
Martin Delille
4
Diese Antwort ist absolut falsch. Wenn ich OnKeyDown nicht bereits von einem Basissteuerelement überschrieben hätte, das bereits die Pfeiltasten handhabte (um das Verhalten zu ändern), hätte ich dies nicht gewusst und es auf die harte Tour implementiert. Siehe Alphas Antwort unten.
Joshua
1
Selbst Alphas Antwort funktioniert in meiner Situation nicht, aber Snarfblams. Danke!
Zionpi
2

Leider ist es aufgrund von Einschränkungen bei KeyDown-Ereignissen ziemlich schwierig, dies mit den Pfeiltasten zu erreichen. Es gibt jedoch einige Möglichkeiten, dies zu umgehen:

  • Wie in @Snarfblam angegeben, können Sie die ProcessCmdKey-Methode überschreiben , mit der die Pfeiltasten nicht mehr analysiert werden können.
  • Wie in der akzeptierten Antwort auf diese Frage angegeben , verfügt XNA über eine integrierte Methode namens Keyboard.GetState () , mit der Sie Pfeiltasteneingaben verwenden können. Allerdings hat WinForms nicht, aber es kann durch eine P / Invoke erfolgen , oder durch eine Klasse verwenden , die mit ihm hilft .

Ich empfehle, diese Klasse zu verwenden. Das geht ganz einfach:

var left = KeyboardInfo.GetKeyState(Keys.Left);
var right = KeyboardInfo.GetKeyState(Keys.Right);
var up = KeyboardInfo.GetKeyState(Keys.Up);
var down = KeyboardInfo.GetKeyState(Keys.Down);

if (left.IsPressed)
{
//do something...
}

//etc...

Wenn Sie dies in Kombination mit dem KeyDown-Ereignis verwenden, können Sie Ihr Ziel meiner Meinung nach zuverlässig erreichen.

Maxim Zaslavsky
quelle
2

Ich hatte ein ähnliches Problem beim Aufrufen des WPF-Fensters aus WinForms.

var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
    ElementHost.EnableModelessKeyboardInterop(wpfwindow);
    wpfwindow.Show();

Das Anzeigen des Fensters als Dialogfeld funktionierte jedoch

var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
    ElementHost.EnableModelessKeyboardInterop(wpfwindow);
    wpfwindow.ShowDialog();

Hoffe das hilft.

Janez Krnc
quelle
0

Um Tastenanschläge in einem Forms-Steuerelement zu erfassen, müssen Sie eine neue Klasse ableiten, die auf der Klasse des gewünschten Steuerelements basiert, und Sie überschreiben den ProcessCmdKey ().

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    //handle your keys here
}

Beispiel:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    //capture up arrow key
    if (keyData == Keys.Up )
    {
        MessageBox.Show("You pressed Up arrow key");
        return true;
    }

    return base.ProcessCmdKey(ref msg, keyData);
}

Vollständige Quelle ... Pfeiltasten in C #

Vayne

vaynenick
quelle
0

Ich denke, der beste Weg, dies zu tun, besteht darin, damit umzugehen, wie der MSDN auf http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx sagte

Aber geh damit um, wie du es wirklich brauchst. Mein Weg (im folgenden Beispiel) ist es, jeden KeyDown zu fangen ;-)

    /// <summary>
    /// onPreviewKeyDown
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
    {
        e.IsInputKey = true;
    }

    /// <summary>
    /// onKeyDown
    /// </summary>
    /// <param name="e"></param>
    protected override void OnKeyDown(KeyEventArgs e)
    {
        Input.SetFlag(e.KeyCode);
        e.Handled = true;
    }

    /// <summary>
    /// onKeyUp
    /// </summary>
    /// <param name="e"></param>
    protected override void OnKeyUp(KeyEventArgs e)
    {
        Input.RemoveFlag(e.KeyCode);
        e.Handled = true;
    }
Marcus.D
quelle
0
protected override bool IsInputKey(Keys keyData)
{
    if (((keyData & Keys.Up) == Keys.Up)
        || ((keyData & Keys.Down) == Keys.Down)
        || ((keyData & Keys.Left) == Keys.Left)
        || ((keyData & Keys.Right) == Keys.Right))
        return true;
    else
        return base.IsInputKey(keyData);
}
google dev
quelle