2009-02-16 7 views
1

Signalé J'ai une combinaison de touches comme celui-cicomment développer ENUM

Keys key=Keys.Control | Keys.Shift | Keys.D ... 

Je ne sais pas comment élargir la variable clé de valeurs séparées par des clés. Peut-être comme ça

foreach(Keys k in key) 
{ 
    MessageBox.Show(k.ToString()); 
} 

cela me semble stupide. Comment faire ça?

Répondre

3
Keys key = Keys.Control | Keys.Shift | Keys.D; 

foreach (string s in key.ToString().Split(',')) 
{ 
    Keys k = (Keys) Enum.Parse(typeof(Keys), s.Trim()); 

    Console.WriteLine(k); 
} 
9

Voir la définition des clés. Toutes les valeurs agissent comme normales, des valeurs mutuellement exclusives, à l'exception de ce qui suit:

//  The bitmask to extract a key code from a key value. 
KeyCode = 65535, 
//  The SHIFT modifier key. 
Shift = 65536, 
//  The CTRL modifier key. 
Control = 131072, 
//  The ALT modifier key. 
Alt = 262144, 

donc tout ce que vous devez vérifier est l'alt, le contrôle et le décalage. Pour obtenir la clé non décalée, utilisez

Keys value = key & Keys.KeyCode 

Pour savoir si changement, alt ou contrôle est pressé

bool altValue = key & Keys.Alt 
bool controlValue = key & Keys.Control 
bool shiftValue = key & Keys.Shift 

Et voilà

2

Le battant pavillon énumérations sont juste bons vieux champs de bits , vous devez utiliser les opérations de bits pour voir quelles valeurs ont été définies, par exemple:

foreach(Key i in Enum.GetValues(typeof(Keys))) 
{ 
    if(key & i !=0) 
     MessageBox.Show(i); 
} 
+0

Ceci n'est pas bon pour une énumération Keys car ce ne sont pas des champs de bits sauf trois valeurs; toutes les valeurs jusqu'à 65535 sont des valeurs enum normales, donc la plupart des clés provoquent beaucoup de boîtes de message ici. – configurator

0
foreach(int keyValue in Enum.GetValues(typeof(Keys))) 
    { 
     if(k & keyValue != 0) 
      Console.WriteLine(((Key)keyValue).ToString() + " is pressed"); 
    } 
+0

Cela donnera des valeurs supplémentaires si l'enum définit certaines combinaisons de convience, par ex. "Default" ou "AllValues". –

+0

@Jon si c'est le cas, il est possible de filtrer les valeurs indésirables en vérifiant que Math.Log (keyValue) /Math.Log (2) est entier et non 0. (ie keyValue est la puissance de 2) –

3

En supposant qu'il est un ENUM basé int avec des valeurs composant 1, 2, 4 ... 2^n, vous pouvez utiliser:

public static IEnumerable<T> DecomposeEnum<T>(T value) where T : struct 
{ 
    int intValue = (int)(object) value; 
    for (int bit = 0; bit < 32 && intValue >> bit != 0; bit++) 
    { 
     int candidate = 1 << bit; 
     if ((candidate & intValue) != 0) 
     { 
      yield return (T) (object) candidate; 
     } 
    } 
} 

C'est assez sombre en termes de boxe et unboxing, mais la plupart du temps fonctionne. Pourquoi surtout? Eh bien, nous allons essayer ceci:

static void Main() 
{ 
    Keys keys = Keys.Control | Keys.Shift | Keys.D; 
    foreach (Keys key in DecomposeEnum(keys)) 
    { 
     Console.WriteLine(key); 
    } 
} 

Le résultat est:

MButton 
64 
Shift 
Control 

Ceci est parce que "D" est pas représenté par un seul bit, mais une combinaison de bits. Le code ci-dessus fonctionnera pour les types de drapeaux "purs" (c'est pourquoi je le laisse ici) mais vous voudrez peut-être chercher ailleurs si vous voulez spécifiquement utiliser les touches.

+0

Avez-vous une solution similaire pour aller dans l'autre sens? C'est à dire. composition d'un «IEnumerable » à un «TEnum»? –

+1

@gt: Vous pouvez convertir chaque valeur en un 'int', ou les ensemble, puis renvoyer le résultat à' T'. –

0
int i = 1; 
while (key > 0) { 
    if ((key & (Keys)i) > 0) 
     DoSomething(); 
    i <<= 1; 
} 
0

Les clés ENUM a [Flags] attribut si keys.ToString() envoie déjà "Contrôle, Shift, D" sans que vous ayez à faire tout ce genre de choses.