2011-12-10 11 views
5

Il mio obiettivo è quello di implementare un gestore di tasti personalizzato Control + S per collegare un metodo di salvataggio personalizzato in un'app winforms.WinForms - Acquisizione della combinazione di pressioni dei tasti con ProcessCmdKey VS KeyDown

Ci sono diversi modi per farlo in base al mio R & D. In primo luogo, ho provato l'ovvio gestore di eventi KeyPress. Questo non era abbastanza potente per catturare le pressioni dei tasti che mi servono (non è stato chiamato a livello di Editor, che è quello che mi serviva).

La seconda opzione che sembra migliore è l'override protetto bool ProcessCmdKey (ref Message msg, Keys keyData) override. Funziona - intercetta il clic del tasto CTRL, ma a quanto pare ho bisogno di scrivere un codice extra per mantenere il fatto che il tasto CTRL sia premuto e intercetti il ​​tasto successivo (che sarebbe S nel mio caso) e poi eseguo l'azione personalizzata.

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     if (keyData == (Keys.S | Keys.Control)) 
     { 
      // This is never called 
     } 
     else if (keyData == (Keys.Menu | Keys.Alt)) 
     { 
      // this is called each time I hit CTRL 
     } 
     return true; 
    } 

ProcessCmdKey sembra essere chiamato immediatamente dopo aver premuto il tasto CTRL.

Questo post suggerisce la creazione di una classe Keytracker che persisterà i tasti premuti e fare ciò che deve fare:

Capture Key Sequence via ProcessCmdKey

che sembra una buona opzione, ma prima di scavare in una implementare un ricordo modello di tracciamento, qualcuno ha input su come altro per realizzare questa caratteristica apparentemente comune?

Un altro modello utilizza la funzione API GetKeyboardState:

Capture multiple key downs in C#

Questo sembra interessante, anche se non sono sicuro che sarà ideale mie esigenze.

[DllImport ("user32.dll")] 

public static extern int GetKeyboardState (byte [] keystate);

private void Form1_KeyDown(object sender, KeyEventArgs e) 
{ 
    byte[] keys = new byte[255]; 

    GetKeyboardState (keys); 

    if(keys[(int)Keys.Up] == 129 && keys[(int)Keys.Right] == 129) 
    { 
     Console.WriteLine ("Up Arrow key and Right Arrow key down."); 
    } 
} 

Grazie per dare un'occhiata al mio problema.

UPDATE

Ho aggiunto tre eventi per la consegna delle chiavi ai miei Datapanel. Nessuno di questi eventi viene raccolto da VS quando definisco i punti di interruzione negli eventi, quindi questo è ciò che mi porta a credere che ProcessCmdKey sia la mia migliore opzione.

Se potessi ottenere questi eventi per il lavoro, che sarebbe bene così:

 // Ctrl + S: Save Support 
     this.ParentForm.KeyPreview = true; 
     this.KeyPress    += new KeyPressEventHandler(DataPanel_KeyPress); 
     this.KeyDown    += new KeyEventHandler(DataPanel_KeyDown); 
     this.PreviewKeyDown  += new PreviewKeyDownEventHandler(DataPanel_PreviewKeyDown); 

Nessuno di questi eventi sembra essere catturati quando la pressione dei tasti:

void DataPanel_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) 
    { 
     if (e.KeyCode == (Keys.S | Keys.Control)) 
     { 
      SessionManager.Trace.AddTrace("You Hit Save!!"); 
     } 
    } 

    void DataPanel_KeyDown(object sender, KeyEventArgs e) 
    { 
     if (e.KeyCode == (Keys.S | Keys.Control)) 
     { 
      SessionManager.Trace.AddTrace("You Hit Save!!"); 
     } 
    } 

    void DataPanel_KeyPress(object sender, KeyPressEventArgs e) 
    { 
     var key = e.KeyChar; 
    } 

UPDATE

Ho risolto il problema utilizzando un semplice evento KeyUp e il flag KeyPreview:

void ShipmentDataPanel_KeyUp(object sender, KeyEventArgs e) 
    { 
     if (e.Control && e.KeyCode == Keys.S) 
     { 
      MessageBox.Show("Control + S Key Hit!"); 
     } 
    } 

Grazie.

+0

possibile duplicato di [modo migliore per attuare le scorciatoie da tastiera in WinForms?] (Http://stackoverflow.com/questions/400113/best-way-to-implement -keyboard-shortcuts-in-winforms) –

risposta

3

Impostare la proprietà KeyPreview del modulo su true. Il riepilogo di questa proprietà dice: "Ottiene o imposta un valore che indica se il modulo riceverà eventi chiave prima che l'evento venga passato al controllo che ha lo stato attivo". Quindi utilizzare l'evento KeyUp. A meno che non sia KeyPressed, fornisce anche informazioni su tasti speciali come i tasti di controllo.

+0

Grazie - Ci proverò adesso. Sai fuori mano se KeyPreview funzionerà con l'override di ProcessCmdKey()? – nocarrier

+0

A proposito, sto lavorando al livello DataPanel, quindi presumo che aggiungerò la proprietà KeyPreview al mio ParentForm? Esempio: this.ParentForm.KeyPreview = true; – nocarrier

+0

Ho aggiunto un aggiornamento alla mia domanda. Ho aggiunto gli eventi KeyPress che hai suggerito, ma il mio DataPanel sembra non volerli sottoscrivere. KeyPreview non sembra avere effetto anche sull'evento ProcessCmdKey (viene ancora avviato alla pressione del tasto CTRL). – nocarrier

0

ho risolto questo facendo,

if(e.KeyData==(Keys.S | Keys.Control)) 
Problemi correlati