如何正确销毁窗口?

发布于 2024-08-09 19:20:49 字数 391 浏览 10 评论 0原文

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

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

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

I'm programming a little game, and I set the lpfnWndProc to DefWindowProc
and after that, I made a loop in that way:

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

So how do I handle the Close Window event in that case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

演出会有结束 2024-08-16 19:20:49

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

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

First of all, this is not how you write a message loop: it will take 100% CPU while waiting for messages, and won't remove messages for other windows from the queue. It will also never terminate. See here for an example of a message loop.

About closing windows: DefWindowProc will handle WM_CLOSE automatically and destroy your window. If you want your application to terminate when the window is closed, you need to handle WM_DESTROY and call PostQuitMessage(0) from it. This means you will need your own window procedure instead of DefWindowProc.

夜唯美灬不弃 2024-08-16 19:20:49
  1. 如果您希望 WindowProc 由类处理,您可以执行类似的操作

    类 CWindow 
    {
      静态 LRESULT WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
      { 
        CWindow* 自身;
        if(uMsg == WM_CREATE)
        {
          self = (CWindow*)((LPCREATESTRUCT)lParam)->lplpCreateParams;
        }
        别的
          self = GetWindowLong(hwnd,GWL_USERDATA);
        如果(自我){
          开关(uMsg){
          案例WM_CREATE:
            返回 self->OnCreate(hwnd,(LPCREATESTRUCT)lParam);
          案例 WM_CLOSE:
            self->OnClose();
            返回0;
          // ETC。
          }
        }
        返回 DefWindowProc(hwnd,uMsg,wParam,lParam);
      }
      int OnCreate(HWND hwnd,LPCREATESTRUCT lpcs)
      {
        m_hwnd = hwnd;
        SetWindowLong(m_hwnd,GWL_USERDATA,这个);
        返回0;
      }
    }
    

确保将“this”作为最后一个参数传递给 CreateWindow(Ex) 的操作。

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

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

  1. If you want WindowProc to be handled by a class, you do something like

    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;
      }
    }
    

Making sure of course to pass 'this' as the last parameter to CreateWindow(Ex).

Next, In your message loop, you MUST check for WM_QUIT messages and use that as a cue to exit the loop. Also, NEVER do a filter on hwnd as that will prevent your application loop from dispatching messages for other windows on your thread. And many windows libraries create message windows on threads to facilitate inter process (and thread) comms. If you dont process all windows messages then (a) your game will eventually run out of memory, and (b) the entire system may start to act funny as your application will make IPC messages deadlock, or time out.

Also, WM_CLOSE is (usually) sent via SendMessage, not PostMessage. Sent messages are delivered straight to the window proc and can't be filtered in the app loop.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文