2015-05-07 13 views
12

Ich habe ein KeyPressed Signal in GTK #/Mono-C# für zwei verschiedene Zwecke, die in dem Standard nicht vorhanden sind TreeView: a) zur nächsten Zelle gehen von TAB drücken, und b) der Bearbeitung beginnen durch Drücken irgendein Schlüssel.Wie man Tasten drücken für spezielle Zwecke in Gtk # TreeView?

Die TreeView ist einfach, es hat ein ListStor nur Zeilen und Spalten zeigen, das heißt, es tabellarische Daten enthält.

Der Code, den ich habe, ist unten.

[GLib.ConnectBefore] 
protected void OnTableKeyPressed(object o, Gtk.KeyPressEventArgs args) 
{ 
    int rowIndex; 
    int colIndex; 

    // Do not "eat" the key, by default 
    args.RetVal = false; 

    // Get the current position, needed in both cases. 
    this.GetCurrentCell(out rowIndex, out colIndex); 

    // Adapt the column 
    colIndex += NumFixedColumns; 

    if (args.Event.Key != Gdk.Key.ISO_Enter) { 
     if (args.Event.Key == Gdk.Key.Tab 
      || args.Event.Key == Gdk.Key.ISO_Left_Tab) 
     { 
      if(args.Event.State == Gdk.ModifierType.ShiftMask) { 
       // Back 
       colIndex -= 1; 
       if (colIndex < 1) { 
        colIndex = document.Columns; 
        --rowIndex; 
       } 

       rowIndex = Math.Max(0, rowIndex); 
      } else { 
       // Advance 
       colIndex += 1; 
       if (colIndex > document.Columns) { 
        colIndex = 1; 
        ++rowIndex; 
       } 

       rowIndex = Math.Min(rowIndex, document.Rows); 
      } 

      this.SetCurrentCell(rowIndex, colIndex); 
      args.RetVal = true;        // Eat the TAB 
     } else { 
      this.SetCurrentCell(rowIndex, colIndex, true); 
     } 
    } 

    return; 
} 

Ich habe zwei Fragen:

  1. Wie kann ich auf das TreeView Signal, dass eine Zelle die Bearbeitung beendet wurde? Das Problem ist, dass wenn Sie TAB drücken, wenn keine Zelle bearbeitet wird, alles gut funktioniert. Wenn der Benutzer jedoch eine Zelle bearbeitet, gehen die bisher eingegebenen Inhalte verloren. Also, wenn der Benutzer eine Zelle bearbeitet, möchte ich dem TreeView signalisieren, um die Ausgabe zu beenden, und das Weitermachen mit dem aktuellen Verhalten.

  2. Wie kann ich vermeiden, den ersten Schlüssel beim Bearbeiten einer Zelle zu verlieren? Angenommen du bist über einer Zelle. Sie drücken die Tasten 1, 2, 3 und 4. Mein Handler interferiert korrekt und setzt die aktuelle Zelle in den Editiermodus. Die Zelle erhält jedoch nur 2, 3 und 4, obwohl ich arg.RetVal auf false setze.

Info über meine Funktionen

  • GetCurrentCell(row, col) übersetzt die aktuelle Zelle von einem TreePath zu einem Paar von ints.
  • SetCurrentCell(row, col, [edit]) verwendet TreeView.SetCursor(), um eine Zelle Strom zu machen. edit kann true oder false sein. Wenn true ist, wird die Zelle in edition eingefügt. Wenn es false ist, wird nichts bearbeitet.

Antwort

2

Ich bin kein Experte in GTK, tatsächlich habe ich nie damit gearbeitet. Aber ich habe mit Standardsteuerelementen gespielt, um sie in ein nicht standardmäßiges Verhalten zu tricksen. Ich habe vor allem die Menüleiste verändert, die alle Eingaben bei gedrückter Alt-Taste gefangen hat, aber ich brauchte die Alt-Taste als Modifizierer für verschiedene Interaktionen. So kann ich Ihnen einen allgemeinen Ratschlag geben, um Ihre TreeView in das, was Sie brauchen, zu tricksen.

Frage 1:

Von dem, was Sie beschreiben, nehme ich das Standardverhalten Enter für eine erfolgreiche Bearbeitung drücken würde, und die Zelle zu verlassen, um die Bearbeitung abzubrechen. Dies könnte in vielen Anwendungen akzeptabel sein. Andere (z. B. Microsoft Excel) neigen dazu, das Editieren selbst beim Verlassen der Zelle zu akzeptieren. Ich kann also verstehen, dass Sie dieses Verhalten wollen.

Wenn es kein solches eingebautes Verhalten gibt, können Sie die Aktion simulieren, die ein Benutzer tun muss, um dem TreeView zu signalisieren, die Bearbeitung zu beenden, z. Drücken Sie Enter. Sie können ein gefälschtes Key-Ereignis mit dem beschriebenen Ansatz senden here oder wenn GTK auf WPF wie here baut. Der zweite Ansatz ist noch niedriger, da das Fake Key-Ereignis tatsächlich in die Windows-Ereigniswarteschlange implantiert wird. Ich schätze, das sollte auf jeden Fall funktionieren, solange deine Plattform Windows ist. Aber ich bin sicher, dass es ähnliche Mechanismen in anderen Betriebssystemen gibt.

Dann erst nach, übersetzen in die nächste Zelle, TreeView bekommt das verlorene Fokus-Ereignis, aber es ist nicht mehr im Bearbeitungsmodus und nichts sollte passieren.

Frage 2:

Was ich denke, passiert, ist die folgende: Eine-Taste gedrückt wird, TreeView nicht im Bearbeitungsmodus befindet, also das Ereignis ignoriert. Sie erhalten das Ereignis und legen es im Bearbeitungsmodus fest. Aber dann wird das Ereignis nicht zu TreeView zurückkehren, so dass keine Eingabe mehr vorgenommen wird.

Sie können den obigen Ansatz versuchen und das Schlüsselereignis manuell erneut senden. Eine andere Möglichkeit besteht darin, das Ereignis früher zu erfassen, und dann, wenn TreeView es verarbeitet. In WPF gibt es oft das PreviewOn* Ereignis (z.B. siehe here). Vielleicht gibt es ein solches Ereignis für deine Kontrolle?

Sie könnten sich auch noch tiefer einhaken. In WPF gibt es das Ereignis InputManager.Current.PreProcessInput, das direkt über der Windows-Nachrichtenschleife sitzt und Sie alle Arten von Eingaben filtern und verarbeiten kann.

Hier ist ein von meinem Code snipped die Ihnen helfen können:

InputManager.Current.PreProcessInput += (sender, e) => 
{ 
    if (e.StagingItem.Input is MouseButtonEventArgs) 
    { 
     var earg = (MouseButtonEventArgs)e.StagingItem.Input; 
     if (earg.RoutedEvent == Mouse.PreviewMouseDownOutsideCapturedElementEvent) 
      OnPreviewMouseDownOutsideCapturedElement(sender, earg); 
    } 
}; 

Weitere lowlevel Haken siehe zum Beispiel das question.

Viel Glück, und bitte kommentieren, wenn Sie spezifischere Fragen haben.

Verwandte Themen