呼叫 c++ WndProc 中的虚函数失败

发布于 2024-12-02 22:57:31 字数 1648 浏览 2 评论 0原文

我正在开发一个使用 Windows API 显示图形窗口的程序。下面是我在注册窗口类时作为 WndProc 提供的函数 - 它是类 WindowsWindow 内的静态函数。

#define BTK_DLL_FUNC __dllspec(dllexport)

class AbstractBackend
{
protected:
  bool FatalWarnings;

public:
  AbstractBackend (bool FatalWarnings=false);
  ~AbstractBackend ();

  virtual void StartMainLoop () = 0;
  virtual void QuitMainLoop () = 0;
};

class WindowsBackend : public Base::AbstractBackend
{
public:
  static HINSTANCE hinstance;
  static WindowsBackend* instance;

public:
  BTK_DLL_FUNC WindowsBackend ();
  BTK_DLL_FUNC ~WindowsBackend ();

  BTK_DLL_FUNC void StartMainLoop ();
  BTK_DLL_FUNC void QuitMainLoop ();
};


void WindowsBackend::StartMainLoop ()
{
  MSG Msg;
  while (GetMessage (&Msg, NULL, 0, 0) > 0)
  {
    TranslateMessage (&Msg);
    DispatchMessage (&Msg);
  }
}

void WindowsBackend::QuitMainLoop ()
{
  PostQuitMessage (0); /* Send a WM_QUIT message, to stop the main loop */
}

LRESULT CALLBACK WindowsWindow::WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
  case WM_CREATE:
    break;

  case WM_CLOSE:
    DestroyWindow (hwnd);
    break;

  case WM_DESTROY: /* The window was destroyed */
    {
      WindowsBackend::instance->QuitMainLoop (); /* This doesn't work! */
      break;
    }

  default:
    return DefWindowProc(hwnd, msg, wParam, lParam);
  }
  return 0;
}

现在,这是我不明白的部分 - QuitMainLoop 没有开始,也没有返回(我尝试了调试器,它显示 Quit 函数没有被调用,而且该调用之后的任何行没有被执行)。所以实际上,我的程序在该调用之后就卡住了。

但是,将对自定义退出函数的调用替换为对 PostQuitMessage 的直接调用是可行的。

任何解释和/或解决这个问题的方法(并能够调用虚拟函数)都将受到高度赞赏。

编辑:添加了确切的代码

I'm developing a program that displays graphical windows using the windows API. Below is function I provided as the WndProc when registering the window class - it is a static function inside the class WindowsWindow.

#define BTK_DLL_FUNC __dllspec(dllexport)

class AbstractBackend
{
protected:
  bool FatalWarnings;

public:
  AbstractBackend (bool FatalWarnings=false);
  ~AbstractBackend ();

  virtual void StartMainLoop () = 0;
  virtual void QuitMainLoop () = 0;
};

class WindowsBackend : public Base::AbstractBackend
{
public:
  static HINSTANCE hinstance;
  static WindowsBackend* instance;

public:
  BTK_DLL_FUNC WindowsBackend ();
  BTK_DLL_FUNC ~WindowsBackend ();

  BTK_DLL_FUNC void StartMainLoop ();
  BTK_DLL_FUNC void QuitMainLoop ();
};


void WindowsBackend::StartMainLoop ()
{
  MSG Msg;
  while (GetMessage (&Msg, NULL, 0, 0) > 0)
  {
    TranslateMessage (&Msg);
    DispatchMessage (&Msg);
  }
}

void WindowsBackend::QuitMainLoop ()
{
  PostQuitMessage (0); /* Send a WM_QUIT message, to stop the main loop */
}

LRESULT CALLBACK WindowsWindow::WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
  case WM_CREATE:
    break;

  case WM_CLOSE:
    DestroyWindow (hwnd);
    break;

  case WM_DESTROY: /* The window was destroyed */
    {
      WindowsBackend::instance->QuitMainLoop (); /* This doesn't work! */
      break;
    }

  default:
    return DefWindowProc(hwnd, msg, wParam, lParam);
  }
  return 0;
}

Now, here is the part I don't understand - The QuitMainLoop doesn't begin and it doesn't return (I tried the debugger and it showed that the Quit function isn't being called, and also that any line after that call isn't being executed). So practically, my program gets stuck after that call.

But, replacing the call to the custom quit function with a direct call to PostQuitMessage works.

Any explanations and/or way to get around this (and be able to call a virtual function) would be highly appriciated.

Edit: Added the exact code

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

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

发布评论

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

评论(1

由于您尚未发布我们可以运行来重现问题的完整代码,因此我们必须猜测。

我可以看到对 QuitMainLoop() 的调用失败的唯一方法是 WindowsBackend::instance 是否以某种方式损坏。您是否在调用QuitMainLoop()之前错误地销毁了它?也许存在内存损坏?

我会在调试器的反汇编视图下查看它。这应该告诉您出了什么问题,然后您需要按照线索找出原因。

Since you have not posted full code that we can run to reproduce the problem we have to guess.

The only way that I can see for the call to QuitMainLoop() to fail is if WindowsBackend::instance is somehow corrupted. Have you destroyed it by mistake before calling QuitMainLoop()? Has there been a memory corruption perhaps?

I would look at this under the disassembly view in the debugger. That should tell you what has gone wrong and then you need to follow the clues to find out why.

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