WIN32 wrapper class :)

Started by
0 comments, last by mikeman 17 years, 6 months ago
Hi, I just wanted to post this here (I hope this is the right topic). Anyway, I found that sometimes working with Win32 can be a little bit (a bunch!!) like annoying. So I tried to make my own class that managed the main windows things for a game, nothing to "Extravagant". I hope somebody can find it useful, I know I would have some week ago :). So you can use it freely, and don't have to give credit if you don't want to. So here it goes:


//////////////////////////////////////////////////////////////////////////////////////////
// Date: 21/08/2006																		//
// Header file for managing most used Windows functions and aplications.				//
// Version :	WIN  2.5																//
//////////////////////////////////////////////////////////////////////////////////////////

// DEFINES ///////////////////////////////////////////////////////////////////////////////
#ifndef GUARD_WINCLASS_H		// This is for guarding that the header file will not be
#define GUARD_WINCLASS_H		// loaded more than once.

#ifndef WIN32_LEAN_AND_MEAN		// This is for only including most used Windows functions
	#define WIN32_LEAN_AND_MEAN
#endif

#define WINCLASS_VERSION 0x19			// The version number of the class

// MACROS ////////////////////////////////////////////////////////////////////////////////
#define KeyState(vk) ((GetAsyncKeyState(vk) & 0x8000) ? TRUE : FALSE)

// INCLUDES //////////////////////////////////////////////////////////////////////////////
#include <Windows.h>		// Main Windows header file

class WINCLASS{
public:
// PUBLIC METHODS ////////////////////////////////////////////////////////////////////////
		// Puts all the variables to zero values
	WINCLASS();
		// Calls the Release() method
	~WINCLASS();
		// Initializes the class
	BOOL Initialize(BOOL bWindowed,
		CONST CHAR* ClassName,
		CONST CHAR* WinTitle = "Default Window",
		UINT window_width = 800, 
		UINT window_height = 600,
		HINSTANCE hInstance = GetModuleHandle(NULL), 
		LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM) = MsgHandler);
		// Releases the class
	MSG Release();
		// Handles a single message
	BOOL HandleMsg();
		// Returns TRUE if the class is active
	inline BOOL Active();
		// Changes the show mode of the window. (SW_MINIMIZE, SW_MAXIMIZE...)
	void WindowShow(INT Show);
// GET- FUNCTIONS ////////////////////////////////////////////////////////////////////////		
		// Returns the handler for the window
	HWND GetWindow();
		// Returns a copy of the last Msg struct
	MSG GetMsg() const;
		// Returns the X position of the window on the desktop
	UINT GetXPos() const;
		// Returns the Y position of the window on the desktop
	UINT GetYPos() const;
		// Returns the X size of the window
	UINT GetXSize() const;
		// Returns the Y size of the window
	UINT GetYSize() const;
		// Returns the state of the window focus		
	BOOL GetFocus() const;
// OTHER /////////////////////////////////////////////////////////////////////////////////
		// Default MsgHandler for the class
	friend LRESULT CALLBACK MsgHandler(HWND hWindow, UINT Msg, 
										WPARAM wParam, LPARAM lParam);

private:
// PRIVATE METHODS ///////////////////////////////////////////////////////////////////////
		// Creates, fills and registers the WNDCLASSEX to Windows
	BOOL ClassRegister(LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM));
		// Unregisters the WNDCLASSEX from windows
	BOOL ClassUnRegister();
		// Creates a new window with the default settings
	BOOL WinCreate(DWORD dwFlags);
		// Destroys the main window
	BOOL WinDestroy();
		
// PRIVATE VARIABLES /////////////////////////////////////////////////////////////////////
		// Main aplication instance handler
	HINSTANCE m_hMainInstance;
		// Handler to the main window
	HWND m_hMainWindow;
		// Keeps record if the "Class Registration" and the "Window Creation" succeeded
	BOOL m_bClassRegistered, m_bWindowCreated;
		// Keeps record of the focus on the window
	BOOL m_bFocus;
		// Structure for handling the messages
	MSG m_Msg;
		// Integers for keeping record of the window dimensions and position. Only for
		// windowed mode
	UINT m_nYPOS, m_nXPOS, m_nYSIZE, m_nXSIZE;
		// Name of the class and the window
	CHAR* m_sClassName, *m_sWindowTitle;
};


// WinClass REFERENCE CLASS //////////////////////////////////////////////////////////////
static class WINCLASS_REF
{
public:
	// Set the reference
	VOID SetRef(WINCLASS* WinClass)
	{
		m_pWinClass = WinClass;
	}
	// Get the reference
	WINCLASS* GetRef()
	{
		return m_pWinClass;
	}
private:
	// Pointer to the WINCLASS class
	WINCLASS* m_pWinClass;
}DEF_WINCLASS;


//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// IMPLEMENTATION //////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

	// DEFAULT CONSTRUCTOR AND DESTRUCTOR //
	
//////////////////////////////////////////////////////////////////////////////////////////
// WINCLASS : Default constructor.  Sets to zero all the variables of the class.		//
//////////////////////////////////////////////////////////////////////////////////////////
WINCLASS::WINCLASS()
{
	// Zero out all the variables
	m_hMainWindow = NULL;
	m_bClassRegistered = FALSE;
	m_bWindowCreated = FALSE;
	ZeroMemory(&m_Msg, sizeof(MSG));
	m_nYPOS = 20;
	m_nXPOS = 20;
	m_nXSIZE = 320;
	m_nYSIZE = 240;
	m_sClassName = NULL;
	m_sWindowTitle = NULL;


	// Set the reference to the class
	DEF_WINCLASS.SetRef(this);
}

//////////////////////////////////////////////////////////////////////////////////////////
// ~WINCLASS : Default destructor. Calls the Release() method.							//
//////////////////////////////////////////////////////////////////////////////////////////
WINCLASS::~WINCLASS()
{
	// Call the release method 
	Release();

	// Release the char* of the Window title and the class name
	try{
		if (m_sClassName)
			delete [] m_sClassName;
		m_sClassName = NULL;

		if (m_sWindowTitle)
			delete [] m_sWindowTitle;
		m_sWindowTitle = NULL;
	}catch(...){
		MessageBox(NULL, "Error handling the strings, some memory wasn't freed",
					"Release error", MB_OK | MB_ICONSTOP);
		OutputDebugString("***ERROR: releasing the class strings. Memory not freed***\n");
	}
}

	// INITIALIZATION AND RELEASE FUNCTIONS //

//////////////////////////////////////////////////////////////////////////////////////////
// Initialize : Initializes the class and the main window.								//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL WINCLASS::Initialize(BOOL bWindowed,
		    CONST CHAR* ClassName,
			CONST CHAR* WinTitle,
			UINT window_width, 
			UINT window_height,
			HINSTANCE hInstance,
			LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM))
{
	if (Active())	// If the class is already active then release it first
		Release();

	// Make a copy for the ClassName and WindowTitle strings
	// CLASS NAME
	if (m_sClassName)	// Check that is not a valid pointer
		delete [] m_sClassName;	// Delete in case of
	m_sClassName = NULL;

	m_sClassName = new char[strlen(ClassName)+1];	// Reserve the space
	strcpy (m_sClassName, ClassName);				// Copy the string
	
	// WINDOW TITLE
	if (m_sWindowTitle)	// Check that is not a valid pointer
		delete [] m_sWindowTitle;	// Delete in case of
	m_sWindowTitle = NULL;

	m_sWindowTitle = new char[strlen(WinTitle)+1];	// Reserve space
	strcpy(m_sWindowTitle, WinTitle);			// Copy the title
	
	
	// Set the values for the HINSTANCE. It's just in case.
	if (hInstance != NULL)	// This is just for protection :)
		m_hMainInstance = hInstance;
	else
		m_hMainInstance = GetModuleHandle(NULL);

	
	if (!ClassRegister(MessageHandler))	// Registers the class to windows
		return FALSE;

	// Set the values for screen height and width
	m_nXSIZE = window_width;
	m_nYSIZE = window_height;

	DWORD dwFlags = NULL;	// Variable to hold the flags given to the
							// window creation function

	if (bWindowed)	// Check is going to be windowed or full screen
		dwFlags = (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
	else
		dwFlags = (WS_VISIBLE | WS_POPUP);
	
	if (!WinCreate(dwFlags))	// Creates a new window
		return FALSE;

	return TRUE;		// SUCCESS
}

//////////////////////////////////////////////////////////////////////////////////////////
// Release : Releases the window and unregisters the class.								//
//////////////////////////////////////////////////////////////////////////////////////////
MSG WINCLASS::Release()
{
	if (!WinDestroy())	// Destroy the main window
		OutputDebugString("***FAILED: Destroying the window***\n");

	if (!ClassUnRegister())		// Unregister the class from windows
		OutputDebugString("***FAILED: Unregistering WNDCLASSEX***\n");
	
	return GetMsg();	// Return the last message
}

//////////////////////////////////////////////////////////////////////////////////////////
// ClassRegister : Creates, fills and registers the WNDCLASSEX struct on Windows.		//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL WINCLASS::ClassRegister(LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM))
{
	ClassUnRegister();		// If it was registered -> unregister then

	// *** DEBUG OPTION *** //
	// Unregister the class if there's one registered
	// while (UnregisterClass(m_sClassName.c_str(), m_hMainInstance));

	WNDCLASSEX MainClass;	// struct of the instance to register
	ZeroMemory(&MainClass, sizeof(WNDCLASSEX));	// Set to NULL

	MainClass.cbSize			=	sizeof(WNDCLASSEX);	// Size of the structure
	MainClass.style				=	CS_DBLCLKS | CS_OWNDC |		// Style flags
									CS_HREDRAW | CS_VREDRAW;
	MainClass.lpfnWndProc		=	MessageHandler;	// Function pointer to the MsgHandler
	MainClass.cbClsExtra		=	0;
	MainClass.cbWndExtra		=	0;
	MainClass.hInstance			=	m_hMainInstance;	// Handle to the instance handle
	MainClass.hIcon				=	LoadIcon(NULL, IDI_WINLOGO);	// Default icon
	MainClass.hIconSm			=	LoadIcon(NULL, IDI_WINLOGO);	// Default small icon
	MainClass.hCursor			=	LoadCursor(NULL, IDC_ARROW);	// Default pointer
	MainClass.hbrBackground		=	(HBRUSH)GetStockObject(BLACK_BRUSH);
	MainClass.lpszMenuName		=	NULL;	// No menus
	MainClass.lpszClassName		=	m_sClassName;	// Name of the class

	if (!RegisterClassEx(&MainClass))
	{
		OutputDebugString("***Failed to register de WNDCLASSEX struct.***\n");
		MessageBox(NULL, "Failed to register the class on Windows",
			"Initialization error", MB_OK | MB_ICONSTOP | MB_TOPMOST);
		return FALSE;	// Failed to register
	}
	
	m_bClassRegistered = TRUE;	// Class registration succeeded
	return TRUE;
}

//////////////////////////////////////////////////////////////////////////////////////////
// ClassUnRegister : Un-Registers de WNDCLASSEX struct from Windows.					//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL WINCLASS::ClassUnRegister()
{	
	if (m_bClassRegistered)
	{
		BOOL result = UnregisterClass(m_sClassName,m_hMainInstance);
		if (!result)
			return FALSE;	// Failed to un-register
	}

	m_bClassRegistered = FALSE; // Class un-registration succeeded
	return TRUE;
}

//////////////////////////////////////////////////////////////////////////////////////////
// WinCreate : Creates a new window with the default parameters.						//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL WINCLASS::WinCreate(DWORD dwFlags)
{
	if (m_bWindowCreated)	// Destroy the window if one already exists
		WinDestroy();
	
	// Create the extended styles window
	m_hMainWindow = CreateWindowEx(NULL,     //WS_EX_TOPMOST,
								m_sClassName,
								m_sWindowTitle,
								dwFlags,
								m_nXPOS, m_nYPOS,
								m_nXSIZE, m_nYSIZE,
								NULL, 
								NULL,
								m_hMainInstance, 
								NULL);
	
	if (!m_hMainWindow)	// On failure
	{
		DWORD dwERROR = GetLastError();
		OutputDebugString("***Failed to create the (ex)window.***\n ");

		// DEBUG WINDOW, TRY TO CREATE A NON-EXTENDED STYLES WINDOW //////////////////////
		m_hMainWindow = CreateWindow(m_sClassName,
								m_sWindowTitle,
								dwFlags,
								m_nXPOS, m_nYPOS,
								m_nXSIZE, m_nYSIZE,
								NULL,
								NULL,
								m_hMainInstance,
								NULL);

		if (!m_hMainWindow)		// Failed completely. Terminate
		{
			dwERROR = GetLastError();
			OutputDebugString("***FAILED TO CREATE DEBUG WINDOW. TERMINATING.***\n");
			
			// Report the failure to the user
			MessageBox(NULL,
				"Failed to create the window. TERMINATING...",
				"Initialization", MB_OK | MB_ICONSTOP | MB_TOPMOST);

			return FALSE;	// Failed to create the window
		}
	}

	HandleMsg();	// Handle the WM_CREATE msg
	m_bWindowCreated = TRUE;	// Set the flag to true
	return TRUE;
}

//////////////////////////////////////////////////////////////////////////////////////////
// WinDestroy : Destroys the main window.												//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL WINCLASS::WinDestroy()
{
	if (m_bWindowCreated)	// Check if the window was created
		DestroyWindow(m_hMainWindow);	// Destroy the window
	
	m_bWindowCreated = FALSE;
	return TRUE;
}

	// MESSAGE HANDLING //

//////////////////////////////////////////////////////////////////////////////////////////
// HandleMsg : Handles a single message from the queve.									//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL WINCLASS::HandleMsg()
{
	if (PeekMessage(&m_Msg, m_hMainWindow, 0, 0, PM_REMOVE))	// Get a message from the
	{															// queve.
		if (m_Msg.message == WM_QUIT)	// Closes the entire aplication
			Release();

		TranslateMessage(&m_Msg);	// Translate the new message.
		DispatchMessage(&m_Msg);	// Sends the message to the message handler
		return TRUE;
	}
	return FALSE;
}

	// STATE FUNCTIONS //
//////////////////////////////////////////////////////////////////////////////////////////
// Active : Returns true if the class is still active.									//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL WINCLASS::Active()
{
	if (m_bClassRegistered && m_bWindowCreated)	// The class is only active if the
		return TRUE;							// WNDCLASSEX struct is registered to 
												// Windows and there's an active window
	return FALSE;
}

//////////////////////////////////////////////////////////////////////////////////////////
// WindowShow : Changes the display mode (show) of the window. (Minimize, Maximized..)	//
//////////////////////////////////////////////////////////////////////////////////////////
void WINCLASS::WindowShow(INT Show)
{
	// Sets a 
	ShowWindow(m_hMainWindow, Show);
}

	// GET- FUNCTIONS //
//////////////////////////////////////////////////////////////////////////////////////////
// GetMsg : Returns a copy of the m_Msg struct.											//
//////////////////////////////////////////////////////////////////////////////////////////
MSG WINCLASS::GetMsg() const
{
	return m_Msg;
}

//////////////////////////////////////////////////////////////////////////////////////////
// GetWindow : Returns the handle to the main window.									//
//////////////////////////////////////////////////////////////////////////////////////////
HWND WINCLASS::GetWindow()
{
	return m_hMainWindow;
}

//////////////////////////////////////////////////////////////////////////////////////////
// GetXPOS, GetYPOS, GetXSIZE, GetYSIZE : Returns the window size and position.			//
//////////////////////////////////////////////////////////////////////////////////////////
UINT WINCLASS::GetXPos() const
{
	return m_nXPOS;
}
UINT WINCLASS::GetYPos() const
{
	return m_nYPOS;
}
UINT WINCLASS::GetXSize() const
{
	return m_nXSIZE;
}
UINT WINCLASS::GetYSize() const
{
	return m_nYSIZE;
}

//////////////////////////////////////////////////////////////////////////////////////////
// GetFocus : Returns TRUE if the main window is active.								//
//////////////////////////////////////////////////////////////////////////////////////////
BOOL WINCLASS::GetFocus() const
{
	return m_bFocus;
}

//////////////////////////////////////////////////////////////////////////////////////////
// MsgHandler : Default class message handler.											//
//////////////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK MsgHandler(HWND hWindow, UINT Msg, 
						  WPARAM wParam, LPARAM lParam)
{
	// Get the pointer
	WINCLASS* WinClass = DEF_WINCLASS.GetRef();

	switch (Msg){
	case WM_ACTIVATE:		// When the window gains or looses focus
			if(LOWORD(wParam) == WA_INACTIVE)
				WinClass->m_bFocus = FALSE;
			else
				WinClass->m_bFocus = TRUE;
			break;
	case WM_MOVE:		// When the window changes it's position
			WinClass->m_nXPOS = LOWORD(lParam);
			WinClass->m_nYPOS = HIWORD(lParam);
			break;
	case WM_SIZE:		// When the window changes it's dimensions
			WinClass->m_nXSIZE = LOWORD(lParam);
			WinClass->m_nYSIZE = HIWORD(lParam);
			break;
	case WM_PAINT:		// When the window needs repainting
			ValidateRect(WinClass->m_hMainWindow, NULL);
			break;
	case WM_CLOSE:		// When the user want's to close the aplication
			PostQuitMessage(0);		// The user "wants" to quit
			break;
	case WM_DESTROY:	// The main window was destroyed
			PostQuitMessage(0);
			break;
	default:	// Other messages
			return DefWindowProc(hWindow, Msg, wParam, lParam);
	}
	
	return 0;	// Message handled succesful
}
#endif



It includes: - A class for managing Windows basic things - A default Message Proc - "Get" functions. For knowing the window properties (size, position, focus) - "Get" function for retrieving the window handle (HWND). - A message handler (WINCLASS::HandleMsg()) - An Initialize function with default parameters. So you can change only what you want, and let as default the other things. NOTES: - The only thing that changes when initializing as "windowed" true, is that the window is "Overlapped window", or if is false, then it's a "Popup window". - If you want to use another Message Procedure you can add it in the WINCLASS::Initialize(...) function. (It's the last parameter) - There's another class called "WINCLASS_REF". That's only to link the default message proc and the WINCLASS. But in case you need to access the WINCLASS out of it's scope, e.g. you want the HWND in a function (although is not the best practice) you can do DEF_WINCLASS.GetRef()->GetWindow(). As "DEF_WINCLASS" is an static instance of the WINCLASS_REF class. So for example to make a simple application you write:
[source lang = "cpp"]

#include <WinClass.h>

INT WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE hPrevInstance,
				   LPSTR	 sCmdLine,
				   INT		 nShow)
{
	WINCLASS WinClass;
	WinClass.Initialize(TRUE, "Class Name", "Window Title");

	while(WinClass.Active())
	{
		WinClass.HandleMsg();
		if (KeyState(VK_ESCAPE))
			PostQuitMessage(0);
	}

	return (INT)WinClass.Release().wParam;
}




Simple as that!! lease any comments for making this better, are welcome :). And I hope it helps to someone!! [Edited by - jorelmb on March 24, 2007 11:07:19 PM]
------------------------------"Carpe Diem!""Failure is the prequel of success"_.-:Jimbo:-._
Advertisement
Looks good to me. Some things I noticed in a quick look:

1)The name: WINCLASS. First of all, all-capital reminds me of #define constants. And you don't need to put "class" on the end. I think naming the class just "Window" or "Widget" is far better.

2)You don't need an "Initialize" method, that's what constructors are for.

3)For message handling, you use a kind of "global" variable that holds the last WINCLASS created(the WINCLASS_REF). This will not work at all with multiple windows, such as a window and a child window like a button, but there is a way to fix it. Win32 gives you some extra bytes for each window handle where you can store user information, you can use that to store a pointer to the WINCLASS object. In other words, you can associate an HWND with a WINCLASS object. There is an article here, I think by Oluseyi, that addresses those issues.

-EDIT: Here it is:link

Nice work, keep it going!

This topic is closed to new replies.

Advertisement