Je construis une application où toutes les entrées clés doivent être gérées par les fenêtres elles-mêmes.
Je règle tabstop sur false pour chaque contrôle qui peut saisir le focus sauf un panneau (mais je ne sais pas si cela a un effet).
J'ai défini KeyPreview sur true et je gère l'événement KeyDown sur ce formulaire.
Mon problème est que parfois les touches fléchées ne répondent plus:
L'événement keydown n'est pas déclenché lorsque j'ai appuyé uniquement sur une touche fléchée.
L'événement keydown est déclenché si j'appuie sur une touche fléchée avec le modificateur de contrôle.
Avez-vous une idée de la raison pour laquelle ma touche fléchée arrête soudainement de tirer?
protected override bool IsInputKey(Keys keyData)
{
switch (keyData)
{
case Keys.Right:
case Keys.Left:
case Keys.Up:
case Keys.Down:
return true;
case Keys.Shift | Keys.Right:
case Keys.Shift | Keys.Left:
case Keys.Shift | Keys.Up:
case Keys.Shift | Keys.Down:
return true;
}
return base.IsInputKey(keyData);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
switch (e.KeyCode)
{
case Keys.Left:
case Keys.Right:
case Keys.Up:
case Keys.Down:
if (e.Shift)
{
}
else
{
}
break;
}
}
J'avais exactement le même problème. J'ai considéré la réponse fournie par @Snarfblam; Toutefois, si vous lisez la documentation sur MSDN, la méthode ProcessCMDKey est censée remplacer les événements clés pour les éléments de menu dans une application.
Je suis récemment tombé sur cet article de Microsoft, qui semble très prometteur: http://msdn.Microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx . Selon Microsoft, la meilleure chose à faire est de définir e.IsInputKey=true;
dans l'événement PreviewKeyDown
après la détection des touches de direction. Cela déclenchera l'événement KeyDown
.
Cela fonctionnait assez bien pour moi et était moins astucieux que de remplacer ProcessCMDKey.
J'utilise PreviewKeyDown
private void _calendar_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e){
switch (e.KeyCode){
case Keys.Down:
case Keys.Right:
//action
break;
case Keys.Up:
case Keys.Left:
//action
break;
}
}
Voir Réponse de Rodolfo Neuber pour la meilleure réponse
(Ma réponse originale):
Dérivez d'une classe de contrôle et vous pouvez remplacer la méthode ProcessCmdKey. Microsoft a choisi d'omettre ces clés des événements KeyDown car elles affectent plusieurs contrôles et déplacent le focus, mais il est très difficile de faire réagir une application à ces clés de toute autre manière.
J'ai eu un problème similaire lors de l'appel de la fenêtre WPF à partir de WinForms.
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.Show();
Cependant, montrer la fenêtre comme un dialogue , cela a fonctionné
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.ShowDialog();
J'espère que cela t'aides.
Malheureusement, il est assez difficile d'y parvenir avec les touches fléchées, en raison des restrictions imposées par les événements KeyDown. Cependant, il existe plusieurs façons de contourner ce problème:
Je recommande d'essayer d'utiliser cette classe. C'est assez simple de le faire:
var left = KeyboardInfo.GetKeyState(Keys.Left);
var right = KeyboardInfo.GetKeyState(Keys.Right);
var up = KeyboardInfo.GetKeyState(Keys.Up);
var down = KeyboardInfo.GetKeyState(Keys.Down);
if (left.IsPressed)
{
//do something...
}
//etc...
Si vous l'utilisez en combinaison avec l'événement KeyDown, je pense que vous pouvez atteindre votre objectif de manière fiable.
protected override bool IsInputKey(Keys keyData)
{
if (((keyData & Keys.Up) == Keys.Up)
|| ((keyData & Keys.Down) == Keys.Down)
|| ((keyData & Keys.Left) == Keys.Left)
|| ((keyData & Keys.Right) == Keys.Right))
return true;
else
return base.IsInputKey(keyData);
}
Pour capturer les séquences de touches dans un contrôle Forms, vous devez dériver une nouvelle classe basée sur la classe du contrôle que vous souhaitez et remplacer le ProcessCmdKey ().
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
//handle your keys here
}
Exemple :
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
//capture up arrow key
if (keyData == Keys.Up )
{
MessageBox.Show("You pressed Up arrow key");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
Source complète ... Touches fléchées en C #
Vayne
Je pense que la meilleure solution consiste à le gérer comme le dit MSDN http://msdn.Microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx
Mais manipulez-le, comme vous en avez vraiment besoin. Ma façon (dans l'exemple ci-dessous) est d'attraper chaque KeyDown ;-)
/// <summary>
/// onPreviewKeyDown
/// </summary>
/// <param name="e"></param>
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
{
e.IsInputKey = true;
}
/// <summary>
/// onKeyDown
/// </summary>
/// <param name="e"></param>
protected override void OnKeyDown(KeyEventArgs e)
{
Input.SetFlag(e.KeyCode);
e.Handled = true;
}
/// <summary>
/// onKeyUp
/// </summary>
/// <param name="e"></param>
protected override void OnKeyUp(KeyEventArgs e)
{
Input.RemoveFlag(e.KeyCode);
e.Handled = true;
}
j'ai eu le même problème et utilisais déjà le code dans la réponse sélectionnée. ce lien était la réponse pour moi; peut-être pour d'autres aussi.
Comment désactiver la navigation sur WinForm avec des flèches en C #?