2010-12-29 3 views
1

Ich habe ein Formular, das sich selbst schließt, wenn die ESC-Taste gedrückt wird, dank , ProcessKeyEventArgs, ProcessCmdKey oder was auch immer. Aber ich habe ein Steuerelement auf diesem Formular, das sehr relevante Dinge tut, wenn ESC gedrückt wird (es versteckt sich) und das Formular sollte nicht geschlossen werden, wenn das passiert.Wie schließe ich ein Formular, wenn die ESC-Taste gedrückt wurde, aber nur wenn kein Steuerelement es behandelt?

Die Steuerung verwendet das KeyDown Ereignis und stellt die SuppressKeyPress Flags auf wahr, aber das geschieht nach die zuvor erwähnte Schlüssel Vorschau bilden, wodurch keine Wirkung.

Gibt es eine Art KeyPostview?

Wie schließe ich das Formular nicht, wenn ein Control eine relevante Verwendung eines Schlüsseltreffers hat?

Bearbeiten: Die Steuerbehandlung ESC ist eine Textbox in einem Hand-Maid-ListView eingebettet. Das Textfeld wird angezeigt, wenn der Benutzer auf eine Zelle klickt und die Edition aktiviert. Um den neuen Text zu validieren, wäre ENTER schön (das funktioniert bereits, da der Fokus auf etwas anderes gelegt wird). Um die Ausgabe abzubrechen, scheint ESC am natürlichsten zu sein.

+2

Ich bin etwas misstrauisch gegenüber dem Design an erster Stelle. Wird sich der durchschnittliche Benutzer mit der Esc-Taste wohlfühlen und zwei sehr unterschiedliche Dinge tun? Werden sie das Konzept des "Fokus" und der "aktiven Kontrolle" gut genug verstehen, um zu erwarten, was passieren wird? Stellen Sie zumindest sicher, dass Sie dies aus der Perspektive des Benutzers und nicht nur des Entwicklers betrachten. –

+0

Denken Sie an Excel. Wenn Sie eine Zelle doppelklicken, können Sie sie bearbeiten. ESC bricht die Ausgabe ab. – Gabriel

+1

aber Excel schließt nicht, wenn Sie ESC git, wie Sie Ihre App beschrieben haben –

Antwort

1

Sie konkurrieren Big Time über die Escape-Taste. Zusammen mit der Eingabetaste ist das ein sehr wichtiger Schlüssel in der Windows-Standardbenutzeroberfläche. Legen Sie einfach eine Schaltfläche auf dem Formular ab und legen Sie die CancelButton-Eigenschaft des Formulars auf eine andere Schaltfläche fest, die den Tastendruck auf diese Schaltfläche auslöst.

Um damit zu konkurrieren, müssen Sie ein Steuerelement erstellen, das Winforms sagt, dass Sie wirklich denken, dass der Escape-Schlüssel mehr wichtig ist. Dies erfordert das Überschreiben der IsInputKey-Eigenschaft. Gefällt mir:

using System; 
using System.Windows.Forms; 

class MyTexBox : TextBox { 
    protected override bool IsInputKey(Keys keyData) { 
     if (keyData == Keys.Escape) return true; 
     return base.IsInputKey(keyData); 
    } 
    protected override void OnKeyDown(KeyEventArgs e) { 
     if (e.KeyData == Keys.Escape) { 
      this.Text = ""; // for example 
      e.SuppressKeyPress = true; 
      return; 
     } 
     base.OnKeyDown(e); 
    } 
} 
+0

Das ist sehr – Gabriel

+0

Works Wunder. Es gibt zwei Probleme obwohl. 1. Ich muss einen Knopf auf dem Formular haben, um die CancelButton Sache zu behandeln. Das ist keine große Sache für mich, weil ich bereits einen auf virtual al meine Formen habe, aber das mag sei ein hassl e für andere Programmierer. 2. Diese Schaltfläche muss sowohl aktiviert als auch sichtbar sein. Um Verwechslungen während der Design-Zeit zu vermeiden, sollte es zur Design-Zeit sichtbar sein und somit zur Laufzeit sichtbar sein. Es kann ein weiterer Ärger sein, es durch Ausblenden aus dem Formular herauszuziehen. Das ist immer noch die beste Lösung für mich, denn es schließt keine Überprüfung ein, um das Formular zu schließen. \ o/ – Gabriel

+1

Überschreiben Sie ProcessCmdKey() des Formulars. –

0

Können Sie überprüfen, welches Steuerelement zuerst den Fokus hat? Wenn es nur ein Steuerelement in Ihrem Formular gibt, das etwas mit dem Escape-Schlüssel relevant vornimmt, überprüfen Sie, ob das Steuerelement das Fokus hat, bevor Sie das Formular schließen.

+0

Ich möchte nicht, dass das Formular nach diesem bestimmten Steuerelement (die in der Tat ein UserControl ist) zu überprüfen. Ich würde gerne in der Lage sein, diese Kontrolle auf das Formular fallen zu lassen und nichts zu tun, erwarte, dass es richtig funktioniert. Ich bin jedoch bereit, die KeyPreview-Sache zu ändern, die wie eine Sackgasse aussieht. – Gabriel

+0

Okay. Scheint, als ob 2 Zeilen es für dich tun würden, kann nicht viel einfacher als das werden. Ich muss Cody trotzdem zustimmen. – Moose

1

OK - das funktioniert:

class CustomTB : TextBox 
{ 
    public CustomTB() 
     : base() 
    { 
     CustomTB.SuppressEscape = false; 
    } 

    public static bool SuppressEscape { get; set; } 

    protected override void OnKeyDown(KeyEventArgs e) 
    { 
     CustomTB.SuppressEscape = (e.KeyCode == Keys.Escape); 
     base.OnKeyUp(e); 
    } 
} 

In Ihrem Formular:

public Form1() 
    { 
     InitializeComponent(); 
     this.KeyPreview = true; 
    } 

    private void Form1_KeyUp(object sender, KeyEventArgs e) 
    { 
     if (e.KeyCode == Keys.Escape && !CustomTB.SuppressEscape) 
     { 
      this.Close(); 
     } 
     CustomTB.SuppressEscape = false; 
    } 
+0

Ja, genau das habe ich mir gedacht. – Moose

+0

Noch einmal möchte ich in Form_KeyUp nicht nach diesem Steuerelement suchen müssen, das ist zu leicht zu vergessen. – Gabriel

+0

mein neuer Code funktioniert auch. Wenn Sie sich Sorgen um das Vergessen machen, dann machen Sie eine benutzerdefinierte Kontrolle. – zsalzbank

0

Das Grundproblem ist, dass das Dispose-Methode des Formulars aufgerufen wird, wenn Close aufgerufen wird, so wird das Formular in der Nähe gehen und es gibt nicht viel, was du dagegen tun kannst.

Ich würde dies umgehen, indem das UserControl eine Marker-Schnittstelle implementiert, sagen ISpressEsc. Der KeyUp-Handler des Formulars kann dann das aktuell fokussierte Steuerelement finden und das Schließen aufheben, wenn das fokussierte Steuerelement ISuppressEsc implementiert. Beachten Sie, dass Sie zusätzliche Arbeit an find the focused control tun müssen, wenn es ein geschachteltes Steuerelement sein kann.

public interface ISuppressEsc 
{ 
    // marker interface, no declarations 
} 

public partial class UserControl1 : UserControl, ISuppressEsc 
{ 
    public UserControl1() 
    { 
     InitializeComponent(); 
    } 

    private void textBox1_KeyUp(object sender, KeyEventArgs e) 
    { 
     if (e.KeyCode == Keys.Escape) 
     { 
      textBox1.Text = DateTime.Now.ToLongTimeString(); 
     } 
    } 
} 

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     KeyPreview = true; 
    } 

    private void Form1_KeyUp(object sender, KeyEventArgs e) 
    { 
     var activeCtl = ActiveControl; 
     if (!(activeCtl is ISuppressEsc) && e.KeyCode == Keys.Escape) 
     { 
      Close(); 
     } 
    } 
} 
Verwandte Themen