0
votes

I working on an MFC class which derives from CWnd and creates a hidden window in its constructor. The object itself is constructed inside a derived CWinApp::InitInstance function.

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

When I run this code in a debug build it triggers the following assertion:

Debug Assertion Failed!

Program: C:\WINDOWS\SYSTEM32\mfc140ud.dll File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\wincore.cpp Line: 571

For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

If I ignore the assertion, the code works fine and no ill effect is observable. How do I address this assertion?

I'm registering the window as follows as well:

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;
}
1
"Press Retry to debug the application" - that's the first thing you do, whenever you hit a debug assertion. Looking at the source it appears, that MFC requires certain preconditions be met, one of them being, that the window in question has been subclassed. This has not been done when running the constructor. You'll have to postpone window creation to a later point, after subclassing has completed. (Subclassing is an artifact MFC uses to attach its C++ class instances to native windows, wiring up Windows messages to its handlers implemented as class members.) - IInspectable
I'm already running it in the debugger. ;) Postponing the window creation to after the constructor still triggered the same assertion. I moved it to a function called "create" and called it after constructing the object. - JadziaMD
@JadziaMD you need to do what the first comment suggests. Then Visual Studio will show you the line with the ASSERT if the source code of MFC and that will give you a valuable hint about what has gone wrong. - Jabberwocky
@Jabberwocky There's not a retry button to click, since it's in the output window. I'm running it in the Visual Studio debugger, so I have break or continue. Clicking break will only go to my code. I've already opened the MFC file and the assertion doesn't help me ASSERT(oldWndProc != NULL); - JadziaMD
Also see this similar thread: stackoverflow.com/questions/13370578/… Your assertion is also within a _AfxCbtFilterHook func. - Jovibor

1 Answers

-1
votes

So, I was unable to ever figure out what caused the MFC assertion. The solution was to remove the MFC window entirely and replace it with a Win32 window underneath the class, i.e. CreateWindowExW, GetClassinfoExW, and RegisterClassExW.