1

I am having issues with my code. I am making a class to wrap around some WinAPI to create GUIs, however I am having issues when attempting to register the class.

My code:

inline Window::Window(const TCHAR *windowName, const int x, const int y, const int width, const int height, const TCHAR *className) : abstractWindow() {
    Window(0, className, windowName, WS_OVERLAPPEDWINDOW, x, y, width, height, NULL, NULL, NULL, NULL);
}    

Window::Window(const DWORD dwExStyle, const TCHAR *lpClassName, const TCHAR *lpWindowName, const DWORD dwStyle, const int x, const int y, const int nWidth, const int nHeight, const HWND hWndParent, const HMENU hMenu, const HINSTANCE hInstance, const LPVOID lpParam) : abstractWindow() {
    _proc           = (WNDPROC*) &abstractWindow::msgRouter;

    _styleEx        = dwExStyle;
    _className      = (!lpClassName) ? TEXT("MyGuiClass") : lpClassName;
    _windowName     = lpWindowName;
    _style          = dwStyle;
    _x              = x;
    _y              = y;
    _width          = nWidth;
    _height         = nHeight;
    _hwndParent     = hWndParent;
    _hInstance      = (!hInstance) ? ::GetModuleHandle(NULL) : hInstance;
    _hMenu          = hMenu;
    _lpParam        = lpParam;

    _wndClassEx.cbSize          = sizeof(_wndClassEx);
    _wndClassEx.style           = CS_HREDRAW | CS_VREDRAW;
    _wndClassEx.lpfnWndProc     = abstractWindow::msgRouter;
    _wndClassEx.cbClsExtra      = 0;
    _wndClassEx.cbWndExtra      = 0;
    _wndClassEx.hInstance       = _hInstance;
    _wndClassEx.hIcon           = ::LoadIcon(NULL, IDI_APPLICATION);
    _wndClassEx.hCursor         = ::LoadCursor(NULL, IDC_ARROW);
    _wndClassEx.hbrBackground   = (HBRUSH) COLOR_WINDOW;
    _wndClassEx.lpszMenuName    = NULL;
    _wndClassEx.lpszClassName   = _className;
    _wndClassEx.hIconSm         = ::LoadIcon(NULL, IDI_APPLICATION);
}

_wndClassEx is already defined in the class header as of WNDCLASSEX and the register function simply runs RegisterClassEx(&_wndClassEx).

The following are how I call these classes: (However only one is called at a time)

Window gui (TEXT("Title"), 10, 10, 500, 250);
Window gui (0, NULL, TEXT("Title"), WS_OVERLAPPEDWINDOW, 10, 10, 500, 200, NULL, NULL, hInstance, NULL);

The second one works perfectly fine, however when I call the first (shorter parameters, which puts it through to the second) class registration fails. I have completely written the _wndClassEx as well as gone through every single one and modified it to no success. I have gone through with a debugger and everything seems fine. So I have absolutely no idea what to do.

By the way, abstractWindow::msgRouter is static.

Thanks.

Shane
  • 2,007
  • 18
  • 33
  • 1
    Delegating constructors are present in C++11. Prior to that i.e. C++98 (and the version MS VS versions upto 2010) there was no support for your desired behavior. Also, your code doesn't probably do what you think it does -- it creates a temporary `Window` object that is destroyed as soon as you hit the terminating ';'. – dirkgently May 21 '12 at 11:42
  • I have created a similar class for window creation as an answer to a previous question. Take a look and you might find it useful. http://stackoverflow.com/a/1165721/85150 – Indy9000 May 21 '12 at 11:57

2 Answers2

2

The problem is with this constructor:

inline Window::Window(const TCHAR *windowName, const int x, const int y, const int width, const int height, const TCHAR *className) : abstractWindow() {
    Window(0, className, windowName, WS_OVERLAPPEDWINDOW, x, y, width, height, NULL, NULL, NULL, NULL);
}

You can't call a constructor from another constructor like that. What ends up happening is that a temporary object is created and then immediatly discarded. The way to achieve that (this only works if you have a compiler which implements this feature from the new C++11 Standard) is if you say

inline Window::Window(const TCHAR *windowName, const int x, const int y, const int width, const int height, const TCHAR *className) : Window(0, className, windowName, WS_OVERLAPPEDWINDOW, x, y, width, height, NULL, NULL, NULL, NULL) {};

Another way would be to do what @aztaroth said: create a separate method and call it from both constructors (that works even with an older compiler).

BeMFi
  • 71
  • 4
  • Ahh, right, you can do that now. Been a while since I played around with C++. I should probably read up on that newfangled C++11 stuff sometime. ;) – aztaroth May 21 '12 at 11:58
  • Thanks guys, I had this function seperately before however thought it would work with the 'inline' command. – Shane May 21 '12 at 12:41
1

Write a method that initializes the window (basically cut and paste the second constructor), then call it with proper values from both constructors.

aztaroth
  • 979
  • 7
  • 13