Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object oriented c++ win32?

Tags:

c++

winapi

I want to create my own class to handle creating windows and the window procedure but I have noticed that the window procedure has to be static! I'm now wondering whether its possible to make the window procedure object oriented? I have read some tutorials on object oriented windows, but they always make the procedure static -.- whats the use in that? :/

Any links or info on how to get around this problem would be appreciated,

thanks

like image 855
Kaije Avatar asked Aug 01 '10 00:08

Kaije


2 Answers

You can get around that by making the static WndProc delegate everything to the members:

// Forward declarations
class MyWindowClass;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

std::map<HWND, MyWindowClass *> windowMap;

// Your class
class MyWindowClass  {
private:
  HWND m_handle;

  // The member WndProc
  LRESULT MyWndProc(UINT message, WPARAM wParam, LPARAM lParam) { /* ... */ }

public:
  MyWindowClass()
  {
    /* TODO: Create the window here and assign its handle to m_handle */
    /* Pass &WndProc as the pointer to the Window procedure */

    // Register the window
    windowMap[m_handle] = this;
  }
};

// The delegating WndProc
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  std::map<HWND, MyWindowClass *>::iterator it = windowMap.find(hWnd);
  if (it != windowMap.end())
    return it->second->MyWndProc(message, wParam, lParam);
  return 0;
}
like image 44
Karel Petranek Avatar answered Oct 19 '22 14:10

Karel Petranek


The general technique of allowing a window instance to be represented by as class instance is to make use of the SetWindowLongPtr and GetWindowLongPtr to associate your class instance pointer with the window handle. Below is some sample code to get you started. It may not compile without a few tweaks. It's only meant to be a reference.

Personally, I've stopped rolling my own window classes back a few years ago when I discovered ATL's CWindow and CWindowImpl template class. They take care of doing all this mundane coding for you so can focus on just writing methods that handle window messages. See the example code I wrote up here.

Hope this helps.

class CYourWindowClass
{
private:
    HWND m_hwnd;

public:
    LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
            case WM_CREATE: return OnCreate(wParam, lParam);
            case wM_PAINT: return OnPaint(wParam, lParam);
            case WM_DESTROY:
            {
                SetWindowLongPtr(m_hwnd, GWLP_USERDATA, NULL);
                m_hwnd = NULL;
                return 0;
            }
        }
        return DefWindowProc(m_hwnd, uMsg, wParam, lParam);

    }

    CYourWindowClass()
    {
        m_hwnd = NULL;
    }

    ~CYourWindowClass()
    {
        ASSERT(m_hwnd == NULL && "You forgot to destroy your window!");
        if (m_hwnd)
        {
            SetWindowLong(m_hwnd, GWLP_USERDATA, 0);
        }
    }

    bool Create(...) // add whatever parameters you want
    {
        HWND hwnd = CreateWindow("Your Window Class Name", "Your Window title", dwStyle, x, y, width, height, NULL, hMenu, g_hInstance, (LPARAM)this);
        if (hwnd == NULL)
            return false;

        ASSERT(m_hwnd == hwnd);
        return true;
    }


    static LRESULT __stdcall StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        CYourWindowClass* pWindow = (CYourWindowClass*)GetWindowLongPtr(hwnd, GWLP_USERDATA);

        if (uMsg == WM_CREATE)
        {
            pWindow = ((CREATESTRUCT*)lParam)->lpCreateParams;
            SetWindowLongPtr(hwnd, GWLP_USERDATA, (void*)pWindow);
            m_hWnd = hwnd;
        }

        if (pWindow != NULL)
        {
            return pWindow->WndProc(uMsg, wParam, lParam);
        }

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


};
like image 138
selbie Avatar answered Oct 19 '22 15:10

selbie