呼叫 c++ WndProc 中的虚函数失败
我正在开发一个使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(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 ifWindowsBackend::instance
is somehow corrupted. Have you destroyed it by mistake before callingQuitMainLoop()
? 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.