如何正确销毁窗口?

时间:2009-11-01 10:07:51

标签: c++ winapi window message terminate

我正在编写一个小游戏,我将 lpfnWndProc 设置为 DefWindowProc 然后,我以这种方式做了一个循环:

    MSG lastMessage;
 while (true)
 {
  if (PeekMessage(
   &lastMessage, 
   this->getWindow(), 
   0, 0, 
   PM_REMOVE))
  {
   TranslateMessage(&lastMessage);
   DispatchMessage(&lastMessage);
  }
 }

那么在这种情况下如何处理关闭窗口事件?

2 个答案:

答案 0 :(得分:2)

首先,这不是你编写消息循环的方式:它在等待消息时需要100%的CPU,并且不会从队列中删除其他窗口的消息。它也永远不会终止。有关消息循环的示例,请参阅here

关于关闭窗口:DefWindowProc将自动处理WM_CLOSE并销毁您的窗口。如果您希望应用程序在窗口关闭时终止,则需要处理WM_DESTROY并从中调用PostQuitMessage(0)。这意味着您需要自己的window procedure而不是DefWindowProc

答案 1 :(得分:0)

  1. 如果您希望某个类处理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;
      }
    }
    
  2. 确保当然将'this'作为CreateWindow(Ex)的最后一个参数传递。

    接下来,在您的消息循环中,您必须检查WM_QUIT消息并将其用作提示以退出循环。此外,永远不要对hwnd进行过滤,因为这会阻止您的应用程序循环为您的线程上的其他窗口分派消息。许多Windows库在线程上创建消息窗口以促进进程间(和线程)通信。如果您不处理所有Windows消息,那么(a)您的游戏最终会耗尽内存,并且(b)整个系统可能会开始变得有趣,因为您的应用程序会使IPC消息陷入僵局或超时。

    此外,WM_CLOSE(通常)通过SendMessage发送,而不是PostMessage。已发送的消息将直接传递到窗口过程,无法在应用程序循环中进行过滤。