2009-10-07 5 views
0

Je suis en utilisant le code suivant pour afficher un menu contextuel sur ma forme quand on appuie sur « Alt-A »:Problèmes d'affichage d'un ContextMenu lors de l'événement KeyDown

private void Form1_KeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Alt && e.KeyCode == Keys.A) 
    { 
     ContextMenuStrip menu = new ContextMenuStrip(); 
     ToolStripMenuItem item = new ToolStripMenuItem("Hello &World"); 
     item.Click += new EventHandler(item_Click); 
     menu.MenuItems.Add(item); 

     ToolStripMenuItem item2 = new ToolStripMenuItem("Some &Andriod"); 
     item2.Click +=new EventHandler(item_Click); 
     menu.MenuItems.Add(item2); 

     menu.Show(this, new Point(0,0)); 
    } 
} 

void item_Click(object sender, EventArgs e) 
{ 
    MessageBox.Show("Hey!") 
} 

Le problème que j'ai est que le deuxième élément Meny ("Certains & Android") est en cours de "clic" dès que le menu est affiché - apparemment parce que la touche (Alt-A) est passé immémitairement au menu.

Si je change cet élément de menu pour avoir un Mnémonique différent (par exemple "& Certains Android"), cela ne se produit pas et le menu s'affiche normalement.

Je sais que la classe ContextMenu est dépréciée, mais est-il un moyen d'empêcher ce comportement? Je l'ai déjà essayé de définir la propriété Handled des EventArgs à vrai, mais qui n'a rien fait (probablement parce que ne fera pas quoi que ce soit jusqu'à ce que le gestionnaire d'événements est terminée, et la méthode Show() interrompt l'exécution jusqu'à ce que le ContextMenu ne soit plus affichée.

MISE à jOUR: J'ai mis à jour le code pour utiliser la nouvelle classe ContextMenuStrip et a constaté que la même chose arrive, mais la classe ContextMenuStrip fournit des méthodes beaucoup plus pour moi de passer outre permettre un meilleur contrôle de l'élément de menu

.

J'ai remarqué qu'avec la classe ContextMenuStrip la méthode Show() retourne instantanément (alors que le menu est toujours affiché), même si la propriété Handled est Ent Args à true n'empêche pas que la touche soit manipulée par le menu contextuel. Je cherche à utiliser une logique plus complexe pour décider si l'événement click doit être déclenché si un certain intervalle de temps s'est écoulé depuis que le menu a été affiché et si un événement KeyUp a été traité depuis, mais tout cela semble extrêmement salissant - sûrement quelqu'un d'autre a déjà rencontré ce problème auparavant?

Répondre

1

Je pense que cela pourrait être plus lié au fait que, dans KeyDown vous ouvrez votre menu et KeyUp est passée au menu, puis à la place.

Donc, vous devriez peut-être déplacer l'ouverture du menu à keyUp ou KeyPress. Cela devrait éviter le problème entièrement alors.

+0

qui a fait l'affaire - merci. – Justin

+0

Hmmm, peut-être j'étais un peu hâtive - oui mettre la même logique dans l'événement KeyUp empêche cela, mais idéalement je veux avoir le menu affiché pendant KeyDown - aussi le menu est déclenché avant de relâcher des touches, (donc je ne sais pas si tel est l'événement clé jusqu'à déclenchement) – Justin

+0

Hm, je pense que vous devriez essayer * déterminer ce qui se passe exactement *, en enregistrant des gestionnaires d'événements KeyUp/bas dans le menu et votre forme et l'impression des messages de diagnostic appropriés. Tout de suite, je ne sais pas exactement ce qui pourrait être responsable ici. Si 'e.Handled = true' n'aide pas à sentir que c'est KeyPress ou KeyUp qui déclenche l'entrée du menu. – Joey

4

J'ai eu le même problème avec une touche Alt enfoncée tout en ouvrant un menu contextuel. J'ai compris que c'était l'événement clé dans le menu contextuel qui a été publié peu de temps après la création. J'ai résolu le problème en héritant de la ContextMenuStrip et redéfinissant la méthode ProcessCmdKey comme suit:

public partial class AdvancedContextMenuStrip : ContextMenuStrip 
{ 
    public AdvancedContextMenuStrip() 
    { 
     InitializeComponent(); 
    } 

    protected override bool ProcessCmdKey(ref Message m, Keys keyData) 
    { 
     if ((keyData & Keys.Alt) == Keys.Alt) 
      return true; 

     return base.ProcessCmdKey(ref m, keyData); 
    } 
} 
+0

Cela a résolu mon problème. Je veux arrêter l'ouverture du menu contextuel si une certaine touche est actuellement pressée. L'utilisation de Close() dans la méthode de remplacement lorsque la clé cible est détectée fonctionne. – ScruffyDuck

+0

J'avais besoin d'ouvrir un menu contextuel par un clic droit mais en donnant des éléments différents lorsque le clic était fait avec Alt. Sans surcharger ProcessCmdKey, le menu contextuel a été immédiatement fermé lorsque vous avez appuyé sur alt. Ce code a résolu le problème. – Feri

Questions connexes