试图理解c# WinForms WndProc方法在处理热键消息时到底发生了什么

本文关键字:消息 什么 发生了 处理 WinForms 方法 WndProc | 更新日期: 2023-09-27 18:14:39

我一直在做一个c# WinForms应用程序,它使用讨论得很好的GlobalAddAtom和RegisterHotKey PInvoke方法注册几个热键。该程序以最小化模式启动并在系统托盘中运行。每次接收到一个热键消息时,程序捕获关于按下哪个键的数据,并将其交给另一个对象进行处理。这在一段时间内工作得相对良好,但偶尔会出现一些奇怪的行为。比如同一条消息被多次处理,或者一些消息完全丢失。

在添加了一些广泛的日志记录之后,我发现如果用户按住热键组合(例如Win + C)的时间比正常时间长一点,或者只是简单地按住它,那么在消息循环中会收到新的热键消息,而之前的消息还没有完成处理。

现在,在我看来,消息是在UI线程上接收的(即使它是隐藏的),并通过对不同类的实例的阻塞调用来处理。如果这是真的,那么另一条消息如何进入当前正在处理第一条消息的同一函数呢?这就是我对Win32缺乏了解的地方,让我摸不着头脑。

在我看来,第二条消息是在另一个线程上收到的。但如果那是真的那么它调用的是处理类的哪个实例呢?

任何帮助解决这个问题将非常感激!

下面是一个简化的例子。这段代码…

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case MultipleClipboardsDialog.WM_HOTKEY:
            HotKey hotKey = new HotKey(m.LParam);
            Log.Debug("About to process hot key " + hotKey.ToString());
            this.Processor.ProcessHotKey(hotKey);
            Log.Debug("Finished processing hot key " + hotKey.ToString());
            break;
        default:
            base.WndProc(ref m);
            break;
    }
}

…生成如下输出:

About to process hot key Win + C
About to process hot key Win + C
About to process hot key Win + C
Finished processing hot key Win + C

试图理解c# WinForms WndProc方法在处理热键消息时到底发生了什么

您正在寻找的消息仅在按钮被释放时生成。在Windows中设置消息的方式是每次按键最多生成三条消息。启动spy++,看看记事本。您应该能够看到在正常Windows操作期间生成的消息。

你最终会得到KeyDown, KeyPressed和KeyUp消息(或与其相当的东西)。您可能会拦截其中的一个或两个消息(正常操作,并且您会对其进行编码)。您可能还需要查看Ascii和虚拟密钥。