C# Windows.Forms.MouseButtons中的奇数枚举值

C# Windows.Forms.MouseButtons中的奇数枚举值,c#,winforms,enums,C#,Winforms,Enums,我在System.Windows.Forms命名空间中找到了这个gem(IMO)。我正在努力弄清楚为什么会这样 [Flags] public enum MouseButtons { None = 0, Left = 1048576, Right = 2097152, Middle = 4194304, XButton1 = 8388608, XButton2 = 16777216, } 有人能解释一下为什么它使用这些值(从2^20到2^24的幂)

我在
System.Windows.Forms
命名空间中找到了这个gem(IMO)。我正在努力弄清楚为什么会这样

[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
}

第一个值是二进制的
1000000000000000000
,这为另外20位留出了空间!为什么我们需要这样的空间?为什么要这样保存它?

Winforms中使用的枚举值确实倾向于匹配winapi中的相应位,但鼠标按钮完全不是这样。解释这一点需要相当大胆的猜测

我有一个,不依赖Windows消息检索鼠标按钮状态的方式非常奇怪。调用GetAsyncKeyState(),通过VK_XBUTTON2传递VK_LBUTTON。实际上代表鼠标键而不是键盘键的伪虚拟键。这是很久以前的事了,我猜不出他们为什么这样做,而不是提供一个合适的GetMouseButtonState()winapi函数

Keys枚举也有这些值,如Keys.LButton等。关键点的另一个特殊之处是,它还可以对修改器关键点的状态进行编码。例如,有Keys.Control和Keys.ControlKey。还有钥匙,Shift vs Keys,ShiftKey,等等。第一个表示密钥的状态,第二个表示实际密钥。它允许像keydata==(Keys.Control | Keys.F)这样的友好代码检查是否按下了Ctrl+F

这些鼠标按钮枚举值的意义在于,它们适合键枚举值,以指示鼠标按钮的状态。保留20位用于编码密钥的位


听起来不错,不是吗?唯一的问题是,它在Winforms对象模型中从未以这种方式组合。但是可以在您自己的代码中定义一个也使用鼠标状态的快捷方式。

我猜这与底层Windows API如何将鼠标信息传递到.NET有关

Windows软件包包括单击鼠标按钮以及信息块中的指针位置(想想旧的鼠标事件结构)。NET中的枚举是按照高效的方式设置的,因此它们可能与底层Windows消息的方式很好地吻合


因此,.NET不需要获取低级消息并将其转换为一组新的值,.NET只需将其感兴趣的低级消息中的位作为目标-无转换,无数学,只是效率问题。

可能是由于Win32的兼容性问题。@newStackExchangeInstance是否介意共享一个链接或一个可能导致类似情况的解释?我没有关于此特定情况的任何信息,但我知道的是,由于win32的原因,.NET中的枚举中有很多奇数值。因此,枚举值以某种方式直接传输到win32或从win32传输而不映射到正常值?这比这更奇怪,它只是强制转换,因为所有枚举都只是整型类型的类型安全包装。