我希望启动一个单独的线程来处理窗口消息(通过阻塞的GetMessage循环),但是仍然在初始线程中创build窗口。
在单独的线程中,只要它启动,我就用PM_NOREMOVE调用PeekMessage
来确保消息队列的存在(是否有必要?),然后..
AttachThreadInput(initial thread id,GetCurrentThreadId(),true)
..最后进入消息循环
我还没有使用互斥体或cs来确保这是及时发生的,但是为了简单起见,我仅仅在最初的线程中使用了一个Sleep
语句。
无论如何,窗口消息似乎不被单独的线程拦截。
我有些不确定我是否正确地做了这件事,并且希望得到任何可能的指导。 两个线程都在同一个进程中
谢谢你们
这不是AttachThreadInput
所做的。 即使在将输入队列附加到另一个线程后,Windows仍然具有线程关联。 给定窗口的队列中的消息只能通过该窗口的线程从队列中移除。
AttachTheadInput
所做的是让两个线程共享一个输入队列。 这允许他们查询关于输入状态的信息,并且知道另一个线程将针对相同的查询得到相同的答案。 例如,一个线程可以调用GetAsyncKeyState
并知道答案反映了另一个线程的关键状态。
它允许两个或多个线程与输入队列具有相同的关系,并且与Windows 3x中的进程具有相同的关系。 这是这个API存在的原因; 所以复杂的多进程应用程序可以从Win 3x移植到Win95 / WinNT。
从主线程开始创建窗口是最好的方法,而在单独的循环线程中处理它们的消息是使用自定义消息,可以将消息发送到单独的线程 – 从而允许它创建窗口,但仍然允许从最初的线程调用该动作:
1)分配一个自定义的消息,并创建一个结构来保存窗口初始化参数:
message_create_window = WM_USER + 0; class Message_create_window{ Message_create_window(...); };
2)不是调用CreateWindow
(Ex),而是使用类似于以下的东西,传递相关的窗口创建参数:
PostThreadMessage( thread.id, message_create_window, new Message_create_window(...), 0 );
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; ...
但是,这确实有以下副作用:
如果在这个答案中有任何重大的漏洞,或者这似乎是一个可怕的方法,请纠正我。 (这仍然是我的问题,我试图找到最好的方法来实现这一点)