ModifierKeys 按位与

ModifierKeys Bitwise AND

我正在向图表控件上的滚轮事件添加一些功能,我很好奇大多数文档中在确定按下哪个修改键时出现的按位 AND(例如 https://msdn.microsoft.com/en-us/library/yazd4ct6(v=vs.110).aspx

void Chart_MouseWheel(object sender, MouseEventArgs e)
{
    //if ((ModifierKeys & (Keys.Shift | Keys.Control)) == (Keys.Shift | Keys.Control)) 
    if(ModifierKeys == (Keys.Shift | Keys.Control))
    {
        //+/- 5 chart threshold with control and shift held
        Threshold += (decimal)(e.Delta / 24m / 100m);
    }
    //else if ((ModifierKeys & Keys.Shift) == Keys.Shift)
    else if(ModifierKeys == Keys.Shift)
    {
        //+/- 1 chart threshold change with shift held
        Threshold += (decimal)(e.Delta / 120m / 100m);
    }
    //else if ((ModifierKeys & Keys.Control) == Keys.Control)
    else if(ModifierKeys == Keys.Control)
    {
        var selectedIndex = styledComboBox1.SelectedIndex;
        selectedIndex += -1*(e.Delta / 120);

        if (selectedIndex < 0) selectedIndex = 0;
        if (selectedIndex > (styledComboBox1.Items.Count - 1)) selectedIndex = styledComboBox1.Items.Count - 1;

        styledComboBox1.SelectedIndex = selectedIndex;
    }
    else
    {
        AxisMax += 0.02 * e.Delta / 120;
    }
}

注释和未注释的 if/else if 行产生相同的结果,三种组合(Shift+Control、Shift、Control)中的每一种都产生了所需的效果,所以我只是想知道为什么它在未评论的场景。

此外,当我没有检查 Shift+Control 作为第一个条件时,它只会落入 Shift 块 - 这是为什么?

注释代码的工作方式与未注释代码相同,只要您不按任何其他修改键:尝试同时按 ALT,您应该注意区别。

如果您跳过第一次检查,第二次检查未注释的代码会说 "if only shift is pressed",而注释的代码会说 "if shift is pressed, no matter if other modifiers are pressed"

因此,跳过第一个检查,按 CTRL + SHIFT 不匹配您未注释的检查,但匹配注释检查

这个问题我玩得很开心,问得好!

TL;DR 按位 AND 从枚举中删除任何其他标志,以防您想要忽略它们并仅查看是否按下了您指定的键。

下面是一个控制台应用程序,它向您展示了每个操作的位,以及为什么在按 CTRL + SHIFT 时使用和不使用按位 AND 时它的工作原理相同。按位 AND 用于过滤掉任何其他修饰符:无论是否按下 ALT 或 WINDOWS,它都会将检查与 CTRL + SHIFT 进行比较。每个都有用例(您可能只想忽略 alt 键,这很好,您会在哪里使用它,或者您可能想确保它没有被按下,只有 CTRL 和 SHIFT)。

我从 right from the source.

中得到的 ModifierKeys 定义
public class Program
{
    [Flags]
    private enum ModifierKeys
    {
        None = 0,
        Alt = 1,
        Control = 2,
        Shift = 4,
        Windows = 8
    }

    static void Main(string[] args)
    {
        ModifierKeys none = ModifierKeys.None;
        ModifierKeys alt = ModifierKeys.Alt;
        ModifierKeys control = ModifierKeys.Control;
        ModifierKeys shift = ModifierKeys.Shift;
        ModifierKeys windows = ModifierKeys.Windows;
        ShowEnums(none, alt, control, shift, windows);

        ShowAddingFlags(control, shift);

        ShowBitwiseAnd(none, alt, control, shift, windows);


        CompareWithShiftAndControl(alt, control, shift);

        Console.ReadKey();
    }

    private static void ShowBitwiseAnd(params ModifierKeys[] ms)
    {
        List<ModifierKeys> mods = new List<ModifierKeys>();
        mods.AddRange(ms);

        ModifierKeys c = ModifierKeys.None;

        Console.WriteLine("Adding all...");

        foreach (var m in mods)
        {
            Console.WriteLine(GetBinaryString(m));
            c = c | m;
        }

        Console.WriteLine(GetBinaryString(c));
        Console.WriteLine(c);
        Console.WriteLine();
    }

    private static void CompareWithShiftAndControl(params ModifierKeys[] ms)
    {
        var withAlt = ModifierKeys.Alt | ModifierKeys.Control | ModifierKeys.Shift;
        var withoutAlt = ModifierKeys.Control | ModifierKeys.Shift;

        Console.WriteLine("Using bitwise And:" );

        var formatter = "{0} & {1} = {2}";
        Console.WriteLine(formatter, GetBinaryString(withAlt), GetBinaryString(withoutAlt), GetBinaryString(withAlt & withoutAlt));
        Console.WriteLine(formatter, withAlt, withoutAlt, withAlt & withoutAlt);

    }

    private static void ShowAddingFlags(params ModifierKeys[] ms)
    {
        List<ModifierKeys> mods = new List<ModifierKeys>();
        mods.AddRange(ms);

        ModifierKeys c = ModifierKeys.None;

        Console.WriteLine("Adding Control and Shift...");

        foreach (var m in mods)
        {
            Console.WriteLine(GetBinaryString(m));
            c = c | m;
        }

        Console.WriteLine(GetBinaryString(c));
        Console.WriteLine(c);
        Console.WriteLine();
    }

    private static string GetBinaryString(ModifierKeys modifierKeys)
    {
        return Convert.ToString((int)modifierKeys, 2).PadLeft(8, '0'); 
    }

    private static void ShowEnums(params ModifierKeys[] ms)
    {
        List<ModifierKeys> mods = new List<ModifierKeys>();
        mods.AddRange(ms);

        foreach (var m in mods)
        {
            Console.WriteLine(m);
            Console.WriteLine(GetBinaryString(m));
        }

        Console.WriteLine();
    }
}