Jump to content
  • Advertisement
Sign in to follow this  
jorelmb

WIN32 wrapper class :)

This topic is 4265 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!