【发布时间】:2019-05-01 06:20:02
【问题描述】:
我正在研究一个派生自 CWnd 的 MFC 类,并在其构造函数中创建一个隐藏窗口。对象本身是在派生的 CWinApp::InitInstance 函数中构造的。
if (
this->CWnd::Create(
nullptr,
nullptr,
WS_DISABLED, // Even disabled it will receive broadcast messages.
{0, 0, 0, 0},
CWnd::GetDesktopWindow(),
fakeWindowId
) == FALSE
)
throw runtime_error{"failed to create window"};
当我在调试版本中运行此代码时,它会触发以下断言:
调试断言失败!
程序:C:\WINDOWS\SYSTEM32\mfc140ud.dll 文件: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp 行:571
有关您的程序如何导致断言失败的信息, 请参阅有关断言的 Visual C++ 文档。
(按重试调试应用程序)
如果我忽略该断言,则代码可以正常工作,并且不会观察到任何不良影响。我该如何处理这个断言?
我也是这样注册窗口的:
BOOL HiddenWindow::PreCreateWindow(CREATESTRUCTW& cs)
{
if ( ! CWnd::PreCreateWindow(cs))
return FALSE;
cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
WNDCLASSEXW wc;
ZeroMemory(&wc, sizeof(WNDCLASSEXW));
wc.cbSize = sizeof(WNDCLASSEXW);
const auto instance{AfxGetInstanceHandle()};
if (GetClassInfoExW(instance, this->className_.c_str(), &wc) == FALSE)
{
wc.lpszClassName = this->className_.c_str();
if ( ! RegisterClassExW(&wc))
{
Logger::Fatal(
"Registering the window for copy data message failed! Messages will not be "
"copied, error code {}.",
GetLastError()
);
return FALSE;
}
}
else
Logger::Debug(
"There is already a window registered under the class name '{}'.",
toString(this->className_)
);
cs.lpszClass = _wcsdup(this->className_.c_str());
return TRUE;
}
【问题讨论】:
-
“按重试调试应用程序” - 这是您在遇到调试断言时所做的第一件事。查看源代码,MFC 需要满足某些先决条件,其中之一是,所讨论的窗口已被子类化。这在运行构造函数时尚未完成。在子类化完成后,您必须将窗口创建推迟到以后。 (子类化是 MFC 用来将其 C++ 类实例附加到本机窗口的工件,将 Windows 消息连接到其作为类成员实现的处理程序。)
-
我已经在调试器中运行它了。 ;) 将窗口创建推迟到构造函数仍然触发相同的断言之后。我将它移到一个名为“create”的函数中,并在构造对象后调用它。
-
@JadziaMD 你需要按照第一条评论的建议去做。如果 MFC 的源代码,Visual Studio 将向您显示带有 ASSERT 的行,这将为您提供有关问题所在的宝贵提示。
-
@Jabberwocky 没有可单击的重试按钮,因为它位于输出窗口中。我在 Visual Studio 调试器中运行它,所以我有中断或继续。单击中断只会转到我的代码。我已经打开了 MFC 文件,但断言对我没有帮助
ASSERT(oldWndProc != NULL); -
另见此类似线程:stackoverflow.com/questions/13370578/… 您的断言也在
_AfxCbtFilterHook函数内。