2010-03-22 9 views
6

quando premiamo un tasto e continuiamo a premere, la pressione del tasto e l'evento keydown scatta continuamente. C'è un modo per lasciare che questi attivano solo dopo un ciclo completo, ad es. Keydown e quindi key up.come non consentire più tasti di chiamata ricevuti con una pressione di un tasto?

Vorrei che l'utente non fosse in grado di premere il tasto continuamente piuttosto vorrebbe che l'utente dovesse premere quindi rilasciare la tastiera per digitare un carattere!

in modo che il seguente caso non si verifichi ad esempio: pppppppppppppppppppppppppp quando l'utente preme "p" per 1 sec.

risposta

7

Dichiarare un booleano isKeyDown, nell'evento KeyDown, impostare il valore booleano su true. Nell'evento KeyUp, impostare il valore booleano su falso.

Questo è il codice di esempio

bool isKeyDown=false; 
public void control_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) 
{ 
    if(isKeyDown) 
     return; 
    isKeyDown=true; 
    // do what you want to do 
} 

public void control1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) 
{ 
    isKeyDown=false; 
    // do you key up event, if any. 
} 
+0

Come indicato dal poster, entrambi gli eventi si attivano (keyDown seguito da keyUp) anche quando è un tasto che si ripete – Ian

+0

@iAn: non è vero. ricevi ripetuti keydown, ma solo una chiave. –

+0

@iAn: MSDN dice altrimenti: "L'evento KeyDown si verifica quando l'utente preme un tasto qualsiasi L'evento KeyUp si verifica quando l'utente rilascia la chiave.Gli eventi KeyDown duplicati si verificano ogni volta che il tasto si ripete, se si tiene premuto il tasto, ma solo un evento KeyUp viene generato quando l'utente rilascia la chiave. " – Niki

2

Per evitare che una chiave di sparare più volte se tenuto premuto: è necessario utilizzare la proprietà SuppressKeyPress in questo modo:

bool isKeyRepeating = false; 

public void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) 
{ 
    if (isKeyRepeating) 
    { 
     e.SuppressKeyPress = true; 
    } 
    else 
    { 
     isKeyRepeating = true; 
    } 

} 

public void textBox1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) 
{ 
    isKeyRepeating = false; 
} 

See: KeyEventArgs..::.Handled Property ... e ... KeyEventArgs..::.SuppressKeyPress Property .... per le informazioni pertinenti

+0

Suoni a destra. –

+0

Se si imposta 'KeyPreview su Form' su true e si utilizza lo stesso codice (sopra) nei gestori KeyDown e KeyUp del modulo: tutti i TextBox su quel modulo avranno la soppressione dei tasti soppressa. Non l'ho testato su altri controlli rispetto ai TextBox. Il fatto che Nobugz (che è maledettamente più intelligente di me) ha dato una risposta qui sotto suggerisce questo codice, anche a livello di modulo non impedirebbe la ripetizione della chiave in qualche altra condizione di cui non sono a conoscenza. – BillW

5

È possibile farlo a livello di applicazione filtrando i messaggi chiave in basso con IMess Filtro età. Ecco un esempio:

public partial class Form1 : Form, IMessageFilter { 
    public Form1() { 
     InitializeComponent(); 
     Application.AddMessageFilter(this); 
     this.FormClosed += (s, e) => Application.RemoveMessageFilter(this); 
    } 

    private Keys mLastKey = Keys.None; 

    public bool PreFilterMessage(ref Message m) { 
     if (m.Msg == 0x100 || m.Msg == 0x104) { 
     // Detect WM_KEYDOWN, WM_SYSKEYDOWN 
     Keys key = (Keys)m.WParam.ToInt32(); 
     if (key != Keys.Control && key != Keys.Shift && key != Keys.Alt) { 
      if (key == mLastKey) return true; 
      mLastKey = key; 
     } 
     } 
     else if (m.Msg == 0x101 || m.Msg == 0x105) { 
     // Detect WM_UP, WM_SYSKEYUP 
     Keys key = (Keys)m.WParam.ToInt32(); 
     if (key == mLastKey) mLastKey = Keys.None; 
     } 
     return false; 
    } 
    } 

Una cosa che ho perseguito è il numero di ripetizioni nel messaggio WM_KEYDOWN. Stranamente questo non ha funzionato sulla mia macchina, era 1 per la ripetizione delle chiavi. Non so perché.

+0

@nobugz +1 Ho sempre imparato molto dalle tue risposte! Cose molto interessanti succedendo sopra con la rimozione di MessageFilter su Form Closed. Immagino che tu vada "così in profondità" nella tua risposta a coprire ogni possibile caso di input di controllo? Presumo che non ci sia modo di gestire questo a livello di applicazione che sarebbe indipendente da qualsiasi forma (s)? – BillW

+0

@BillW: Grazie! Questo è a livello di applicazione, IMessageFilter opera per tutte le forme. Se dovrebbe funzionare solo per un modulo, questa non è la soluzione giusta. Presumo che si tratti di una sorta di app di gioco, quindi dovrebbe essere ok. –

+0

Certo, ora posso vedere che è un'applicazione larga e mi chiedo come abbia perso visto che per cominciare :) – BillW