Window wrapper issue

Started by
2 comments, last by Aardvajk 15 years, 8 months ago
I haven't been programming for what seems like eons now, so with that in mind, please try and bear with me here. I figured that I would start out with a few simple reusable utility classes, and I had managed to stay out of any real trouble in the design and execution process; until I started work on a Win32 window wrapper. The wrapper class actually 'works' in essence, it just won't forward any of the messages from the static WndProc
Window::MessageRouter()
to the class level WndProc
Window::MessageHandler()
. Through debugging, I've found that it doesn't seem like the MessageRouter is setting the window pointer correctly through the
SetWindowLong
method. As in the last IF-ELSE statement of the routing method, the window pointer always holds a null value. If anyone could please offer some insight as to why the window pointer is never getting set properly, I would very much appreciate it. I am currently stuck on this issue, after I initially ran into the problem, I did some article reading and tutorial searching, including the window wrapper article on GD.net. But I have yet to find anything that helps resolve this issue. Window.h

#ifndef __WINDOW_H__
#define __WINDOW_H__

#include "Common.h"

class Window
{
private:
	HWND mWindow;
	HINSTANCE mInstance;
	DWORD mStyle;
	WCHAR* mClassName;
	WCHAR* mWindowTitle;
	int mWidth, mHeight;

public:
	bool Create();
	void Show();
	void Release();
	virtual LRESULT CALLBACK MessageHandler(HWND Wnd, UINT Msg, WPARAM WParam, LPARAM LParam);
	static LRESULT CALLBACK MessageRouter(HWND Wnd, UINT Msg, WPARAM WParam, LPARAM LParam);

public:
	Window(WCHAR* ClassName, WCHAR* WndTitle, int Width, int Height, DWORD Style, HINSTANCE Instance);
	~Window();

public:
	inline HWND GetWindow() { if(this->mWindow != NULL) return this->mWindow; };
	inline int GetWidth() { return this->mWidth; };
	inline int GetHeight() { return this->mHeight; };
};

#endif // __WINDOW_H__


Window.cpp

#include "Window.h"

//--------------------------------------------------------------------------------------------
Window::Window(WCHAR* ClassName, WCHAR* WndTitle, int Width, int Height, DWORD Style, HINSTANCE Instance)
{
	// Set class member default values.
	this->mClassName = ClassName;
	this->mWindowTitle = WndTitle;
	this->mStyle = Style;
	this->mWidth = Width;
	this->mHeight = Height;
	this->mInstance = Instance;
	this->mWindow = NULL;
}

//--------------------------------------------------------------------------------------------
Window::~Window()
{
	// Call the class release method.
	this->Release();
}

//--------------------------------------------------------------------------------------------
bool Window::Create()
{
	// Create and clear the window class object.
	WNDCLASSEX WndClass;
	ZeroMemory(&WndClass, sizeof(WNDCLASSEX));

	// Fill in the window class data.
	WndClass.cbSize = sizeof(WNDCLASSEX);
	WndClass.style = CS_OWNDC;
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = this->mInstance;
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClass.lpszMenuName = NULL;
	WndClass.lpszClassName = this->mClassName;
	WndClass.lpfnWndProc = MessageRouter;

	// Register the window class object.
	if(RegisterClassEx(&WndClass) == false)
	{
		MessageBox(NULL, L"Window::Create() - Failed to register the window class object.", L"Error!", 0);
		return false;
	}

	// Create the window object.
	this->mWindow = CreateWindow(this->mClassName, this->mWindowTitle, this->mStyle,
									GetSystemMetrics(SM_CXSCREEN) / 2 - (this->mWidth / 2),
									GetSystemMetrics(SM_CYSCREEN) / 2 - (this->mHeight / 2),
									this->mWidth, this->mHeight,
									NULL, NULL, this->mInstance, NULL);

	// Check for success of window creation.
	if(this->mWindow == NULL)
	{
		MessageBox(NULL, L"Window::Create() - Failed to create the window object.", L"Error!", 0);
		return false;
	}

	return true;
}

//--------------------------------------------------------------------------------------------
void Window::Show()
{
	// Check if the window object exists.
	if(this->mWindow == NULL)
	{
		MessageBox(NULL, L"Window::Show() - Failed to find window object.", L"Error!", 0);
		return;
	}

	// Show and update the window.
	ShowWindow(this->mWindow, SW_SHOW);
	UpdateWindow(this->mWindow);
}

//--------------------------------------------------------------------------------------------
void Window::Release()
{
	// Check if the window object exists.
	if(this->mWindow != NULL)
	{
		// Destroy the window object.
		DestroyWindow(this->mWindow);
		this->mWindow = NULL;
	}
}

//--------------------------------------------------------------------------------------------
LRESULT CALLBACK Window::MessageRouter(HWND Wnd, UINT Msg, WPARAM WParam, LPARAM LParam)
{
	// Create a window class pointer object.
	Window* WindowPtr;

	// Check if a window creation message was passed.
	if(Msg == WM_NCCREATE)
	{
		// Set the window pointer object.
		SetWindowLong(Wnd, GWL_USERDATA, (long)(LPCREATESTRUCT(LParam))->lpCreateParams);
	}

	// Get the window pointer object.
	WindowPtr = (Window*)GetWindowLong(Wnd, GWL_USERDATA);

	// Check  if the window pointer object is valid.
	if(WindowPtr != NULL)
	{
		// Process the messages with the window pointer objects handler.
		return WindowPtr->MessageHandler(Wnd, Msg, WParam, LParam);
	}
	else
	{
		// Process the messages with the default window handler.
		return DefWindowProc(Wnd, Msg, WParam, LParam);
	}	
}

//--------------------------------------------------------------------------------------------
LRESULT CALLBACK Window::MessageHandler(HWND Wnd, UINT Msg, WPARAM WParam, LPARAM LParam)
{
	switch(Msg)
	{
	case WM_DESTROY:
		{
			// Post a quit message to the window.
			PostQuitMessage(0);
			return 0;
		}

	default:
		{
			// Process remaining messages with the default window handler.
			return DefWindowProc(Wnd, Msg, WParam, LParam);
		}
	}

	return 0;
}


Advertisement
You need to pass the this pointer as creation parameter data.
Try it with this:

	// Create the window object.	this->mWindow = CreateWindow(this->mClassName, this->mWindowTitle, this->mStyle,									GetSystemMetrics(SM_CXSCREEN) / 2 - (this->mWidth / 2),									GetSystemMetrics(SM_CYSCREEN) / 2 - (this->mHeight / 2),									this->mWidth, this->mHeight,									NULL, NULL, this->mInstance, reinterpret_cast<LPVOID>(this));

Some of the functions you're using there are deprecated, like CreateWindow instead of CreateWindowEx and [Set|Get]WindowLong instead of [Set|Get]WindowLongPtr.
Also, look into initialiser lists for your constructor.
I've set up the same kind of thing. Try passing in 'this' as the last parameter to your CreateWindow() function instead of NULL.

This page on MSDN explains why more thoroughly than I can.

Hope this at least gets you a little further along. If not I can share a few snippets of my code to use as reference if you want.

[Edit]
Too slow
A good article, worth reading.

This topic is closed to new replies.

Advertisement