Нечетные значения перечисления в Windows.Forms.MouseButtons

Я нашел этот камень (IMO) в пространстве имен System.Windows.Forms. Я пытаюсь понять, почему это так.

[Flags]
public enum MouseButtons
{
    None = 0,
    Left = 1048576,
    Right = 2097152,
    Middle = 4194304,
    XButton1 = 8388608,
    XButton2 = 16777216,
}

Может кто-нибудь объяснить, почему он использует эти значения (мощность от 2^20 до 2^24) вместо этого:

public enum MouseButtons
{
    None = 0,
    Left = 1,      // 2^0
    Right = 2,     // 2^1
    Middle = 4,    // 2^2
    XButton1 = 8,  // 2^3
    XButton2 = 16, // 2^4
}

Первое значение 100000000000000000000 в двоичном формате, которое оставляет пространство для еще 20 бит! Зачем нам такое пространство и почему оно сохраняется так?

Ответ 1

Значения Enum, используемые в Winforms, имеют тенденцию соответствовать соответствующим битам в winapi, но это не относится ко всем кнопкам мыши. Объяснение этого требует довольно дикого угадывания.

У меня его есть, то, как вы извлекаете состояние кнопок мыши, не полагаясь на сообщение Windows, очень странно. Вы вызываете GetAsyncKeyState(), передавая VK_LBUTTON через VK_XBUTTON2. Поддельные виртуальные ключи, которые фактически представляют собой клавиши мыши, а не клавиши клавиатуры. Это произошло слишком давно для меня, чтобы догадаться, почему они сделали это таким образом, вместо того, чтобы предоставлять правильную функцию GetMouseButtonState() winapi.

Перечисление ключей также имеет такие значения, как Keys.LButton и т.д. Что-то еще особенное в Keys заключается в том, что он также может кодировать состояние ключа-модификатора. Например, Keys.Control и Keys.ControlKey. И Keys.Shift vs Keys.ShiftKey и т.д. Первый показывает состояние ключа, второй - фактический ключ. Что позволяет использовать дружественный код, например keydata == (Keys.Control | Keys.F), чтобы проверить, нажата ли комбинация клавиш Ctrl + F.

Значение этих значений перечисления MouseButtons заключается в том, что они вписываются в значение переименования клавиш, чтобы указать состояние кнопок мыши. Оставляя 20 бит доступными для битов, которые кодируют ключ.

Звучит неплохо, не так ли? Единственная икота заключается в том, что она никогда не объединяется в объектной модели Winforms. Но может быть в вашем собственном коде, чтобы определить ярлык, который также использует состояние мыши.

Ответ 2

Я предполагаю, что это связано с тем, как базовый Windows API передает информацию мыши в .NET.

Windows-пакеты, на которые нажимаются кнопки мыши, а также позиция указателя в блоке информации (подумайте о старой структуре MOUSE_EVENT). Перечисления в .NET настраиваются так, как они должны быть эффективными, поэтому они, вероятно, хорошо согласуются с тем, как основное сообщение Windows.

Итак, вместо того, чтобы получать сообщение нижнего уровня и преобразовывать его в новый набор значений,.NET просто нацеливает биты в сообщении нижнего уровня, которое ему интересно - без преобразования, без математики, просто эффективность.