C# 这个位掩码如何应用于LPRAM(WM_热键)

C# 这个位掩码如何应用于LPRAM(WM_热键),c#,winapi,bit-manipulation,intptr,C#,Winapi,Bit Manipulation,Intptr,目前,我正在开发一个简单的类库,可以在各种不同的工具的帮助下进行处理 考虑一下我编写的这段完整的代码 protected override void WndProc(ref Message m) { const int WM_HOTKEY = 0x0312; if (m.Msg == WM_HOTKEY) { var modifier = (int) m.LParam & 0xFFFF; var key = ((int) m.LP

目前,我正在开发一个简单的类库,可以在各种不同的工具的帮助下进行处理

考虑一下我编写的这段完整的代码

protected override void WndProc(ref Message m)
{
    const int WM_HOTKEY = 0x0312;

    if (m.Msg == WM_HOTKEY)
    {
        var modifier = (int) m.LParam & 0xFFFF;
        var key = ((int) m.LParam & 0xFFFF);
    }

    base.WndProc(ref m);
}
一些我真的不明白的东西,我想在这里解释一下位掩码是如何工作的。我对如何应用逐位运算符有合理的理解,但我不理解为什么在这里应用这个特定的位掩码


此外,我正在努力理解
IntPtr
的目的。为什么在这种情况下,
LParam
IntPtr
?谢谢

WM_热键的文档说明
LPARAM
包含两个16位字段。高位字(高位16位)具有按下键的VK,低位字(低位16位)具有指定的修饰符

LPARAM&0xffff
将获得低16位,而
LPARAM>>16
将获得高16位

LPARAM&0xffff
之所以有效,是因为32位LPARAM看起来像:

   V bit 31                              V bit 0
   HIGH WORD           LOW WORD
0y vvvv vvvv vvvv vvvv mmmm mmmm mmmm mmmm where v is the vk, and m is the modifier 
0y 0000 0000 0000 0000 1111 1111 1111 1111 == 0x0000ffff
========================================== Bitwise and
0y 0000 0000 0000 0000 mmmm mmmm mmmm mmmm Just left with the modifier bits
LPARAM>>16
通过将位16位置向右移位来工作

   V bit 31                              V bit 0
   HIGH WORD           LOW WORD
0y vvvv vvvv vvvv vvvv mmmm mmmm mmmm mmmm where v is the vk, and m is the modifier 
0y 0vvv vvvv vvvv vvvv vmmm mmmm mmmm mmmm right shifted once (>> 1)
0y 00vv vvvv vvvv vvvv vvmm mmmm mmmm mmmm right shifted twice (>> 2)
...
0y 0000 0000 0000 0000 vvvv vvvv vvvv vvvv right shifted sixteen times (>> 16)
LPARAM
定义为指针的大小,因此它将映射到托管代码中的
IntPtr
。因为我们只使用LPRAM的低32位,所以我们需要切掉高32位。我们可以强制转换为
int
来执行此操作,但如果您使用
选中的
算法运行,则会导致
溢出异常。相反,我们将
IntPtr
转换为
long
(在32位机器上,它将为零填充),然后转换为
int
(它将截断)

如果我们不将
IntPtr
调整为
Int32
,则如果应用程序发送的消息的高位设置为
lparam>>16
,则可能会出现异常

IntPtr lparam = /* comes from WndProc */;
Int32 lparam32 = unchecked((int)(long)lparam);

Int16 lowWord = lparam32 & 0xffff;
Int16 highWord = lparam32 >> 16;
也就是说,这里有一个C#热键监听器的完整实现,我不记得在哪里找到的。如果有人对此有归属,请让我知道,或者编辑这篇文章列出原作者

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public sealed class KeyboardHook : IDisposable
{
    private int _currentId;
    private Window _window;

    public event EventHandler<KeyPressedEventArgs> KeyPressed;

    public KeyboardHook()
    {
        EventHandler<KeyPressedEventArgs> handler = null;
        this._window = new Window();
        if (handler == null)
        {
            handler = delegate (object sender, KeyPressedEventArgs args) {
                if (this.KeyPressed != null)
                {
                    this.KeyPressed(this, args);
                }
            };
        }
        this._window.KeyPressed += handler;
    }

    public void Dispose()
    {
        for (int i = this._currentId; i > 0; i--)
        {
            UnregisterHotKey(this._window.Handle, i);
        }
        this._window.Dispose();
    }

    public void RegisterHotKey(ModifierKeys modifier, Keys key)
    {
        this._currentId++;
        if (!RegisterHotKey(this._window.Handle, this._currentId, (uint) modifier, (uint) key))
        {
            throw new InvalidOperationException("Couldn’t register the hot key.");
        }
    }

    [DllImport("user32.dll")]
    private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
    [DllImport("user32.dll")]
    private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

    private class Window : NativeWindow, IDisposable
    {
        private static int WM_HOTKEY = 0x312;

        public event EventHandler<KeyPressedEventArgs> KeyPressed;

        public Window()
        {
            this.CreateHandle(new CreateParams());
        }

        public void Dispose()
        {
            this.DestroyHandle();
        }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == WM_HOTKEY)
            {
                Keys key = ((Keys) (((int) m.LParam) >> 0x10)) & Keys.KeyCode;
                ModifierKeys modifier = ((ModifierKeys) ((int) m.LParam)) & ((ModifierKeys) 0xffff);
                if (this.KeyPressed != null)
                {
                    this.KeyPressed(this, new KeyPressedEventArgs(modifier, key));
                }
            }
        }
    }
}
使用系统;
使用System.Runtime.CompilerServices;
使用System.Runtime.InteropServices;
使用System.Windows.Forms;
公共密封类键盘挂钩:IDisposable
{
私有int_currentId;
私人窗口(private Window);;
按下公共事件处理程序键;
公用键盘钩子()
{
EventHandler=null;
这是一个新窗口;
if(handler==null)
{
handler=delegate(对象发送者,按键edeventargs args){
如果(this.KeyPressed!=null)
{
按下此键(此,args);
}
};
}
此._window.KeyPressed+=处理程序;
}
公共空间处置()
{
对于(int i=this.\u currentId;i>0;i--)
{
取消注册热键(this.\u window.Handle,i);
}
此。_window.Dispose();
}
公共无效注册表快捷键(ModifierKeys修饰符,快捷键)
{
这个;
if(!RegisterHotKey(this.\u window.Handle,this.\u currentId,(uint)修饰符,(uint)key))
{
抛出新的InvalidOperationException(“无法注册热键”);
}
}
[DllImport(“user32.dll”)]
私有静态外部布尔寄存器hotkey(IntPtr hWnd、int id、uint fsModifiers、uint vk);
[DllImport(“user32.dll”)]
私有静态外部bool unregister热键(IntPtr hWnd,intid);
私有类窗口:NativeWindow,IDisposable
{
私有静态int WM_热键=0x312;
按下公共事件处理程序键;
公共窗口()
{
this.CreateHandle(新的CreateParams());
}
公共空间处置()
{
这个.handle();
}
受保护的覆盖无效WndProc(参考消息m)
{
基准WndProc(参考m);
if(m.Msg==WM_热键)
{
Keys key=((Keys)((int)m.LParam)>>0x10))&Keys.KeyCode;
ModifierKeys修饰符=((ModifierKeys)((int)m.LParam))和((ModifierKeys)0xffff);
如果(this.KeyPressed!=null)
{
this.KeyPressed(this,new KeyPressedEventArgs(modifier,key));
}
}
}
}
}

WM_热键的文档说明
LPRAM包含两个16位字段。高位字(高位16位)具有按下键的VK,低位字(低位16位)具有指定的修饰符

LPARAM&0xffff
将获得低16位,而
LPARAM>>16
将获得高16位

LPARAM&0xffff
之所以有效,是因为32位LPARAM看起来像:

   V bit 31                              V bit 0
   HIGH WORD           LOW WORD
0y vvvv vvvv vvvv vvvv mmmm mmmm mmmm mmmm where v is the vk, and m is the modifier 
0y 0000 0000 0000 0000 1111 1111 1111 1111 == 0x0000ffff
========================================== Bitwise and
0y 0000 0000 0000 0000 mmmm mmmm mmmm mmmm Just left with the modifier bits
LPARAM>>16
通过将位16位置向右移位来工作

   V bit 31                              V bit 0
   HIGH WORD           LOW WORD
0y vvvv vvvv vvvv vvvv mmmm mmmm mmmm mmmm where v is the vk, and m is the modifier 
0y 0vvv vvvv vvvv vvvv vmmm mmmm mmmm mmmm right shifted once (>> 1)
0y 00vv vvvv vvvv vvvv vvmm mmmm mmmm mmmm right shifted twice (>> 2)
...
0y 0000 0000 0000 0000 vvvv vvvv vvvv vvvv right shifted sixteen times (>> 16)
LPARAM
定义为指针的大小,因此它将映射到托管代码中的
IntPtr
。因为我们只使用LPRAM的低32位,所以我们需要切掉高32位。我们可以强制转换为
int
来执行此操作,但如果您使用
选中的
算法运行,则会导致
溢出异常。相反,我们将
IntPtr
转换为
long
(在32位机器上,它将为零填充),然后转换为
int
(它将截断)

如果我们不将
IntPtr
调整为
Int32
,则如果应用程序发送的消息的高位设置为
lparam>>16
,则可能会出现异常

IntPtr lparam = /* comes from WndProc */;
Int32 lparam32 = unchecked((int)(long)lparam);

Int16 lowWord = lparam32 & 0xffff;
Int16 highWord = lparam32 >> 16;
也就是说,这里有一个C#热键监听器的完整实现,我不记得在哪里找到的。如果有人对此有归属,请让我知道,或者编辑这篇文章列出原作者

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public sealed class KeyboardHook : IDisposable
{
    private int _currentId;
    private Window _window;

    public event EventHandler<KeyPressedEventArgs> KeyPressed;

    public KeyboardHook()
    {
        EventHandler<KeyPressedEventArgs> handler = null;
        this._window = new Window();
        if (handler == null)
        {
            handler = delegate (object sender, KeyPressedEventArgs args) {
                if (this.KeyPressed != null)
                {
                    this.KeyPressed(this, args);
                }
            };
        }
        this._window.KeyPressed += handler;
    }

    public void Dispose()
    {
        for (int i = this._currentId; i > 0; i--)
        {
            UnregisterHotKey(this._window.Handle, i);
        }
        this._window.Dispose();
    }

    public void RegisterHotKey(ModifierKeys modifier, Keys key)
    {
        this._currentId++;
        if (!RegisterHotKey(this._window.Handle, this._currentId, (uint) modifier, (uint) key))
        {
            throw new InvalidOperationException("Couldn’t register the hot key.");
        }
    }

    [DllImport("user32.dll")]
    private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
    [DllImport("user32.dll")]
    private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

    private class Window : NativeWindow, IDisposable
    {
        private static int WM_HOTKEY = 0x312;

        public event EventHandler<KeyPressedEventArgs> KeyPressed;

        public Window()
        {
            this.CreateHandle(new CreateParams());
        }

        public void Dispose()
        {
            this.DestroyHandle();
        }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            if (m.Msg == WM_HOTKEY)
            {
                Keys key = ((Keys) (((int) m.LParam) >> 0x10)) & Keys.KeyCode;
                ModifierKeys modifier = ((ModifierKeys) ((int) m.LParam)) & ((ModifierKeys) 0xffff);
                if (this.KeyPressed != null)
                {
                    this.KeyPressed(this, new KeyPressedEventArgs(modifier, key));
                }
            }
        }
    }
}
使用系统;
使用System.Runtime.CompilerServices;
使用System.Runtime.InteropServices;
使用System.Windows.Forms;
公共印章c