2009-08-19 8 views
24

Ich erstelle ein kleines Spiel, das Spiel wird auf einem Panel auf einem Windows-Formular gedruckt. Jetzt möchte ich das Keydown-Ereignis erfassen, um zu sehen, ob es die Pfeiltasten gedrückt hat, das Problem ist jedoch, dass ich nicht scheinen kann, um es zu erfassen.C# versucht, das KeyDown-Ereignis auf einem Formular zu erfassen

Lassen Sie mich erklären, auf dem Formular habe ich 4 Tasten und verschiedene andere Bedienelemente und wenn der Benutzer zum Beispiel eine der Tasten drücken (um ein Spielereignis auszulösen) dann hat die Taste den Fokus und ich kann die Bewegungen nicht erfassen mit den Pfeiltasten.

Ich habe versucht, so etwas wie

private void KeyDown(KeyEventArgs e) 
    { 
     if (e.KeyCode == Keys.Left) 
     { 
      game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.E); 
      game.DrawObjects(panel1.CreateGraphics()); 
     } 
     else if (e.KeyCode == Keys.Right) 
     { 
      game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.W); 
      game.DrawObjects(panel1.CreateGraphics()); 
     } 
     else if (e.KeyCode == Keys.Up) 
     { 
      game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.N); 
      game.DrawObjects(panel1.CreateGraphics()); 
     } 
     else if (e.KeyCode == Keys.Down) 
     { 
      game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.S); 
      game.DrawObjects(panel1.CreateGraphics()); 
     } 
    } 

und dann, wenn die Form-Taste gedrückt Ereignisses gedrückt wurde, ich verwendet, um dieses

private void MainForm_KeyDown(object sender, KeyEventArgs e) 
    { 
     KeyDown(e); 
    } 

ich auch für die Tasten und die verschiedenen anderen Steuerelemente auf der addierte keydown Windows Form, aber ich bekomme keine Antwort zurück. Ich habe einen Breakpoint innerhalb der Funktion eingerichtet, um zu sehen, ob er aufgerufen wird, aber dieser Breakpoint niemals auslöst?

Irgendwelche Ideen?

Am optimalsten war es, ein generelles KeyDown-Ereignis auszulösen (unabhängig davon, welches Steuerelement gerade den Fokus hat) und dann die KeyDown-Methode aufzurufen.

Antwort

17

Aufschalten IsInputKey Verhalten


Sie müssen das IsInputKey Verhalten überschreiben, um zu informieren, dass Sie das richtige Ar wollen Zeilenschlüssel, der als InputKey und nicht als spezieller Verhaltensschlüssel behandelt wird. Dafür müssen Sie die Methode für jede Ihrer Steuerelemente überschreiben. Ich würde Ihnen raten, Ihre gewonnen Buttons zu erstellen, lassen Sie uns sagen MyButton

Die Klasse unten erstellt eine benutzerdefinierte Schaltfläche, die das IsInputKey Methode, so dass die rechte Pfeiltaste überschreibt nicht als Spezialschlüssel behandelt wird. Von dort können Sie es leicht für die anderen Pfeiltasten oder etwas anderes machen.

public partial class MyButton : Button 
    { 
     protected override bool IsInputKey(Keys keyData) 
     { 
      if (keyData == Keys.Right) 
      { 
       return true; 
      } 
      else 
      { 
       return base.IsInputKey(keyData); 
      } 
     } 
    } 

Danach können Sie Ihr keyDown Event Ereignis in jeder anderen Taste oder in der Form selbst behandeln:

In der Buttons' KeyDown Methode versuchen, diese Eigenschaften festlegen:

private void myButton1_KeyDown(object sender, KeyEventArgs e) 
{ 
    e.Handled = true; 
    //DoSomething(); 
} 

- ODER -

behandeln Sie das allgemeine Verhalten in der Form: (nicht setzen e.Handled = wahr; in den Tasten)

private void Form1_KeyDown(object sender, KeyEventArgs e) 
{ 
    //DoSomething(); 
} 
+1

Es ist semi-arbeiten, jetzt bekomme ich das Keydown-Ereignis, aber wenn ich die Tasten drücke, werden sie immer noch fokussiert und dann funktioniert es nur, wenn ich die obere Pfeiltaste drücke, bis sie alle durchläuft und sie den Fokus verlieren. – Patrick

+0

Wie fangen Sie die KeyDown-Ereignisse "Keys.Left" und "Keys.Right"? –

+0

Ich bearbeitete meine Antwort zu verweisen IsInputKey-Methode –

29

Haben Sie die KeyPreview Eigenschaft des Formulars auf true festgelegt? Dadurch erhält das Formular einen ersten Blick auf wichtige Ereignisse.

Update: bekommen dies richtig funktionieren, wenn ein Button Fokus hat scheint ein bisschen schwierig. Das Button-Steuerelement fängt die Pfeiltaste ab und verschiebt den Fokus zum nächsten oder vorherigen Steuerelement in der Aktivierreihenfolge so, dass die Ereignisse KeyDown, KeyUp und KeyPress nicht ausgelöst werden. Allerdings ist die PreviewKeyDown Ereignis ausgelöst, so dass verwendet werden kann:

private void Form_KeyDown(object sender, KeyEventArgs e) 
{ 
    e.Handled = ProcessKeyDown(e.KeyCode); 
} 

// event handler for the PreViewKeyDown event for the buttons 
private void ArrowButton_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) 
{ 
    ProcessKeyDown(e.KeyCode); 

} 

private bool ProcessKeyDown(Keys keyCode) 
{ 
    switch (keyCode) 
    { 
     case Keys.Up: 
      { 
       // act on up arrow 
       return true; 
      } 
     case Keys.Down: 
      { 
       // act on down arrow 
       return true; 
      } 
     case Keys.Left: 
      { 
       // act on left arrow 
       return true; 
      } 
     case Keys.Right: 
      { 
       // act on right arrow 
       return true; 
      } 
    } 
    return false; 
} 

Doch der Fokus bewegt sich in einer ziemlich hässlichen Art und Weise ...

+0

Es ist halb-Arbeits, bekomme ich jetzt das KeyDown-Ereignis, aber wenn ich die Tasten drücken, sie noch fokussierter worden und dann stoppt es, wenn ich die Taste arbeiten:
Ihr kleines Spiel Beispiel so könnte neu geschrieben oben Pfeiltaste, bis es durch sie alle Schleifen und sie Fokus verlieren. – Patrick

+0

@Patrick: Ja, die Pfeiltasten und Button-Steuerelement scheinen eine sehr enge Beziehung zu haben. Ich habe meine Antwort aktualisiert, indem ich sie um einen Schritt vorwärts gebracht habe. –

7
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     KeyPreview = true; 
     KeyDown += new KeyEventHandler(Form1_KeyDown); 
    } 

    void Form1_KeyDown(object sender, KeyEventArgs e) 
    { 
     System.Diagnostics.Debug.Write(e.KeyCode); 
    } 
} 
+1

Sie wissen nicht, dass Ihre Antwort eine Menge Zeit von mir spart. Danke vielmals. –

+0

Es sollte "KeyPreview = True;" Das macht die KeyDown ausgelöst –

16

Ich glaube, der einfachste Weg, um dieses Problem zu lösen, ist die ProcessCmdKey() -Methode des Formulars durch Überschreiben. Auf diese Weise wird Ihre Schlüsselverarbeitungslogik ausgeführt, unabhängig davon, welches Steuerelement zum Zeitpunkt des Tastendrucks den Fokus hat. Außerdem können Sie sogar auswählen, ob das fokussierte Steuerelement den Schlüssel erhält, nachdem Sie es verarbeitet haben (false zurückgeben) oder nicht (true zurückgeben).

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
{ 
    if (keyData == Keys.Left) 
    { 
     MoveLeft(); DrawGame(); DoWhatever(); 
     return true; //for the active control to see the keypress, return false 
    } 
    else if (keyData == Keys.Right) 
    { 
     MoveRight(); DrawGame(); DoWhatever(); 
     return true; //for the active control to see the keypress, return false 
    } 
    else if (keyData == Keys.Up) 
    { 
     MoveUp(); DrawGame(); DoWhatever(); 
     return true; //for the active control to see the keypress, return false 
    } 
    else if (keyData == Keys.Down) 
    { 
     MoveDown(); DrawGame(); DoWhatever(); 
     return true; //for the active control to see the keypress, return false 
    } 
    else 
     return base.ProcessCmdKey(ref msg, keyData); 
} 
+0

Es ist großartig, aber Leerzeichen Schlüssel nicht verarbeitet – Singlet

+2

Große Lösung. Erfasst alle Tastendrücke. Sogar Platz. – Kibbee

+0

Dies ist der einfachste Weg, um diese Probleme zu lösen, und funktionierte auch perfekt für mich. –

Verwandte Themen