我正在编写一个小游戏,我将 lpfnWndProc 设置为 DefWindowProc 然后,我以这种方式做了一个循环:
MSG lastMessage;
while (true)
{
if (PeekMessage(
&lastMessage,
this->getWindow(),
0, 0,
PM_REMOVE))
{
TranslateMessage(&lastMessage);
DispatchMessage(&lastMessage);
}
}
那么在这种情况下如何处理关闭窗口事件?
答案 0 :(得分:2)
首先,这不是你编写消息循环的方式:它在等待消息时需要100%的CPU,并且不会从队列中删除其他窗口的消息。它也永远不会终止。有关消息循环的示例,请参阅here。
关于关闭窗口:DefWindowProc
将自动处理WM_CLOSE
并销毁您的窗口。如果您希望应用程序在窗口关闭时终止,则需要处理WM_DESTROY
并从中调用PostQuitMessage(0)
。这意味着您需要自己的window procedure而不是DefWindowProc
。
答案 1 :(得分:0)
如果您希望某个类处理WindowProc,您可以执行类似
的操作class CWindow
{
static LRESULT WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
CWindow* self;
if(uMsg == WM_CREATE)
{
self = (CWindow*)((LPCREATESTRUCT)lParam)->lplpCreateParams;
}
else
self = GetWindowLong(hwnd,GWL_USERDATA);
if(self){
switch(uMsg){
case WM_CREATE:
return self->OnCreate(hwnd,(LPCREATESTRUCT)lParam);
case WM_CLOSE:
self->OnClose();
return 0;
// etc.
}
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
int OnCreate(HWND hwnd,LPCREATESTRUCT lpcs)
{
m_hwnd = hwnd;
SetWindowLong(m_hwnd,GWL_USERDATA,this);
return 0;
}
}
确保当然将'this'作为CreateWindow(Ex)的最后一个参数传递。
接下来,在您的消息循环中,您必须检查WM_QUIT消息并将其用作提示以退出循环。此外,永远不要对hwnd进行过滤,因为这会阻止您的应用程序循环为您的线程上的其他窗口分派消息。许多Windows库在线程上创建消息窗口以促进进程间(和线程)通信。如果您不处理所有Windows消息,那么(a)您的游戏最终会耗尽内存,并且(b)整个系统可能会开始变得有趣,因为您的应用程序会使IPC消息陷入僵局或超时。
此外,WM_CLOSE(通常)通过SendMessage发送,而不是PostMessage。已发送的消息将直接传递到窗口过程,无法在应用程序循环中进行过滤。