Home > other >  "Access violation reading location 0xFFFFFFFFFFFFFFFF" Why can't I make an object of
"Access violation reading location 0xFFFFFFFFFFFFFFFF" Why can't I make an object of

Time:01-04

I'm making a library with raw Win32 API. My problem is, when I make an object of my child window classes, I get an error that says:

Access violation reading location 0xFFFFFFFFFFFFFFFF

I have tried many solutions, but they didn't work for me.

Also, I know that I can't access my class members in the HandleMessage() function inside the Text class (one of the child classes) because they're filled with some random garbage. How can I fix this issue?

Here's the Text.h file:

class IText
{
protected:
    virtual void onPaint(Event) = 0;
    virtual void onClick(Event) = 0;
};

class Text : public Component, IText, IEventListener
{
public:
    Text();
    Text(const std::string& text, const Style& style, const handleWindow_t& parent);
    operator const std::string () const;
public:
    const std::wstring& getComponentClassName() const;
    const handleWindow_t& getHandleWindow() const;
public:
    void onPaint(Event e) override;
    void onClick(Event e) override;
public:
    void addEventListener(const std::string& eventType, const std::function<void(Event)>& callbackFn) override;
public:
    static LRESULT CALLBACK HandleMsgSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        Text* self = nullptr;
        if (uMsg == WM_NCCREATE)
        {
            LPCREATESTRUCT pCreate = reinterpret_cast<LPCREATESTRUCT>(lParam);
            self = static_cast<Text*>(pCreate->lpCreateParams);
            self->m_Hwnd = hWnd;
            SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(self));
        }
        else
        {
            self = reinterpret_cast<Text*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
        }
        if (self)
        {
            return self->HandleMessage(uMsg, wParam, lParam);
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }

    LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        Event e;
        e.code = uMsg;
        e.spec = wParam;
        e.data = lParam;
        e.component = m_Hwnd;
        e.target = this;
        switch (uMsg)
        {
            case WM_PAINT:
            {
                onPaint(e);
            }
            return 0;

            case WM_LBUTTONDOWN:
            {
                onClick(e);
            }
            return 0;
        }
        return DefWindowProc(m_Hwnd, uMsg, wParam, lParam);
    }
public:
    handleWindow_t m_Hwnd;
private:
    Style m_Style;
    handleWindow_t m_Parent;
    std::wstring m_Text, m_ClassName = make_ClassName(L"Text");
};

Here's the Text.cpp file:

Text::Text() : m_Style({0}), m_Text(L""), m_Parent(nullptr)
{
}

Text::Text(const std::string& text, const Style& style, const handleWindow_t& parent) : m_Text(to_wstring(text)), m_Style(style), m_Parent(parent)
{
    WNDCLASS wc = { 0 };

    wc.style = CS_VREDRAW | CS_HREDRAW;
    wc.lpfnWndProc = HandleMsgSetup;
    wc.hInstance = GetModuleHandle(nullptr);
    wc.lpszClassName = m_ClassName.c_str();

    if (!RegisterClass(&wc))
        DWORD ret = GetLastError();

    if (!(m_Hwnd = CreateWindowEx(
                    0,
                    m_ClassName.c_str(),
                    L"",
                    WS_CHILD | WS_VISIBLE,
                    m_Style.marginX, m_Style.marginY, m_Style.width, m_Style.height,
                    parent,
                    nullptr,
                    GetModuleHandle(nullptr), this
    )))
        printf("%s", "error\n");
}

Text::operator const std::string () const
{
    return to_string(m_Text);
}

const std::wstring& Text::getComponentClassName() const
{
    return m_ClassName;
}

const handleWindow_t& Text::getHandleWindow() const
{
    return m_Hwnd;
}

void Text::onPaint(Event e)
{
    PAINTSTRUCT ps;
    handleDeviceContext_t hdc = BeginPaint(m_Hwnd, &ps);
    FillRect(hdc, &ps.rcPaint, Brush(m_Style.backgroundColor));
    HFONT font = CreateFontA(20, 0, 0, 0, FW_NORMAL, false, false, false, DEFAULT_CHARSET,
                    0, 0, 0,
                    0, "Sans Serif" // Or Segoe UI
    );
    SelectObject(hdc, font);
    SetTextColor(hdc, m_Style.color);
    if (m_Style.backgroundColor == transparent)
        SetBkMode(hdc, TRANSPARENT);
    else
        SetBkColor(hdc, m_Style.backgroundColor);
    DrawText(hdc, m_Text.c_str(), -1, &ps.rcPaint, DT_NOCLIP);
    EndPaint(m_Hwnd, &ps);
}

void Text::addEventListener(const std::string& eventType, const std::function<void(Event)>& callbackFn)
{
    if (eventType == "click")
        m_ClickCallback = callbackFn;
}

void Text::onClick(Event e)
{
    m_ClickCallback(e);
}

And here's the main.cpp:

void init(handleWindow_t window)
{
    Style txtStyle = { 0 };
    txtStyle.width = 100;
    txtStyle.height = 22;
    txtStyle.color = RGB(0, 100, 255);
    txtStyle.backgroundColor = 0;
    Text text("text", txtStyle, window);
    text.addEventListener("click", [](Event e)
        {
            std::cout << "Clicked\n";
        });
}

int main()
{
    Style appStyle = { 0 };
    appStyle.width = 800;
    appStyle.height = 600;
    appStyle.marginX = 100;
    appStyle.marginY = 100;
    appStyle.backgroundColor = 0xffffff;
    Window window("Sandbox", appStyle);
    window.show();

    init(window);
    while (window.running())
    {

    }
    return 0;
}

CodePudding user response:

The reason why I was getting that error was the that Text object was destructed when init function scope ends and the solution for that is to make pointer to that object so the Text object is not destroyed when the init function returns.

Here's the code

void init(handleWindow_t window)
{
    Style txtStyle = { 0 };
    txtStyle.width = 100;
    txtStyle.height = 22;
    txtStyle.color = RGB(0, 100, 255);
    txtStyle.backgroundColor = 0;
    Text* text = new Text("text", txtStyle, window);
    text->addEventListener("click", [](Event e)
        {
            std::cout << "Clicked\n";
        });
}
  • Related