【问题标题】:Form WM_KEYDOWN and WM_KEYUP messages aren't captured in WndProc表单 WM_KEYDOWN 和 WM_KEYUP 消息未在 WndProc 中捕获
【发布时间】:2013-12-05 18:44:27
【问题描述】:

未捕获表单 keydown 和 keyup 消息:

public partial class Form1 : Form
{
    const int WM_KEYDOWN = 0x100;
    const int WM_KEYUP = 0x101;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            log("down");
        }
        if (m.Msg == WM_KEYUP)
        {
            log("up");
        }
        base.WndProc(ref m);
    }
}

【问题讨论】:

    标签: c# wndproc windows-messages


    【解决方案1】:

    您应该改写ProcessCmdKey

    本例摘自from this article

    public partial class Form1 : Form, IMessageFilter
    {
        const int WM_KEYDOWN = 0x100;
        const int WM_KEYUP = 0x101;
        const int WM_SYSKEYDOWN = 0x104;
        Keys lastKeyPressed = Keys.None;
        public Form1()
        {
            InitializeComponent();
            Application.AddMessageFilter(this);
            this.FormClosed += (s, e) => Application.RemoveMessageFilter(this);
        }
        public bool PreFilterMessage(ref Message m) 
        {
            if(m.Msg == WM_KEYUP)
            {
                Debug.WriteLine("Filter -> KeyUp LastKeyPressed=" + lastKeyPressed.ToString());
            }
            return false;
        }
    
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if ((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
            {
                lastKeyPressed = keyData;
                switch (keyData)
                {
                    case Keys.Down:
                        Debug.WriteLine("Down Arrow Captured");
                        break;
    
                    case Keys.Up:
                        Debug.WriteLine("Up Arrow Captured");
                        break;
    
                    case Keys.Tab:
                        Debug.WriteLine("Tab Key Captured");
                        break;
    
                    case Keys.Control | Keys.M:
                        Debug.WriteLine("<CTRL> + M Captured");
                        break;
    
                    case Keys.Alt | Keys.Z:
                        Debug.WriteLine("<ALT> + Z Captured");
                        break;
                }
            }
    
            return base.ProcessCmdKey(ref msg, keyData);
        }
                
    

    可能有一种方法可以从传递给 PreFilterMessage 的消息中提取 KeyCode,如this article 中所述

    【讨论】:

    • 它不会捕获 WM_KEYUP 消息并触发键自动重复。
    • 现在不在 PC 附近进行测试。但是你添加 wm-keyup const 了吗?
    • 是的,我添加了它。顺便说一句,许多开发人员抱怨没有 WM_KEYUP 反应,但我还没有看到任何解决方案。
    • 我已经从其他答案中整理了一些代码,您需要按照@HansPassant herehere 的说明实现IMessageFilter。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-23
    • 2012-05-25
    • 2021-12-26
    • 2018-04-30
    • 2017-06-15
    相关资源
    最近更新 更多