1
\$\begingroup\$

This is the revised version of the Window Creation Wrapper Class. I tried to improve the code due to the remarks of @user1118321 (see posted link) and I hope for further reviews. For instance, you could give advice about using C++11 more strictly. createWindow is now a factory method. For creating a window with prior set up you should use create instead. Furthermore the func pointers are revised, more events deliver a standard behaviour (e.g. onPaint will be called between BeginPaint and EndPaint) and the OpaquePtr struct is now an unique_ptr (copy/move constructor, copy/move assignment operator is also available). Some minor fixes and changes have been made additionally.

XoursWindow.h

#ifndef __XOURSWINDOW_H
#define __XOURSWINDOW_H

#include <Windows.h>
#include <memory>

enum XWINDOW_ERROR {
    XWINDOW_SUCCESS = 1,
    XWINDOW_FAILURE,

    /*  registerWindowClass
    */  //  ERRORS
    XWINDOW_WNDCLASS_ATOM_ALREADY_SET,

    /*  setWindowClassAtom
    */  //  ERRORS
    XWINDOW_SET_WNDCLASSATOM_FAILED,

    /*  createWindow
    */  //  WARNINGS
    XWINDOW_WNDCLASS_ALREADY_EXISTS,

        //  ERRORS
    XWINDOW_WNDCLASS_INCOMPATIBLE,
    XWINDOW_WINDOW_ALREADY_CREATED,
    XWINDOW_CREATING_WINDOW_FAILED
};

#define XWINDOW_USERDATA_OFFSET         4

class XoursWindow {

public:
    XoursWindow ();

    XoursWindow (const XoursWindow&);
    XoursWindow (XoursWindow&&);
    XoursWindow& operator=(const XoursWindow&);
    XoursWindow& operator=(XoursWindow&&);

    virtual ~XoursWindow ();

    void setWindowClassAtom (ATOM);
    ATOM getWindowClassAtom ();

    void create (DWORD, wchar_t*, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, int);
    void create (wchar_t*, int, int, int, int, HINSTANCE, int);
    void create (wchar_t*, HINSTANCE, int);

    static XoursWindow* createWindow (DWORD, WNDCLASSEX*, wchar_t*, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, int);
    static XoursWindow* createWindow (wchar_t*, int, int, int, int, HINSTANCE, int);
    static XoursWindow* createWindow (wchar_t*, HINSTANCE, int);

    int destroy ();

    void setAdditionalData (void*);     // setter for additional window data
    void* getAdditionalData ();         // getter for additional window data

    LRESULT (*onCreate) (HWND, LPCREATESTRUCT);

    LRESULT (*onEraseBkgnd) (HWND, HDC);
    LRESULT (*onPaint) (HWND, HDC, LPPAINTSTRUCT);

    LRESULT (*onMove) (HWND, LPPOINTS);
    LRESULT (*onGetMinMaxInfo) (HWND, LPMINMAXINFO);

    LRESULT (*onSize) (HWND, WPARAM, LPARAM);
    LRESULT (*onCommand) (HWND, WPARAM, LPARAM);
    LRESULT (*onNotify) (HWND, WPARAM, LPARAM);
    LRESULT (*onTimer) (HWND, WPARAM, LPARAM);

    LRESULT (*onClose) (HWND);
    LRESULT (*onDestroy) (HWND);
    LRESULT (*onQuit) (HWND, WPARAM);

    WNDPROC eventHandler;

    HWND getWindowHandle ();
    int getLastError ();

private:
    struct OpaquePtr;
    std::unique_ptr<OpaquePtr> optr;
};

#endif // __XOURSWINDOW_H

XoursWindow.cpp:

#include "header/XoursWindow_OpaquePtr.h"       // contains XoursWindow.h

XoursWindow::XoursWindow (): optr (new OpaquePtr) {
    this->optr->init_helper (*this);
}

XoursWindow::XoursWindow (const XoursWindow& origin) : optr (new OpaquePtr (*(origin).optr)) {
    XoursWindow::OpaquePtr::copy_helper (*this, origin);
}

XoursWindow::XoursWindow (XoursWindow&& origin) : optr (new OpaquePtr (std::move (*(origin).optr))) {
    XoursWindow::OpaquePtr::copy_helper (*this, origin);

    if (this->getWindowHandle () != NULL)
        SetWindowLongPtr (this->getWindowHandle (), XWINDOW_USERDATA_OFFSET, (LONG_PTR) this);

    this->optr->init_helper (origin);   // due to the object has been moved re-initialize origin
}

XoursWindow& XoursWindow::operator=(const XoursWindow& origin)  {
    *optr = *origin.optr;
    XoursWindow::OpaquePtr::copy_helper (*this, origin);

    return *this;
}

XoursWindow& XoursWindow::operator=(XoursWindow&& origin)  {
    *optr = std::move (*origin.optr);
    XoursWindow::OpaquePtr::copy_helper (*this, origin);

    if (this->getWindowHandle () != NULL)
        SetWindowLongPtr (this->getWindowHandle (), XWINDOW_USERDATA_OFFSET, (LONG_PTR) this);

    this->optr->init_helper (origin);   // due to the object has been moved re-initialize origin

    return *this;
}

XoursWindow::~XoursWindow () {
}

void XoursWindow::create (DWORD dwStyleEx, wchar_t* strTitle, DWORD dwStyle, int posX, int posY, int width, int height, HWND hWndParent, HMENU hMenu, HINSTANCE hInst, int cmdShow) {
    this->optr->create_window_helper (*this, dwStyleEx, strTitle, dwStyle, posX, posY, width, height, hWndParent, hMenu, hInst, cmdShow);
}

void XoursWindow::create (wchar_t* strTitle, int posX, int posY, int width, int height, HINSTANCE hInst, int cmdShow) {
    this->optr->create_window_helper (*this, NULL, strTitle, WS_OVERLAPPEDWINDOW, posX, posY, width, height, NULL, NULL, hInst, cmdShow);
}

void XoursWindow::create (wchar_t* strTitle, HINSTANCE hInst, int cmdShow) {
    this->optr->create_window_helper (*this, NULL, strTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, cmdShow);
}

XoursWindow* XoursWindow::createWindow (DWORD dwStyleEx, WNDCLASSEX* wincl, wchar_t* strTitle, DWORD dwStyle, int posX, int posY, int width, int height, HWND hWndParent, HMENU hMenu, HINSTANCE hInst, int cmdShow) {
    XoursWindow *factory = new XoursWindow;

    if (wincl != NULL) {
        wincl->hInstance = hInst;
        factory->optr->register_wndclass_helper (wincl);

        if (factory->optr->classAtom == 0) {
            delete factory;
            return nullptr;
        }
    }

    factory->optr->create_window_helper (*factory, dwStyleEx, strTitle, dwStyle, posX, posY, width, height, hWndParent, hMenu, hInst, cmdShow);
    if (factory->getLastError () == XWINDOW_CREATING_WINDOW_FAILED) {
        delete factory;
        return nullptr;
    }

    return factory;
}

XoursWindow* XoursWindow::createWindow (wchar_t* strTitle, int posX, int posY, int width, int height, HINSTANCE hInst, int cmdShow) {
    return XoursWindow::createWindow (NULL, NULL, strTitle, WS_OVERLAPPEDWINDOW, posX, posY, width, height, NULL, NULL, hInst, cmdShow);
}

XoursWindow* XoursWindow::createWindow (wchar_t* strTitle, HINSTANCE hInst, int cmdShow) {
    return XoursWindow::createWindow (NULL, NULL, strTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, cmdShow);
}

int XoursWindow::destroy () {
    DestroyWindow (this->getWindowHandle ());
    this->optr->init_helper (*this);

    return 0;
}

void XoursWindow::setAdditionalData (void* data) {
    this->optr->windowData = data;
}

void* XoursWindow::getAdditionalData () {
    return this->optr->windowData;
}

HWND XoursWindow::getWindowHandle () {
    return this->optr->window;
}

int XoursWindow::getLastError () {
    return this->optr->xwnd_err;
}

XoursWindow_OpaquePtr.h

#ifndef __XOURSWINDOW_OPAQUEPTR_H
#define __XOURSWINDOW_OPAQUEPTR_H

#include "XoursWindow.h"

struct XoursWindow::OpaquePtr {
    wchar_t className[128];
    ATOM classAtom;

    static unsigned long objectCounter;
    DWORD objectId = 0;
    void* windowData = NULL;

    HWND window = NULL;
    XWINDOW_ERROR xwnd_err = XWINDOW_SUCCESS;

    OpaquePtr () = default;
    OpaquePtr (const OpaquePtr&);
    OpaquePtr (OpaquePtr&&);

    OpaquePtr& operator= (const OpaquePtr&);
    OpaquePtr& operator= (OpaquePtr&&);

    ~OpaquePtr () {};

    static void copy_helper (XoursWindow&, const XoursWindow&);
    void init_helper (XoursWindow&);

    void create_window_helper (XoursWindow&, DWORD, wchar_t*, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, int);

    ATOM register_wndclass_helper (HINSTANCE);          // registers standard class for XOURSWINDOW
    ATOM register_wndclass_helper (WNDCLASSEX*);            // registers custom class with WNDCLASSEX

    static LRESULT CALLBACK initialProc (HWND, UINT, WPARAM, LPARAM);                                   // callback function for window initializing
    static LRESULT CALLBACK messageForwardingProc (HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR);    // subclassing routine for message forwarding to eventProc

    LRESULT CALLBACK eventProc (const XoursWindow&, UINT, WPARAM, LPARAM);                              // intern event handler

    static LRESULT CALLBACK eventHandling (HWND, UINT, WPARAM, LPARAM);                                 // standard event handler, per default: eventHandler = eventHandling

    /* this callback method will be deleted in release version
    let's call it an undocumented possibility to have ultimate freedom */
    static LRESULT CALLBACK preCreationEventHandling (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        return DefWindowProc (hwnd, msg, wParam, lParam);
    };
};

#endif // __XOURSWINDOW_OPAQUEPTR_H

XoursWindow_OpaquePtr.cpp

#include "header/XoursWindow_OpaquePtr.h"
#include <CommCtrl.h>

unsigned long XoursWindow::OpaquePtr::objectCounter = 0;

XoursWindow::OpaquePtr::OpaquePtr (const XoursWindow::OpaquePtr& origin) {
    *this = origin;
}

XoursWindow::OpaquePtr::OpaquePtr (XoursWindow::OpaquePtr&& origin) {
    *this = std::move (origin);
}

XoursWindow::OpaquePtr& XoursWindow::OpaquePtr::operator= (const XoursWindow::OpaquePtr& origin) {
    this->classAtom = origin.classAtom;
    lstrcpy (this->className, origin.className);
    this->windowData = origin.windowData;
    return *this;
}

XoursWindow::OpaquePtr& XoursWindow::OpaquePtr::operator= (XoursWindow::OpaquePtr&& origin) {
    this->classAtom = origin.classAtom;
    lstrcpy (this->className, origin.className);
    this->objectId = origin.objectId;
    this->window = origin.window;
    this->windowData = origin.windowData;

    return *this;
}

void XoursWindow::OpaquePtr::copy_helper (XoursWindow& dest, const XoursWindow& src) {
    dest.onCreate = src.onCreate;
    dest.onPaint = src.onPaint;
    dest.onEraseBkgnd = src.onEraseBkgnd;
    dest.onSize = src.onSize;
    dest.onMove = src.onMove;
    dest.onGetMinMaxInfo = src.onGetMinMaxInfo;
    dest.onCommand = src.onCommand;
    dest.onNotify = src.onNotify;
    dest.onTimer = src.onTimer;
    dest.onClose = src.onClose;
    dest.onDestroy = src.onDestroy;
    dest.onQuit = src.onQuit;
    dest.eventHandler = src.eventHandler;
}

void XoursWindow::OpaquePtr::init_helper (XoursWindow& ownerInstancePtr) {      /* unset object data (window/window class will not be destroyed!) */
    ownerInstancePtr.onCreate = NULL;
    ownerInstancePtr.onPaint = NULL;
    ownerInstancePtr.onEraseBkgnd = NULL;

    ownerInstancePtr.onSize = NULL;
    ownerInstancePtr.onMove = NULL;
    ownerInstancePtr.onGetMinMaxInfo = NULL;

    ownerInstancePtr.onCommand = ownerInstancePtr.onNotify = NULL;
    ownerInstancePtr.onTimer = NULL;

    ownerInstancePtr.onClose = NULL;
    ownerInstancePtr.onDestroy = NULL;
    ownerInstancePtr.onQuit = NULL;

    ownerInstancePtr.eventHandler = XoursWindow::OpaquePtr::eventHandling;

    XoursWindow::OpaquePtr::objectCounter++;  // won't be decremented (currently)
    ownerInstancePtr.optr->objectId = 1000 + XoursWindow::OpaquePtr::objectCounter;
    ownerInstancePtr.optr->windowData = NULL;

    ownerInstancePtr.optr->classAtom = 0;
    memset (ownerInstancePtr.optr->className, 0, sizeof (wchar_t) * 128);
    lstrcpy (ownerInstancePtr.optr->className, L"XoursWindow Standard Window Class\0");

    ownerInstancePtr.optr->window = NULL;
    ownerInstancePtr.optr->xwnd_err = XWINDOW_SUCCESS;
}

void XoursWindow::OpaquePtr::create_window_helper (XoursWindow& ownerInstancePtr, DWORD dwStyleEx, wchar_t* strTitle, DWORD dwStyle, int posX, int posY, int width, int height, HWND hWndParent, HMENU hMenu, HINSTANCE hInst, int cmdShow) {
    ownerInstancePtr.optr->xwnd_err = XWINDOW_WINDOW_ALREADY_CREATED;   /* pre-set error to save a few code lines */

    /* not really neccessary, GetLastError would return ERROR_MOD_NOT_FOUND otherwise */
    if (ownerInstancePtr.optr->window != NULL)
        return;

    /* something to do when this->classAtom hasn't been set yet */
    if (ownerInstancePtr.optr->classAtom == 0) {
        /* try to register a standard window class or fail */
        if (ownerInstancePtr.optr->register_wndclass_helper (hInst) == 0) {
            ownerInstancePtr.optr->xwnd_err = XWINDOW_FAILURE;  /* so it failed */

            /* okay, last chance ... but only when the class has been registered already */
            int lastError = GetLastError ();
            if (lastError == ERROR_CLASS_ALREADY_EXISTS) {
                ownerInstancePtr.optr->xwnd_err = XWINDOW_WNDCLASS_ALREADY_EXISTS;

                /* find window handle for retrieving ATOM */
                HWND tmpWnd = FindWindow (ownerInstancePtr.optr->className, NULL);
                if (tmpWnd == NULL)
                    return;

                if (GetClassLongPtr (tmpWnd, GCL_CBWNDEXTRA) != (XWINDOW_USERDATA_OFFSET + sizeof (XoursWindow*))) {
                    ownerInstancePtr.optr->xwnd_err = XWINDOW_WNDCLASS_INCOMPATIBLE;
                    return;
                }

                /* retrieve ATOM to set classAtom of this class instance */
                ownerInstancePtr.optr->classAtom = (ATOM) GetClassLong (tmpWnd, GCW_ATOM);
                if (ownerInstancePtr.optr->classAtom == 0)
                    return;
            }
            else    /* unexpected error */
                return;
        }
    }

    /* create the window */
    ownerInstancePtr.optr->xwnd_err = XWINDOW_CREATING_WINDOW_FAILED;   /* pre-set error ... again */
    CreateWindowEx (dwStyleEx, MAKEINTATOM (ownerInstancePtr.optr->classAtom), strTitle, dwStyle, posX, posY, width, height, hWndParent, hMenu, hInst, &ownerInstancePtr);
    if (ownerInstancePtr.optr->window != NULL) {        /* this->window should be successfully filled by magic */
        ShowWindow (ownerInstancePtr.optr->window, cmdShow);
        UpdateWindow (ownerInstancePtr.optr->window);

        ownerInstancePtr.optr->xwnd_err = XWINDOW_SUCCESS; /* seems to be successful ... */
    }
    /* ... otherwise end with error set */
}

ATOM XoursWindow::OpaquePtr::register_wndclass_helper (HINSTANCE hInst) {       /* standard window class registration */
    this->xwnd_err = XWINDOW_SUCCESS;
    if (this->classAtom != 0){
        this->xwnd_err = XWINDOW_WNDCLASS_ATOM_ALREADY_SET;
        return 0;
    }

    WNDCLASSEX wincl;
    wincl.hInstance = hInst;
    wincl.lpszClassName = this->className;
    wincl.lpfnWndProc = XoursWindow::OpaquePtr::initialProc;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = XWINDOW_USERDATA_OFFSET + sizeof (XoursWindow*);
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND + 1;

    return (this->classAtom = RegisterClassEx (&wincl));
}

ATOM XoursWindow::OpaquePtr::register_wndclass_helper (WNDCLASSEX* wincl) {     /* register user defined window class (with limits) */
    this->xwnd_err = XWINDOW_SUCCESS;
    if (this->classAtom != 0) {
        this->xwnd_err = XWINDOW_WNDCLASS_ATOM_ALREADY_SET;
        return 0;
    }

    lstrcpy (this->className, wincl->lpszClassName);

    /* force the use of our window callback procedure to ensure magic */
    wincl->lpfnWndProc = XoursWindow::OpaquePtr::initialProc;
    wincl->cbWndExtra = XWINDOW_USERDATA_OFFSET + sizeof (XoursWindow*);
    return (this->classAtom = RegisterClassEx (wincl));
}

LRESULT CALLBACK XoursWindow::OpaquePtr::initialProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    /* prepare magic when non-client area is going to be created */
    if (msg == WM_NCCREATE) {
        /* create param should be filled with this-pointer */
        LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
        void * lpCreateParam = lpcs->lpCreateParams;
        /* get class object .. */
        XoursWindow* xinstance = (XoursWindow*) (lpCreateParam);
        if (xinstance->optr->window != 0)       /* ... or fail */
            return 0;

        /* fill window handle (magic moment) */
        xinstance->optr->window = hwnd;

        /* set instance as user data of the window */
        SetWindowLongPtr (hwnd, XWINDOW_USERDATA_OFFSET, (LONG_PTR) xinstance);
        /* subclass window to allow generic event handling */
        SetWindowSubclass (hwnd, XoursWindow::OpaquePtr::messageForwardingProc, xinstance->optr->objectId, 0);

        /* call the event handler */
        return xinstance->optr->eventProc (*xinstance, msg, wParam, lParam);
    }

    /* other things than creation of non-client area is none of our buisness at this point, but ... */
    /* we call an ugly undocumented hack to allow message handling before CreateWindow returns */
    return XoursWindow::OpaquePtr::preCreationEventHandling (hwnd, msg, wParam, lParam);    /* only called until subclassing was successful */
}

LRESULT CALLBACK XoursWindow::OpaquePtr::messageForwardingProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
    /* prepare for message forwarding and get associated object */
    LONG_PTR lpUserData = GetWindowLongPtr (hwnd, XWINDOW_USERDATA_OFFSET);
    XoursWindow* xinstance = (XoursWindow*) lpUserData;
    if (xinstance == NULL || hwnd != xinstance->optr->window)       /* check if retrieved object is valid and verify the window handle */
        return -1;

    /* call the event handler */
    return xinstance->optr->eventProc (*xinstance, msg, wParam, lParam);
}

LRESULT CALLBACK XoursWindow::OpaquePtr::eventProc (const XoursWindow &ownerInstancePtr, UINT msg, WPARAM wParam, LPARAM lParam) {
    /* let's handle our events */
    switch (msg)
    {
        case WM_CREATE: {
            /* when window is going to be created we have to retrieve the object ... */
            LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam;
            void* lpCreateParam = lpcs->lpCreateParams;
            XoursWindow* xinstance = (XoursWindow*) lpCreateParam;

            /* ... and check for sanity */
            if (xinstance != &ownerInstancePtr)
                return -1;

            if (ownerInstancePtr.onCreate != NULL)
                return ownerInstancePtr.onCreate (this->window, (LPCREATESTRUCT) lParam);

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_PAINT: {
            if (ownerInstancePtr.onPaint != NULL) {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint (this->window, &ps);
                    LRESULT result = ownerInstancePtr.onPaint (this->window, hdc, &ps);
                EndPaint (this->window, &ps);

                return result;
            }
            else
                return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_ERASEBKGND: {
            if (ownerInstancePtr.onEraseBkgnd != NULL)
                return ownerInstancePtr.onEraseBkgnd (this->window, (HDC) wParam);

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_SIZE: {
            if (ownerInstancePtr.onSize != NULL)
                return ownerInstancePtr.onSize (this->window, wParam, lParam);

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_MOVE: {
            if (ownerInstancePtr.onMove != NULL)
                return ownerInstancePtr.onMove (this->window, (LPPOINTS) &MAKEPOINTS (lParam));

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_GETMINMAXINFO: {
            if (ownerInstancePtr.onGetMinMaxInfo != NULL)
                return ownerInstancePtr.onGetMinMaxInfo (this->window, (LPMINMAXINFO) lParam);

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_COMMAND: {
            if (ownerInstancePtr.onCommand != NULL)
                return ownerInstancePtr.onCommand (this->window, wParam, lParam);

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_NOTIFY: {
            if (ownerInstancePtr.onNotify != NULL)
                return ownerInstancePtr.onNotify (this->window, wParam, lParam);

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_TIMER: {
            if (ownerInstancePtr.onTimer != NULL)
                return ownerInstancePtr.onTimer (this->window, wParam, lParam);

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_CLOSE: {
            if (ownerInstancePtr.onClose != NULL)
                return ownerInstancePtr.onClose (this->window);

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_DESTROY: {
            if (ownerInstancePtr.onDestroy != NULL)
                return ownerInstancePtr.onDestroy (this->window);
            else {
                PostQuitMessage (0);
                return 0;
            }

            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;

        case WM_QUIT: {
            if (ownerInstancePtr.onQuit != NULL)            /* call onQuit */
                ownerInstancePtr.onQuit (this->window, wParam);
            else if (ownerInstancePtr.eventHandler != NULL)     /* when onQuit is unset, try to call eventHandling */
                ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);

            /* it's pretty important to remove the subclass properly */
            RemoveWindowSubclass (this->window, XoursWindow::OpaquePtr::messageForwardingProc, this->objectId);
        } break;

        default: {
            return ownerInstancePtr.eventHandler (this->window, msg, wParam, lParam);
        } break;
    }
    return 0;
}

LRESULT CALLBACK XoursWindow::OpaquePtr::eventHandling (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    /* standard event handling means calling DefWindowProc */
    return DefWindowProc (hwnd, msg, wParam, lParam);
}

main.cpp (example)

#include <Windows.h>
#include "XoursWindow/header/XoursWindow.h"

LRESULT destroyEvent (HWND hwnd) {
    ShowWindow (hwnd, SW_HIDE);
    return 0;
}

LRESULT moveEvent (HWND hwnd, LPPOINTS pt) {
    ShowWindow (hwnd, SW_HIDE);
    Sleep (100);
    ShowWindow (hwnd, SW_SHOW);
    return 0;
}

LRESULT closeEvent (HWND hwnd) {
    if (MessageBox (NULL, L"Are you sure?", L"Last chance", MB_YESNO) == IDNO)
        return 0;

    DestroyWindow (hwnd);
    return 0;
}

LRESULT paintEvent (HWND hwnd, HDC hdc, LPPAINTSTRUCT ps) {
    TextOut (hdc, 20, 20, L"Paint event has been triggered.", lstrlen (L"Paint event has been triggered."));
    return 0;
}

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
    wchar_t buf[50];

    lstrcpy (buf, L"XoursWindow Standard Window Class 1\0");
    XoursWindow *window = XoursWindow::createWindow (buf, hThisInstance, SW_SHOW);
    if (window == nullptr)
        return -1;

    window->onPaint = paintEvent;
    window->onDestroy = destroyEvent;

    XoursWindow second (*window);
    second.create (L"second", hThisInstance, SW_SHOW);
    second.onClose = closeEvent;
    second.onDestroy = NULL;        // due to onDestroy has been copied from window we have to reset it here

    window->onMove = moveEvent;

    MSG messages;
    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage (&messages);
        DispatchMessage (&messages);
    }

    return (int) messages.wParam;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.