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;
}