2015-05-07 10 views
12

Ho una keyPressed segnale in Gtk #/mono C# per due scopi differenti che non sono presenti nel default TreeView: a) passare alla cella successiva premendo TAB, e b) avviare la modifica premendo qualsiasi chiave.Come gestire la pressione dei tasti per scopi speciali in Gtk # TreeView?

Il TreeView è semplice, ha una ListStore mostrando solo righe e colonne, cioè esso contiene i dati tabulari.

Il codice che ho è di seguito.

[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; 
} 

Ho due domande:

  1. Come posso segnalare al TreeView che una cellula è stata terminata la modifica? Il problema è che se si preme TAB quando nessuna cella viene modificata, tutto funziona correttamente. Tuttavia, se l'utente sta modificando una cella, i contenuti immessi finora vengono persi. Quindi, nel caso in cui l'utente stia modificando una cella, desidero segnalare allo strumento TreeView di completare l'edizione e portare avanti il ​​comportamento corrente.

  2. Come evitare di perdere la prima chiave quando si modifica una cella? Di 'che sei al di sopra di una cella. Premi i tasti 1, 2, 3 e 4. L'handler interferisce correttamente e mette la cella corrente in modalità di edizione. Tuttavia, la cella ottiene solo 2, 3 e 4, anche se sto impostando arg.RetVal a false.

Info su mie funzioni

  • GetCurrentCell(row, col) traduce la cella corrente da un TreePath a una coppia di int.
  • SetCurrentCell(row, col, [edit]) utilizza TreeView.SetCursor() per rendere corrente una cella. edit può essere true o false. Se true, la cella viene messa in edizione. Se è false, non viene modificato nulla.

risposta

2

Non sono esperto in GTK, infatti non ho mai lavorato con esso. Ma ho giocato con i controlli standard per ingannarli in un comportamento non predefinito. Stavo specialmente modificando la barra dei menu, che intrappolava tutti gli input quando veniva premuto il tasto Alt, ma avevo bisogno del tasto Alt come modificatore per varie interazioni. Quindi posso offrirti alcuni consigli generali su come ingannare il tuo TreeView in quello che ti serve.

Domanda 1:

Da ciò che si descrive, suppongo il comportamento predefinito potrebbe essere quella di premere Enter per una modifica di successo, e di lasciare la cella per annullare la modifica. Questo potrebbe essere accettabile in molte applicazioni. Altri (ad es. Microsoft Excel) tendono ad accettare la modifica anche lasciando la cella. Quindi posso capire che vuoi questo comportamento.

Se non vi è alcun comportamento incorporato, è possibile simulare l'azione che un utente deve fare per segnalare a TreeView di terminare la modifica, ad es. premendo Invio. È possibile inviare un evento chiave falso utilizzando l'approccio descritto here o se GTK si basa su WPF come here. Il secondo approccio è ancora più basso in quanto impianta davvero l'evento chiave falso nella coda degli eventi di Windows. Immagino che dovrebbe funzionare in ogni caso, purché la tua piattaforma sia Windows. Ma sono sicuro che ci sono meccanismi simili in altri sistemi operativi.

Quindi solo DOPO che, si traduce nella cella successiva, TreeView ottiene l'evento di messa a fuoco persa, ma non è più in modalità di modifica e non dovrebbe accadere nulla.

Domanda 2:

Quello che penso succede è la seguente: si preme il tasto A, TreeView non è in modalità di modifica, in modo da ignora l'evento. Ottieni l'evento e impostalo in modalità modifica. Ma poi l'evento non tornerà a TreeView, quindi nessun input è reso più lungo.

Si potrebbe provare sopra approccio e manualmente re-inviare l'evento chiave. Un altro modo è quello di acquisire l'evento in precedenza, quindi quando lo processa TreeView. In WPF c'è spesso l'evento PreviewOn* (ad esempio, vedere here). quindi forse c'è un tale evento per il tuo controllo?

Puoi anche agganciarti ancora più a fondo. In WPF c'è l'evento InputManager.Current.PreProcessInput che si trova appena sopra il ciclo dei messaggi di Windows e consente di filtrare ed elaborare tutti i tipi di input.

Ecco un ritagliata da mio codice che possono aiutare a:

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); 
    } 
}; 

Per ganci più basso livello si veda ad esempio questo question.

Buona fortuna, e si prega di commentare, se avete domande più specifiche.

Problemi correlati