如何查看在第二个线程中显示的对话框的Windows消息?

4

我使用注册了一个消息过滤器:

Application.AddMessageFilter(m_messageFilter);

使用这个方法,我可以记录用户在应用程序用户界面中进行的所有鼠标点击。

然而,一个对话框在单独的线程上运行,代码类似于:

void Run()
{
    using( MyDialog dialog = new MyDialog() )
    {
        dialog.ShowDialog();
    }
}

Thread thread = new Thread(Run);

我设置的消息过滤器无法查看发送到该窗口的消息。我该如何获取它们(最好不要太过侵入式)?
我尝试重写MyDialog.PreProcessMessage,但是我很困惑为什么这似乎从未被调用。
谢谢。
3个回答

3
几乎所有的应用程序方法,包括AddMessageFilter,在线程上都是特定的。因此,如果您想在其他线程上过滤消息,则必须在该线程上调用AddMessageFilter。
只需将您的Run方法更改为:
void Run()
{
    using( MyDialog dialog = new MyDialog() )
    {
        Application.AddMessageFilter(new MyMessageFilter());
        Application.Run(dialog); 
    }
}

1

我想你应该按照以下方式重写你的代码

void Run()
{
    using( MyDialog dialog = new MyDialog() )
    {
        Application.Run();
        dialog.ShowDialog();
    }
}

或者可能是

Application.Run(dialog);

在使用 { ... } 内部也可以工作

Application.Run() 在当前线程上开始运行标准应用程序消息循环。通常,消息循环仅在主线程中工作。如果没有 Application.Run(),第二个线程中的标准消息循环将不会启动。

这里有一篇文章在单独的线程上创建闪屏窗体,其中使用了类似的技术 - 第二个窗体(SlpashScreen)在另一个线程中启动,并在该第二个线程中调用 Application.Run(splash)。

正如从这篇文章中所了解到的那样,在不同的线程中运行窗体需要开发人员非常小心,关于如何关闭/处理窗体。


1

只是一个猜测,但你可能可以利用volatile关键字,在这里有一个使用易失性布尔值在不同线程的进程之间检查状态的示例

你可能可以调整那种方法来满足你的需求。根据消息是否在第二个对话框中传递而翻转它

{编辑} 关于PreProcessMessage,我认为它仅适用于键盘输入,而不是鼠标。你可能需要重写WndProc来获取这些事件,这很可能是为什么重写的PreProcessMessage没有触发的原因。

祝你好运!


volatile在这里如何有帮助或相关?显然问题是有两个独立的消息泵(主UI线程和第二个UI线程),而过滤器仅添加到主UI线程,并且第二个线程中的消息发送到该线程的消息泵,该泵没有任何过滤器。 - Mehmet Aras

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接