windows 如何处理来自单独线程的窗口消息?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1964076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:38:56  来源:igfitidea点击:

How can I handle window messages from a separate thread?

windowsmultithreadingwinapi

提问by ProPuke

I wish to launch a separate thread for handling window messages (via a blocking GetMessage loop), but still create the windows in the initial thread, afterward.

我希望启动一个单独的线程来处理窗口消息(通过阻塞 GetMessage 循环),但之后仍然在初始线程中创建窗口。

Within the separate thread, as soon as it launches, I am calling PeekMessagewith PM_NOREMOVE to ensure a message queue exists (is this necessary?), followed by..

在单独的线程中,一旦它启动,我就会调用PeekMessagePM_NOREMOVE 以确保存在消息队列(这是必要的吗?),然后是..

AttachThreadInput(initial thread id,GetCurrentThreadId(),true)

..before finally entering the message loop

..在最终进入消息循环之前

I am not yet using a mutex or cs to ensure this is happening in time, but am merely using a Sleepstatement in my initial thread for the sake of simplicity.

我还没有使用互斥锁或 cs 来确保及时发生这种情况,但Sleep为了简单起见,我只是在我的初始线程中使用了一条语句。

Regardless, window messages do not appear to be intercepted by the separate thread.

无论如何,窗口消息似乎不会被单独的线程拦截。

I am a little unsure as to whether I am doing this correctly, and would appreciate any possible guidance. Both threads are in the same process

我有点不确定我是否正确地做这件事,并希望得到任何可能的指导。两个线程在同一个进程中

Thank you all

谢谢你们

采纳答案by ProPuke

It seems the best way to instigate window creation from the main thread, while having messages for them handled in a separate, looping thread is to use a custom message, that can be sent to the separate thread - Thus allowing it to create the window, but still allowing that action to be invoked from the initial thread:

从主线程发起窗口创建的最佳方法似乎是在单独的循环线程中处理它们的消息时使用自定义消息,该消息可以发送到单独的线程 - 从而允许它创建窗口,但仍然允许从初始线程调用该操作:

1) Allocate a custom message, and create a structure to hold the window initialisation parameters:

1)分配自定义消息,并创建一个结构来保存窗口初始化参数:

message_create_window = WM_USER + 0;
class Message_create_window{
    Message_create_window(...);
};

2) Instead of calling CreateWindow(Ex), use something similiar to the following, passing in the relavant window creation parameters:

2)不要调用CreateWindow(Ex),而是使用类似于以下的东西,传入相关的窗口创建参数:

PostThreadMessage(
    thread.id,
    message_create_window,
    new Message_create_window(...),
    0
);

3) Handle the custom message in the message pump of your ui handling thread, extract the creation parameters, & free afterwards:

3)在你的ui处理线程的消息泵中处理自定义消息,提取创建参数,然后释放:

MSG msg;
GetMessage(&msg,0,0,0);
...
switch(msg->message){
    ...
    case message_create_window:{
        Message_create_window *data=msg->wParam;
        CreateWindowEx(data->...);
        delete data;
    }break;
    ...

This does, however, have the following side-effects:

然而,这确实有以下副作用:

  • The window will be created asynchronously. If it is required that the initial thread block until the window is created (or, indeed, that the window's existence can ever be asserted) then a thread synchronisation tool must be used (such as an event)
  • Care should be taken when interacting with the window (it is a multithreaded application, after all)
  • 窗口将异步创建。如果需要初始线程阻塞直到窗口被创建(或者,实际上,窗口的存在可以被断言),那么必须使用线程同步工具(例如事件)
  • 与窗口交互时要小心(毕竟它是一个多线程应用程序)

If there are any major holes in this answer, or this seems like a terrible approach, please correct me. (This is still my question, & I am trying to find the best way to accomplish this)

如果这个答案有任何重大漏洞,或者这似乎是一个糟糕的方法,请纠正我。(这仍然是我的问题,我正在努力寻找实现这一目标的最佳方法)

回答by John Knoeller

That's not what AttachThreadInputdoes. Even after you attach your input queue to another thread, Windows still have thread affinity. Messages in the queue for a given window can only be removed from the queue by that window's thread.

那不是什么AttachThreadInput。即使将输入队列附加到另一个线程之后,Windows 仍然具有线程关联性。给定窗口的队列中的消息只能由该窗口的线程从队列中删除。

What AttachTheadInputdoes is to make two threads share an input queue. This allows them to query information about the input state and know that the other thread will get the same answer for the same query. For instance, one thread could call GetAsyncKeyStateand know that the answer reflected the key state for the other thread.

什么AttachTheadInput是让两个线程共享一个输入队列。这允许他们查询有关输入状态的信息,并知道另一个线程将获得相同查询的相同答案。例如,一个线程可以调用GetAsyncKeyState并知道答案反映了另一个线程的关键状态。

It allows two or more threads to have the same relationship to the input queue and each other as processes had in Windows 3x. This is the reason that this API exists; so that complex multiprocess applications could be ported from Win 3x to Win95/WinNT.

它允许两个或多个线程与输入队列以及彼此之间的关系与 Windows 3x 中的进程具有相同的关系。这就是这个API存在的原因;这样就可以将复杂的多进程应用程序从 Win 3x 移植到 Win95/WinNT。