Window Frame causing memory corruption

Started by
2 comments, last by Endurion 10 years, 9 months ago

So as the title says, I get memory corruptions when I create window frames, specificly when I make the frame visible.

Once I make the window visible, either using the ShowWindow function, or setting the WS_VISIBLE style flag, it somehow corrupts memory, and can cause crashes in classes I used before that.

It doesnt seem to have anything to do with the OpenGL context either.

Everything works perfectly right until I make the window visible.

I am no expert in the windows API, so I have no idea what I am doing wrong.

I hope I just forgot to set something somewhere, because this bug has been haunting me for a while.

Or maybe you can give me some tips on tracking down the source of the problem.

Window class code:


#include <set>
#include <Windows.h>

#include <GL/GL.h>
#include <GL/wglext.h>

#include "eventmanager.h"

#include "windowflag.h"
#include "window.h"

using namespace Core;
using namespace Base;
using namespace Gfx;
using namespace Wnd;

struct Window::Window_Impl
{
    Window_Impl(Window* a_Window);
    ~Window_Impl();

    bool CreateFrame(const vector2i& a_Position, const vector2i& a_Size, const char8* a_Caption, uint32 a_Flags);
    bool DestroyFrame();

    bool CreateWindowClass();
    bool DestroyWindowClass();

    bool CreateContext(const GraphicsLibrary& a_GraphicsLibrary);

    bool CreateContextOpenGL2(const GraphicsLibrary& a_GraphicsLibrary);
    bool CreateContextOpenGL3(const GraphicsLibrary& a_GraphicsLibrary);
    bool CreateContextOpenGL4(const GraphicsLibrary& a_GraphicsLibrary);

    bool CreateContextDirectX9(const GraphicsLibrary& a_GraphicsLibrary);
    bool CreateContextDirectX10(const GraphicsLibrary& a_GraphicsLibrary);
    bool CreateContextDirectX11(const GraphicsLibrary& a_GraphicsLibrary);

    static LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

    RECT CalculateFrameRectangle(const vector2i& a_Position, const vector2i& a_Size, uint32 a_Flags) const;

    DWORD GetStyleFromFlags(uint32 a_Flags) const;
    DWORD GetStyleExFromFlags(uint32 a_Flags) const;

    uint32 GetFlagsFromStyle(DWORD a_Style, DWORD a_StyleEx) const;

    HINSTANCE m_HINSTANCE;
    HWND m_HWND;
    HDC m_HDC;
    HGLRC m_HGLRC;
    
    static std::set<HGLRC> m_HGLRCList;

    Window* m_Window;
    char8 m_CaptionBuffer[0xFF];
    GraphicsLibrary m_GraphicsLibrary;

    static uint32 m_WindowCounter;
    static char8* m_WindowClassName;
};

uint32 Window::Window_Impl::m_WindowCounter = 0;
char8* Window::Window_Impl::m_WindowClassName = 0;
std::set<HGLRC> Window::Window_Impl::m_HGLRCList = std::set<HGLRC>();

Window::Window(const vector2i& a_Position, const vector2i& a_Size, const char8* a_Caption, uint32 a_Flags, const GraphicsLibrary& a_GraphicsLibrary)
{
    Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Creating Window...");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating private implementation...");
    m_Impl = new Window_Impl(this);
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Private implementation created.");

    if (!m_Impl->CreateFrame(a_Position, a_Size, a_Caption, a_Flags))
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Failed to create Window.");
        return;
    }

    if (!m_Impl->CreateContext(a_GraphicsLibrary))
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Failed to create Window.");
        return;
    }
    
    Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Window created.");
}

Window::~Window()
{
    Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Destroying Window...");

    m_Impl->DestroyFrame();

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Deleting private implementation...");
    delete m_Impl;
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Private implementation deleted.");
    
    Logger::Log(CORE_WINDOW_CHANNEL, VB_INSTANTIATION, "Window destroyed.");
}

vector2i Window::GetPosition() const
{
    if (m_Impl->m_HWND != NULL)
    {
        POINT point;
        point.x = 0;
        point.y = 0;

        if (!ClientToScreen(m_Impl->m_HWND, &point))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to get Window position.", GetLastError());
            return vector2i();
        }

        return vector2i(point.x, point.y);
    }
    else
    {
        return vector2i();
    }
}

vector2i Window::GetSize() const
{
    if (m_Impl->m_HWND != NULL)
    {
        RECT rect;

        if (!GetClientRect(m_Impl->m_HWND, &rect))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to get Window size.", GetLastError());
            return vector2i();
        }

        return vector2i(rect.right - rect.left, rect.bottom - rect.top);
    }
    else
    {
        return vector2i();
    }
}

const char8* Window::GetCaption() const
{
    if (m_Impl->m_HWND != NULL)
    {
        if (GetWindowText(m_Impl->m_HWND, m_Impl->m_CaptionBuffer, 0xFF) == 0)
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to get Window caption.", GetLastError());
            return 0;
        }

        return m_Impl->m_CaptionBuffer;
    }

    return 0;
}

uint32 Window::GetFlags() const
{
    if (m_Impl->m_HWND != NULL)
    {
        LONG style = GetWindowLong(m_Impl->m_HWND, GWL_STYLE);
        LONG exstyle = GetWindowLong(m_Impl->m_HWND, GWL_EXSTYLE);

        return m_Impl->GetFlagsFromStyle(style, exstyle);
    }
    else
    {
        return 0;
    }
}

const GraphicsLibrary& Window::GetGraphicsLibrary() const
{
    return m_Impl->m_GraphicsLibrary;
}

void Window::SetPosition(const vector2i& a_Position)
{
    if (m_Impl->m_HWND != 0)
    {
        RECT rect = m_Impl->CalculateFrameRectangle(a_Position, GetSize(), GetFlags());

        if (!SetWindowPos(m_Impl->m_HWND, 0, rect.left, rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to set Window size.", GetLastError());
        }
    }
}

void Window::SetSize(const vector2i& a_Size)
{
    if (m_Impl->m_HWND != NULL)
    {
        RECT rect = m_Impl->CalculateFrameRectangle(GetPosition(), a_Size, GetFlags());

        if (!SetWindowPos(m_Impl->m_HWND, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to set Window size.", GetLastError());
        }
    }
}

void Window::SetCaption(const char8* a_Caption)
{
    if (m_Impl->m_HWND != NULL)
    {
        if (!SetWindowText(m_Impl->m_HWND, a_Caption))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to set Window caption.", GetLastError());
        }
    }
}

void Window::SetFlags(uint32 a_Flags)
{
    if (m_Impl->m_HWND != NULL)
    {
        vector2i position = GetPosition();
        vector2i size = GetSize();

        SetWindowLong(m_Impl->m_HWND, GWL_STYLE, m_Impl->GetStyleFromFlags(a_Flags));
        SetWindowLong(m_Impl->m_HWND, GWL_EXSTYLE, m_Impl->GetStyleExFromFlags(a_Flags));

        SetPosition(position);
        SetSize(size);

        ShowWindow(m_Impl->m_HWND, SW_SHOW);
        UpdateWindow(m_Impl->m_HWND);
    }
}

void Window::SetAsRenderTarget()
{
    if (m_Impl->m_HWND == NULL)
    {
        return;
    }

    switch (m_Impl->m_GraphicsLibrary.m_Type)
    {
        case GLT_NONE:
        break;

        case GLT_OPENGL:
        if (!wglMakeCurrent(m_Impl->m_HDC, m_Impl->m_HGLRC))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to set Window as target.", GetLastError());
            return;
        }
        break;

        case GLT_DIRECTX:
        #define CORE_COMPILER_MESSAGE "TODO: SetAsTarget DirectX"
        #include "compilermessage.h"
        break;

        default:
        Logger::Error(CORE_WINDOW_CHANNEL, "Failed to set Window as target", "Unknown or unsupported Graphics Library (%i).", m_Impl->m_GraphicsLibrary.m_Type);
        break;
    }
}

void Window::Update()
{
    if (m_Impl->m_HWND == 0)
    {
        return;
    }

    MSG msg;

    while (PeekMessage(&msg, m_Impl->m_HWND, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return;
}

void Window::SwapBuffers()
{
    switch (m_Impl->m_GraphicsLibrary.m_Type)
    {
        case GLT_NONE:
        break;

        case GLT_OPENGL:
        if (!::SwapBuffers(m_Impl->m_HDC))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to swap buffers.", GetLastError());
            return;
        }
        break;

        case GLT_DIRECTX:
        #define CORE_COMPILER_MESSAGE "TODO: implement SwapBuffers for DirectX"
        #include "compilermessage.h"
        break;

        default:
        Logger::Error(CORE_WINDOW_CHANNEL,  "Failed to swap buffers", "Unknown or unsupported Graphics Library (%i).", m_Impl->m_GraphicsLibrary.m_Type);
        break;
    }
}

Window::Window_Impl::Window_Impl(Window* a_Window):
    m_Window(a_Window),
    m_HWND(NULL)
{
    m_HINSTANCE = GetModuleHandle(NULL);
}

Window::Window_Impl::~Window_Impl()
{

}

bool Window::Window_Impl::CreateFrame(const vector2i& a_Position, const vector2i& a_Size, const char8* a_Caption, uint32 a_Flags)
{
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating Window frame...");

    if (!CreateWindowClass())
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Failed to create Window frame.");
        return false;
    }

    RECT rect = CalculateFrameRectangle(a_Position, a_Size, a_Flags);

    m_HWND = CreateWindowEx(GetStyleExFromFlags(a_Flags), m_WindowClassName, a_Caption, GetStyleFromFlags(a_Flags),
                            rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, m_HINSTANCE, this);

    if (m_HWND == NULL)
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create Windows frame.", GetLastError());
        return false;
    }

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window frame created.");
    
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Getting device context..");
    m_HDC = GetDC(m_HWND);
    if (m_HDC == NULL)
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to get device context.", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Device context received.");
    
    return true;
}

bool Window::Window_Impl::DestroyFrame()
{
    if (m_HWND != NULL)
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Destroying Window frame...");

        if (!DestroyWindow(m_HWND))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to destroy Window frame", GetLastError());
            return false;
        }

        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window frame destroyed.");
    }

    return DestroyWindowClass();
}

bool Window::Window_Impl::CreateWindowClass()
{
    if (m_WindowCounter == 0)
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating Window class...");

        const uint32 classnamesize = strlen("windowclass") + 1;

        m_WindowClassName = new char8[classnamesize];
        strcpy_s(m_WindowClassName, classnamesize, "windowclass");

        WNDCLASSEX windowclass;
        memset(&windowclass, 0, sizeof(WNDCLASSEX));

        windowclass.cbSize        = sizeof(WNDCLASSEX);
        windowclass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_GLOBALCLASS;
        windowclass.lpfnWndProc   = StaticWndProc;
        windowclass.hInstance     = m_HINSTANCE;
        windowclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
        windowclass.lpszClassName = m_WindowClassName;

        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Registering Window class...");
        if (!RegisterClassEx(&windowclass))
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to register Window class", GetLastError());
            Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Failed to create Window class");
            return false;
        }
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window class registered.");

        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window class created.");
    }

    m_WindowCounter++;

    return true;
}

bool Window::Window_Impl::DestroyWindowClass()
{
    m_WindowCounter--;
    bool result = true;

    if (m_WindowCounter == 0)
    {
        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Destroying Window class...");

        Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Unregistering Window class");
        if (UnregisterClass(m_WindowClassName, m_HINSTANCE) == 0)
        {
            Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to unregister Window class.", GetLastError());

            result = false;
        }
        else
        {
            Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window class unregistered.");
        }

        delete[] m_WindowClassName;
        m_WindowClassName = 0;

        if (result)
        {
            Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Window class destroyed.");
            return true;
        }
        else
        {
            Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Failed to destroy Window class.");
            return false;
        }
    }

    return true;
}

bool Window::Window_Impl::CreateContext(const GraphicsLibrary& a_GraphicsLibrary)
{
    switch (a_GraphicsLibrary.m_Type)
    {
        case GLT_NONE:
        return true;

        case GLT_OPENGL:
        switch (a_GraphicsLibrary.m_VersionMajor)
        {
            case 4:
            if (CreateContextOpenGL4(a_GraphicsLibrary))
            {
                return true;
            }
            Logger::Warning(CORE_WINDOW_CHANNEL, "Failed to initialize OpenGL 4.x.", "Failed to initialize OpenGL 4.x. Falling back to OpenGL 3.x.");

            case 3:
            if (CreateContextOpenGL3(a_GraphicsLibrary))
            {
                return true;
            }
            Logger::Warning(CORE_WINDOW_CHANNEL, "Failed to initialize OpenGL 3.x.", "Failed to initialize OpenGL 3.x. Falling back to OpenGL 2.x or lower.");

            case 2:
            case 1:
            case 0:
            return CreateContextOpenGL2(a_GraphicsLibrary);

            default:
            Logger::Error(CORE_WINDOW_CHANNEL, "Failed to create OpenGL context.", "Unknown OpenGL version: %i.%i", a_GraphicsLibrary.m_VersionMajor, a_GraphicsLibrary.m_VersionMinor);
            return false;
        }

        case GLT_DIRECTX:
        switch (a_GraphicsLibrary.m_VersionMajor)
        {
            case 11:
            if (CreateContextDirectX11(a_GraphicsLibrary))
            {
                return true;
            }
            Logger::Warning(CORE_WINDOW_CHANNEL, "Failed to initialize DirectX 11.", "Failed to initialize DirectX 11.x. Falling back to DirectX 10.x.");

            case 10:
            if (CreateContextDirectX10(a_GraphicsLibrary))
            {
                return true;
            }
            Logger::Warning(CORE_WINDOW_CHANNEL, "Failed to initialize DirectX 10.", "Failed to initialize DirectX 10.x. Falling back to DirectX 9.x.");

            case 9:
            return CreateContextDirectX9(a_GraphicsLibrary);

            default:
            Logger::Error(CORE_WINDOW_CHANNEL, "Failed to create DirectX context.", "Unknown DirectX version: %i.%i", a_GraphicsLibrary.m_VersionMajor, a_GraphicsLibrary.m_VersionMinor);
            return false;
        }
        break;

        default:
        Logger::Error(CORE_WINDOW_CHANNEL, "Unknown or unsupported Graphics Library. (%i)", "Failed to create context", a_GraphicsLibrary.m_Type);
        return false;
    }
}

bool Window::Window_Impl::CreateContextOpenGL2(const GraphicsLibrary& a_GraphicsLibrary)
{
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating OpenGL 2.x or lower context...");
    
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Choosing pixel format...");
    PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        24,
        8,
        0,
        PFD_MAIN_PLANE,
        0, 0, 0, 0
    };

    int32 pfn = ChoosePixelFormat(m_HDC, &pfd);
    if (pfn == 0)
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create an OpenGL 2.x or lower context", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Pixel format chosen.");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Setting pixel format...");
    if (!SetPixelFormat(m_HDC, pfn, &pfd))
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create an OpenGL 2.x or lower context", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Pixel format set.");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Creating OpenGL context...");
    m_HGLRC = wglCreateContext(m_HDC);
    if (m_HGLRC == 0)
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create an OpenGL 2.x or lower context", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "OpenGL context created.");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "Making OpenGL context current...");
    if (!wglMakeCurrent(m_HDC, m_HGLRC))
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to create an OpenGL 2.x or lower context", GetLastError());
        return false;
    }
    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "OpenGL made current.");

    Logger::Log(CORE_WINDOW_CHANNEL, VB_OTHER, "OpenGL %i.%i context created.", a_GraphicsLibrary.m_VersionMajor, a_GraphicsLibrary.m_VersionMinor);

    m_GraphicsLibrary = a_GraphicsLibrary;

    if (m_HGLRCList.size() != 0)
    {
        wglShareLists(*(m_HGLRCList.begin()), m_HGLRC);
    }

    m_HGLRCList.insert(m_HGLRC);

    return true;
}

bool Window::Window_Impl::CreateContextOpenGL3(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextOpenGL3"
    #include "compilermessage.h"
    return false;
}

bool Window::Window_Impl::CreateContextOpenGL4(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextOpenGL4"
    #include "compilermessage.h"
    return false;
}

bool Window::Window_Impl::CreateContextDirectX9(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextDirectX9"
    #include "compilermessage.h"
    return false;
}

bool Window::Window_Impl::CreateContextDirectX10(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextDirextX10"
    #include "compilermessage.h"
    return false;
}

bool Window::Window_Impl::CreateContextDirectX11(const GraphicsLibrary& a_GraphicsLibrary)
{
    #define CORE_COMPILER_MESSAGE "TODO: implement Window::Window_Impl::CreateContextDirextX11"
    #include "compilermessage.h"
    return false;
}

LRESULT CALLBACK Window::Window_Impl::StaticWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
    Window_Impl* wnd_impl = NULL;

    if (msg == WM_CREATE)
    {
        wnd_impl = (Window_Impl*)(((LPCREATESTRUCT)lParam)->lpCreateParams);

        #if CORE_PLATFORM_BITS == 32
        SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)wnd_impl);
        #endif

        #if CORE_PLATFORM_BITS == 64
        SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)wnd_impl);
        #endif
    }
    else
    {
        #if CORE_PLATFORM_BITS == 32
        wnd_impl = (Window_Impl*)GetWindowLongPtr(hwnd, GWL_USERDATA);
        #endif

        #if CORE_PLATFORM_BITS == 64
        wnd_impl = (Window_Impl*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
        #endif

        if (!wnd_impl)
        {
            return DefWindowProc(hwnd, msg, wParam, lParam);    
        }
    }

    return wnd_impl->WndProc(hwnd, msg, wParam, lParam);
}

LRESULT CALLBACK Window::Window_Impl::WndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_SIZE:
        EventManager::Event("window", "resize", m_Window);
        break;
        
        case WM_MOVE:
        EventManager::Event("window", "move", m_Window);
        break;

        case WM_CLOSE:
        EventManager::Event("window", "close", m_Window);
        return 0;

        case WM_INPUT:
        EventManager::Event("window", "input", ((HRAWINPUT)lParam));
        break;
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

RECT Window::Window_Impl::CalculateFrameRectangle(const vector2i& a_Position, const vector2i& a_Size, uint32 a_Flags) const
{
    RECT rect;
    rect.left = a_Position.x;
    rect.top = a_Position.y;
    rect.right = a_Position.x + a_Size.x;
    rect.bottom = a_Position.y + a_Size.y;

    if (!AdjustWindowRectEx(&rect, GetStyleFromFlags(a_Flags), false, GetStyleExFromFlags(a_Flags)))
    {
        Logger::ErrorWindows(CORE_WINDOW_CHANNEL, "Failed to adjust window rect.", GetLastError());
    }

    return rect;
}

DWORD Window::Window_Impl::GetStyleFromFlags(uint32 a_Flags) const
{
    DWORD style = WS_VISIBLE;

    if ((a_Flags & WF_NOFRAME) != 0)
    {
        style |= WS_POPUP;
    }

    if ((a_Flags & WF_RESIZE) != 0)
    {
        style |= WS_MAXIMIZEBOX;
        style |= WS_THICKFRAME;
    }

    if ((a_Flags & WF_NOFRAME) == 0)
    {
        style |= WS_CAPTION;

        if ((a_Flags & WF_NOSYSMENU) == 0)
        {
            style |= WS_SYSMENU;
            style |= WS_MINIMIZEBOX;
        }
    }
    
    return style;
}

DWORD Window::Window_Impl::GetStyleExFromFlags(uint32 a_Flags) const
{
    DWORD style = 0;
    
    if ((a_Flags & WF_WINDOWS_TOOL) != 0)
    {
        style |= WS_EX_TOOLWINDOW;
    }

    if ((a_Flags & WF_TOPMOST) != 0)
    {
        style |= WS_EX_TOPMOST;
    }

    return style;
}

uint32 Window::Window_Impl::GetFlagsFromStyle(DWORD a_Style, DWORD a_StyleEx) const
{
    uint32 flags = 0;

    if ((a_Style & WS_THICKFRAME) != 0)
    {
        flags |= WF_RESIZE;
    }

    if ((a_Style & WS_CAPTION) == 0)
    {
        flags |= WF_NOFRAME;
    }

    if ((a_Style & WS_SYSMENU) == 0)
    {
        flags |= WF_NOSYSMENU;
    }

    if ((a_StyleEx & WS_EX_TOOLWINDOW) != 0)
    {
        flags |= WF_WINDOWS_TOOL;
    }

    if ((a_StyleEx & WS_EX_TOPMOST) != 0)
    {
        flags |= WF_TOPMOST;
    }

    return flags;
}

I've had this bug for a while and mostly worked around it, but I really want to get rid of it.

Right now I just do as little as possible before creating the window and then hope it doesn't crash.

Advertisement

Nothing ground breaking stares at me. Could you make a small project exhibiting the problem?

One thing, not the cause of a crash though, in your Update method, put NULL as HWND in PeekMessage, otherwise you won't receive some messages.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

After a lot more searching I finally found the source of the bug.

Apparently, the moment I make the window visible it starts sending messages to StaticWndProc, without me calling PeekMessage.

This in turn starts triggering events (not Windows Events, but my event system), which in turn request information about the window.

But all of this is still happening in the constructor of the window object.

So the pointer to the window which it requests information from has not yet been set.

Then it tries to do things with the invalid window pointer, and voila, memory corruption.

I now simply fixed it with a bool to make sure the constructor has been completed.

I do find it weird though that it didnt crash sooner, because the pointer was set to 0.

Usually accessing 0 immediately results in a crash.

Regarding that zero issue:

It depends what you do with the dereferenced pointer.

Most compilers implement class methods as "normal" methods with an instrinsic "this" parameter that gets passed along. If this way is used, running through a method works, as long as no actual member is touched.

Obviously, you should NOT rely on that :)

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

This topic is closed to new replies.

Advertisement