C++ 关于在没有WndProc的情况下运行win32事件循环的另一种方式的想法?
在处理多线程、回调、win32 api函数和其他麻烦时,我收到了一个idea事件。(呵呵) 如果在注册窗口类时,我没有定义全局(或在设计类时定义静态)回调函数,而是为C++ 关于在没有WndProc的情况下运行win32事件循环的另一种方式的想法?,c++,windows,multithreading,winapi,event-loop,C++,Windows,Multithreading,Winapi,Event Loop,在处理多线程、回调、win32 api函数和其他麻烦时,我收到了一个idea事件。(呵呵) 如果在注册窗口类时,我没有定义全局(或在设计类时定义静态)回调函数,而是为lpfnWndProc分配了DefWindowProc,然后在单独的线程上运行整个事件循环,会怎么样 这样我就不必在遇到这个问题时就进行破解了 主线程继续执行,将您从while循环中解放出来,允许您做任何事情,甚至打开另一个窗口(耶!) “正常”方式: LRESULT回调WndProc(…) { …//处理事件信息 返回DefWin
lpfnWndProc
分配了DefWindowProc
,然后在单独的线程上运行整个事件循环,会怎么样
这样我就不必在遇到这个问题时就进行破解了
主线程继续执行,将您从while循环中解放出来,允许您做任何事情,甚至打开另一个窗口(耶!)
“正常”方式:
LRESULT回调WndProc(…)
{
…//处理事件信息
返回DefWindowProc(…);
}
int回调WinMain(…)
{
…//初始化需要初始化的内容:)
WNDCLASSEX wc;
...
wc.lpfnWndProc=WndProc;
…//注册类、创建窗口等。。。
味精;
while(GetMessage(&msg,0,0)!=0)
{
…//TranslateMessage(&msg)如果您想要/需要它
DispatchMessage(&msg);//将消息分派给WndProc
}
返回静态_cast(msg.wParam);
}
我新发现的很棒的方式:
DWORD WINAPI MyAwesomeEventLoop(void*data)//在类中必须是静态的
{
…//对数据做任何需要的事情
味精;
while(GetMessage(&msg,0,0)!=0)
{
…//TranslateMessage(&msg)如果您想要/需要它
…//处理事件信息
//调用PostQuitMessage(0)以离开循环
}
返回静态_cast(msg.wParam);
}
int回调WndProc(…)
{
...
WNDCLASSEX wc;
...
wc.lpfnWndProc=DefWindowProc;
...
HANDLE-threadHandle=0;
//在类中实现时,使用“this”作为第四个参数
threadHandle=CreateThread(0,0,MyAwesomeEventLoop,0,0);
…//你现在可以随心所欲了!:)
//等待线程完成
//希望是因为调用了PostQuitMessage(0)
WaitForSingleObject(线程句柄,无限);
DWORD返回值=0;
GetExitCodeThread(threadHandle和returnValue);
闭柄(螺纹柄);
...
返回静态_cast(返回值);
}
你们觉得怎么样?这并不能给你们带来任何好处,除非现在在通用事件循环中有特定于窗口类的事件处理代码,这很难看。如果需要后台工作,请使用辅助线程。将GUI和事件反应器保留在主线程中,并使用文档中描述的回调
如果您有一个实例处理windows的类,则即使在单线程代码中,也不应将其设置为全局的(否则您将在将来遭受痛苦的重构)。获取MSDN上的消息文档:
阅读第一句话:“从调用线程的消息队列中检索消息。”
窗口的消息队列绑定到创建它的线程。由于您在主线程上创建了窗口,因此在新线程上运行的事件循环将不会收到该窗口的任何消息。如果要在另一个线程上运行事件循环,则需要先创建线程,然后在该线程上创建窗口。例如,它们是全局的。为什么泛型事件循环难看?@acpluspluscoder:包含非泛型代码的泛型事件循环难看。如果它们不是全局性的,那么您使用的是(Get/Set)WindowLongPtr
,所以我不明白您所说的“我不必绕过这个问题”
是什么意思。好主意应该被执行,而不是被批评。您可能已经了解了有关Windows体系结构的一些重要内容,消息队列具有线程关联性。您的GetMessage()调用从未收到消息。这些类型的querstiosn实际上不适合StackOverflow。试试吧。投票赞成使用while
LRESULT CALLBACK WndProc(...)
{
... // process event information
return DefWindowProc(...);
}
int CALLBACK WinMain(...)
{
... // initialize whatever needs initializing :)
WNDCLASSEX wc;
...
wc.lpfnWndProc = WndProc;
... // register the class, create the window, etc...
MSG msg;
while(GetMessage(&msg, 0, 0, 0) != 0)
{
... // TranslateMessage(&msg) if you want/need it
DispatchMessage(&msg); // dispatches the message to WndProc
}
return static_cast<int>(msg.wParam);
}
DWORD WINAPI MyAwesomeEventLoop(void* data) // must be static in a class
{
... // do whatever you need with the data
MSG msg;
while(GetMessage(&msg, 0, 0, 0) != 0)
{
... // TranslateMessage(&msg) if you want/need it
... // process event information
// call PostQuitMessage(0) to leave the loop
}
return static_cast<DWORD>(msg.wParam);
}
int CALLBACK WndProc(...)
{
...
WNDCLASSEX wc;
...
wc.lpfnWndProc = DefWindowProc;
...
HANDLE threadHandle = 0;
// use "this" as the 4th parameter when implementing in a class
threadHandle = CreateThread(0, 0, MyAwesomeEventLoop, 0, 0, 0);
... // you are now free to do whatever you want! :)
// waits untill the thread finishes
// hopefully because PostQuitMessage(0) was called
WaitForSingleObject(threadHandle, INFINITE);
DWORD returnValue = 0;
GetExitCodeThread(threadHandle, &returnValue);
CloseHandle(threadHandle);
...
return static_cast<int>(returnValue);
}