'Win32 window instances behaving differently

I have created a window class using the win32 api. It creates a window, passing in this as a parameter so that I can create and grab the object instance inside the static window proc and pass this off to a non-static window proc. But this is leading to some issues with multiple instances of the class stored in a vector.

  • With 1 instance everything works. The window is create, messages are handle and once the window is closed it is deleted from the vector.
  • With 2 instance, the window that was created second is deleted as intended when closed. But the window that was made first, while going through the same WM_CLOSE message and setting the variable that tracks if the window has been closed that the second window did, doesn't maintain the changes once it leaves the window procedure. Almost as if the window it is changing is a different instance. If this is the case I don't know who that is happening as it should be getting a pointer to it's own instance and calling that instance.
  • With 3 or more instances it gets even weirder. Just like with 2 windows, the window that was most recently created closes and is deleted as intended. But after that the behaviour is seemingly random. Sometimes closing the additional windows will behave like it does with 2 instances, where the values are updated inside the window proc but change back once leaving it. And then other times closing the additional windows can cause it to throw an exception in RtlRegisterSecureMemoryCacheCallback which I have no idea what it is or why it is not guaranteed to throw the exception.

My assumption is that I have done something wrong with the Win32 API and setting up the Window Procedure that means the behaviour is not as intended, but everything I have tried so far hasn't solved my issues. Any advice on this would be appreciated.

My code:

// Window.cpp

auto Window::InitialiseWindow() -> void
{
    m_instance = GetModuleHandleW(0);

    WNDCLASSEX wc = { };
    if (!GetClassInfoExW(m_instance, TEXT("WindowsWindow"), &wc))
    {
        wc.cbSize = sizeof (wc);
        wc.style = 0;
        wc.lpfnWndProc = StaticWindowProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = m_instance;
        wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wc.hCursor = LoadCursor (NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wc.lpszMenuName = NULL;
        wc.lpszClassName = TEXT("WindowsWindow");
        wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);

        if (!RegisterClassExW(&wc)) 
        {
            std::cout << "Failed to register class\n";
            return;
        }
    }

    SetLastError(0);
    m_handle = CreateWindowExW(WS_EX_LEFT, TEXT("WindowsWindow"), TEXT("Test Window"), WS_OVERLAPPEDWINDOW,
                              CW_USEDEFAULT, CW_USEDEFAULT, m_size.first, m_size.second, NULL, NULL, m_instance, this);
        
    if (!m_handle) 
    {
        std::cout << "Could not create handle\n";
        return;
    }
    ::ShowWindow(m_handle, SW_SHOW);
    ::UpdateWindow(m_handle);
}

auto CALLBACK Window::StaticWindowProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp) -> LRESULT
{ 
    Window* instance_ptr = nullptr;

    if (wm == WM_NCCREATE)
    {
        CREATESTRUCTW* cs = (CREATESTRUCTW*) lp;
        instance_ptr = (Window*) cs->lpCreateParams;
        SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)instance_ptr);
    }
    else 
    {
       instance_ptr = (Window*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
    }
  
    if (instance_ptr)
    {
        return instance_ptr->WindowProc(hwnd, wm, wp, lp);
    }
    return DefWindowProc(hwnd, wm, wp, lp);
}

auto Window::WindowProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp) -> LRESULT
{ 
    switch (wm) 
    {
    case WM_CLOSE:
    {
        m_open = false;
        if(!DestroyWindow(hwnd))
        {
            std::cout << "Failed to destroy Window: " << GetLastError() << "\n";
        }
        break;
    }
    default:
    {
        return DefWindowProc(hwnd, wm, wp, lp);
    }
    }
        return DefWindowProc(hwnd, wm, wp, lp);
}
// AddWindow() & ProcessWindow() function

auto Application::AddWindow() -> void
{
    m_windows.emplace_back(Window());
    m_windows[m_windows.size() - 1].InitialiseWindow();
}

auto Application::ProcessWindows() -> void
{
    std::vector<Window>::iterator it = m_windows.begin();
    size_t count = m_windows.size();
    while(it != m_windows.end())
    {
        if (it->IsOpen() == false)
        {
            it = m_windows.erase(it);
        }
        else
        {
            it->ProcessWindow();
            ++it;
        }
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source