2010-07-21 16 views
6

Fondamentalmente, ho un modulo con un controllo personalizzato su di esso (e nient'altro). Il controllo personalizzato è completamente vuoto e il modulo ha KeyPreview impostato su true.Eventi tasto freccia non in arrivo

Con questa configurazione, non ricevo alcun evento KeyDown per alcun tasto freccia o Tab. Ogni altra chiave che ho sulla mia tastiera funziona. Ho gestori di eventi KeyDown collegati a tutto ciò che ha tali eventi, quindi sono sicuro che non mi manca nulla.

Si noti inoltre che se rimuovo il controllo personalizzato (completamente vuoto), ottengo gli eventi del tasto freccia.

Che diavolo sta succedendo qui?

EDIT:

ho aggiunto che questo sia la forma ed il controllo, ma non sto ancora ricevendo i tasti freccia:

protected override void WndProc(ref Message m) { 
    switch (m.Msg) { 
     case 0x100: //WM_KEYDOWN 
      //this is the control's version. In the form, it's this.Text 
      ParentForm.Text = ((Keys)m.WParam).ToString(); 
      break; 
    } 
    base.WndProc(ref m); 
} 

Ho anche controllato con Spy ++, e determinato che la forma stessa non sta ricevendo alcun messaggio WM_KEYDOWN, stanno andando tutti al controllo. Tuttavia, detto questo, il controllo sta ottenendo il tasto freccia WM_KEYDOWN. Sospiro.

Modifica 2: Ho anche aggiornato il file ZIP con questa versione. Si prega di vedere le cose, se si vuole aiutare ...

Edit 3:

ho capito questo, più o meno. Il modulo sta mangiando i tasti freccia, probabilmente nel tentativo di mantenere la concentrazione tra i suoi figli. Ciò è dimostrato dal fatto che ottengo gli eventi se il modulo è vuoto.

Comunque, se posso aggiungere questo codice al form, ho iniziare a ricevere di nuovo gli eventi:

public override bool PreProcessMessage(ref Message msg) { 
    switch (msg.Msg) { 
     case 0x100: //WM_KEYDOWN 
      return false; 
    } 
    return base.PreProcessMessage(ref msg); 
} 

Quando ho sovrascrivere questo, il modulo non viene la possibilità di fare il suo sporco lavoro, e così Ottengo i miei eventi KeyDown come mi aspetto. Presumo che un effetto collaterale di questo è che non posso più usare la mia tastiera per navigare nel modulo (non è un grosso problema in questo caso, dato che è un gioco, e l'intero scopo di questo esercizio è implementare la navigazione da tastiera!)

La questione rimane ancora su come disattivare questa "correttamente", se c'è un modo ...

+0

Sembra che il modulo su cui è attivo il controllo utente stia catturando l'evento e lo imposti per essere gestito prima che l'utente venga controllato da UserControl. Stai assicurando che il controllo utente sia attivo quando viene premuto il tasto? –

risposta

10

Ho effettuato alcuni test approfonditi e ho capito tutto.I wrote a blog post detailing the solution.

In breve, si desidera sovrascrivere il metodo ProcessDialogKey nella forma:

protected override bool ProcessDialogKey(Keys keyData) { 
    return false; 
} 

Questo farà sì che i tasti freccia (e scheda) da consegnare come normali eventi KeyDown. PERÒ! Ciò causerà anche la normale funzionalità dei tasti di dialogo (usando Tab per navigare i controlli, ecc.) Per fallire. Se si desidera mantenere, ma ancora ottenere l'evento KeyDown, utilizzare questo invece:

protected override bool ProcessDialogKey(Keys keyData) { 
    OnKeyDown(new KeyEventArgs(keyData)); 
    return base.ProcessDialogKey(keyData); 
} 

Ciò consegnare un messaggio KeyDown, pur facendo la normale navigazione il dialogo.

+0

Funziona come un incantesimo. – Carra

+0

Grazie! Funziona perfettamente! –

+0

Il tuo blog link è morto?!? –

0

Se messa a fuoco è il problema, e non è possibile ottenere il vostro controllo utente a prendere una messa a fuoco e mantenerlo , una semplice soluzione di work-around sarebbe quella di echeggiare l'evento al controllo dell'utente sull'evento chiave di cui si è preoccupati. Abbonati ai tuoi keydown form o eventi keypress e poi fai in modo che quell'evento porti un evento al tuo controllo utente.

Quindi, in sostanza, Form1_KeyPress chiamerebbe UserControl1_KeyPress con il mittente e gli argomenti di evento da Form1_KeyPress, ad es.

protected void Form1_KeyPress(object sender, KeyEventArgs e) 
{ 
    UserControl1_KeyPress(sender, e); 
} 

In caso contrario, potrebbe essere necessario prendere la strada lunga e sovrascrivere gli eventi WndProc per ottenere la funzionalità desiderata.

+0

UserControl è vuoto e non può ricevere lo stato attivo (AFAIK). Pertanto, il modulo stesso dovrebbe ricevere gli eventi KeyDown. Tuttavia, non lo è. Come ho affermato nella domanda, ho gestori di eventi collegati a tutto ciò che ha l'evento, ma niente sta ricevendo l'evento. Posso provare a sovrascrivere WndProc, ma davvero non dovrei ... –

+0

Ho aggiornato l'OP con i risultati del mio sovrascritto WndProc –