Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Odd enum values in Windows.Forms.MouseButtons

Tags:

c#

enums

winforms

I found this gem (IMO) in System.Windows.Forms namespace. I'm struggling to figure out why is it set like this.

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

Can somebody explain why it uses these values (power of 2^20 to 2^24) instead of this:

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
}

The first value is 100000000000000000000 in binary, which leaves space for another 20 bits! Why do we need such space and why is it preserved like this?

like image 322
Odys Avatar asked Jun 10 '13 20:06

Odys


2 Answers

Enum values used in Winforms do tend to match corresponding bits in the winapi but that's not the case at all for mouse buttons. Explaining this one requires a pretty wild guess.

I do have one, the way you retrieve the state of the mouse buttons without relying on a Windows message is very strange. You call GetAsyncKeyState(), passing VK_LBUTTON through VK_XBUTTON2. Fake virtual keys that actually represent mouse keys and not keyboard keys. This happened way too long ago for me to guess why they did it this way instead of providing a proper GetMouseButtonState() winapi function.

The Keys enumeration has those values as well, like Keys.LButton etcetera. Something else that's special about Keys is that it can also encode the state of a modifier key. There are for example Keys.Control and Keys.ControlKey. And Keys.Shift vs Keys.ShiftKey, etcetera. The first one indicates the state of the key, the second one indicates the actual key. Which permits friendly code like keydata == (Keys.Control | Keys.F) to check if Ctrl+F was pressed.

The significance of these MouseButtons enum values is then that they fit in a Keys enum value to indicate the state of the mouse buttons. Leaving 20 bits available for the bits that encode the key.

Sounds good, doesn't it? The only hiccup is that it is never combined that way within the Winforms object model. But could be in your own code to define a shortcut that also uses the mouse state.

like image 133
Hans Passant Avatar answered Oct 12 '22 22:10

Hans Passant


My guess is that it has to do with how the underlying Windows API is passing mouse information to .NET.

Windows packages up which mouse buttons are clicked as well as pointer position in a block of information (think of the old MOUSE_EVENT structure). The enums in .NET are setup the way they are to be efficient, so they probably line up nicely with how the underlying Windows message.

So, instead of getting the lower-level message and having to convert it into a new set of values, .NET just targets the bits in the lower-level message that it is interested in - no conversion, no math, just efficiency.

like image 40
Brad Rem Avatar answered Oct 12 '22 22:10

Brad Rem