我希望启动一个单独的线程来处理窗口消息(通过阻塞GetMessage循环),但之后仍然在初始线程中创建窗口。
在单独的线程中,一旦启动,我用PM_NOREMOVE调用PeekMessage
以确保存在消息队列(这是必要的吗?),然后是..
AttachThreadInput(initial thread id,GetCurrentThreadId(),true)
..在最终进入消息循环之前
我还没有使用互斥锁或cs来确保及时发生这种情况,但为了简单起见,我只是在我的初始线程中使用Sleep
语句。
无论如何,窗口消息似乎不会被单独的线程截获。
我不确定我是否正确地这样做,并希望得到任何可能的指导。两个线程都在同一个进程中
谢谢大家
答案 0 :(得分:7)
这不是AttachThreadInput
所做的。即使将输入队列附加到另一个线程,Windows仍然具有线程关联。只有该窗口的线程才能从队列中删除给定窗口的队列中的消息。
AttachTheadInput
做的是让两个线程共享一个输入队列。这允许他们查询有关输入状态的信息,并知道另一个线程将为同一查询获得相同的答案。例如,一个线程可以调用GetAsyncKeyState
并知道答案反映了另一个线程的键状态。
它允许两个或多个线程与输入队列具有相同的关系,并且与Windows 3x中的进程具有相同的关系。这就是这个API存在的原因;这样复杂的多进程应用程序就可以从Win 3x移植到Win95 / WinNT。
答案 1 :(得分:2)
这似乎是从主线程启动窗口创建的最佳方式,而在单独的循环线程中处理它们的消息是使用自定义消息,可以将其发送到单独的线程 - 从而允许它创建窗口,但仍然允许从初始线程调用该操作:
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;
...
然而,这确实有以下副作用:
如果这个答案中有任何重大漏洞,或者这似乎是一种可怕的方法,请纠正我。 (这仍然是我的问题,而且我正在努力找到实现这一目标的最佳方法)