Click here to Skip to main content
15,890,043 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi everyone
I am having a problem with my win32 wrapper class in c++
here is my code

Display.h
C++
#pragma once
#include <Windows.h>
class Display
{
private:
	char* mWindowTitle;
	WNDCLASSEX mWndClass;
	HWND mHwnd;
	MSG mMsg;
	int mWidth;
	int mHeight;
public:
	Display(int width, int height, char* windowtitle, WNDPROC messagefunc, HINSTANCE hinst);
	~Display(void);
	bool InitializeWindow();
	HWND GetWindowHandle();
	MSG GetMessageHandler();
};


Display.cpp

C++
#include "display.h"

Display::Display(int width, int height,char* windowtitle, WNDPROC messagefunc, HINSTANCE hinst)
{
	mWindowTitle = windowtitle;
	mWidth = width;
	mHeight = height;
	mHwnd = 0;

	//Step 1 register the window class
	mWndClass.cbSize = sizeof(WNDCLASSEX); //the size of the structure
	mWndClass.style = 0; //Style of the class
	mWndClass.lpfnWndProc = messagefunc; // function pointer to the callback function
	mWndClass.cbClsExtra = 0;
	mWndClass.cbWndExtra = 0;
	mWndClass.hIcon = LoadIcon(hinst, IDI_APPLICATION);
	mWndClass.hCursor = LoadCursor(hinst,IDC_ARROW);
	mWndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	mWndClass.lpszClassName = "EngineGameWindow";
	mWndClass.lpszMenuName = NULL;
	mWndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	mWndClass.hInstance =  hinst;
}

Display::~Display(void)
{
}

bool Display::InitializeWindow()
{
	if(!RegisterClassEx(&mWndClass))
		MessageBox(NULL,"Sorry could not register window class",
						"Window Registration Error", MB_ICONEXCLAMATION | MB_OK);

	//Step 2 creating the window
	mHwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"EngineGameWindow", mWindowTitle,
		WS_OVERLAPPEDWINDOW,GetSystemMetrics(SM_CXSCREEN)/4,
							GetSystemMetrics(SM_CYSCREEN)/8, 
							mWidth, mHeight,NULL,NULL,mWndClass.hInstance,NULL);
	if(mHwnd == NULL)
		MessageBox(mHwnd,"Window not created","Window Creation Error",MB_ICONEXCLAMATION | MB_OK);

	return true;
}

HWND Display::GetWindowHandle()
{
	return mHwnd;
}

MSG Display::GetMessageHandler()
{
	return mMsg;
}



main.cpp

C++
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
	if(msg == WM_CHAR && wparam == VK_ESCAPE)
	{
		PostQuitMessage(0);
		return 0;
	}
	switch(msg)
	{
	case WM_CLOSE: //when the window is to be closed
		//close the window 
		DestroyWindow(hwnd);
		break;
	case WM_DESTROY: // When the entire window class is destroyed
		// 
		PostQuitMessage(0);
		break;
	case WM_PAINT:
		ValidateRect(hwnd, 0);
		break;
	default:
		return DefWindowProc(hwnd,msg,wparam,lparam);
	}
	return DefWindowProc(hwnd, msg, wparam, lparam);
}

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hPrevinstance, LPSTR lpcmdline, int ncmdshow)
{
	Display display = Display(800, 600, "Engine",WndProc,hinst);
	if(!display.InitializeWindow())
		return 0;

	Directx9Api api = Directx9Api();
	if(!api.InitializeApi())
		return 0;

	ShowWindow(display.GetWindowHandle(), SW_SHOW);
	UpdateWindow(display.GetWindowHandle());

	//Step 3 the Message loop
	while (GetMessage(&display.GetMessageHandler(),display.GetWindowHandle(),0,0) > 0)
	{
		TranslateMessage(&(display.GetMessageHandler()));
		DispatchMessage(&(display.GetMessageHandler()));
	}
	return 0;
}


When i create a window from the class i cant interact with it that is, i cant close, minimize or maximize it. But when i create the window without it in a class, that is when i do everything in the main function like this

C++
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprevinst,LPSTR lpcmdline, int ncmdshow)
{
	WNDCLASSEX wndclassex;
	HWND hwnd;
	MSG msg;

	//Step 1 register the window class
	wndclassex.cbSize = sizeof(WNDCLASSEX); //the size of the structure
	wndclassex.style = CS_DROPSHADOW; //Style of the class
	wndclassex.lpfnWndProc = WndProc; // function pointer to the callback function
	wndclassex.cbClsExtra = 0;
	wndclassex.cbWndExtra = 0;
	wndclassex.hIcon = LoadIcon(hinst, IDI_APPLICATION);
	wndclassex.hCursor = LoadCursor(hinst,IDC_ARROW);
	wndclassex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
	wndclassex.lpszClassName = wndclassname;
	wndclassex.lpszMenuName = NULL;
	wndclassex.hIconSm = LoadIcon(hinst, IDI_APPLICATION);
	wndclassex.hInstance =  hinst;

	if(!RegisterClassEx(&wndclassex))
	{
		MessageBox(NULL, "Sorry could not register window class",
			"Window Registration Error", MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	//Step 2 creating the window
	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,wndclassname,"A simple window",
		WS_OVERLAPPEDWINDOW,((GetSystemMetrics(SM_CXSCREEN)/2)/2), ((GetSystemMetrics(SM_CYSCREEN)/2)/2), 300, 300,NULL,NULL,hinst,NULL);
	
	if(hwnd == NULL)
	{
		MessageBox(hwnd,"Sorry could not create a window","Window Creation Error",MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	ShowWindow(hwnd, ncmdshow);
	UpdateWindow(hwnd);

	//Step 3 the Message loop
	while (GetMessage(&msg,hwnd,0,0) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);

	}

	return msg.wParam;
}


it works perfectly.Can anyone help me

Thanks in advance.
Posted
Comments
Frankie-C 1-Feb-15 18:39pm    
Have a look to GetMessageHandler() and the use you make of it...

You're returning a new copy of your MSG in GetMessageHandler, change that to return a pointer instead, and it will work.

C++
MSG* Display::GetMessageHandler()
{
    return &mMsg;
}


And then call it like this;
C#
while (GetMessage(display.GetMessageHandler(), display.GetWindowHandle(), 0, 0) > 0)
{
    TranslateMessage((display.GetMessageHandler()));
    DispatchMessage((display.GetMessageHandler()));
}


Hope this helps,
Fredrik
 
Share this answer
 
Comments
Member 10809885 2-Feb-15 9:36am    
Thanks Fredrik. It works perfectly.
Fredrik Bornander 2-Feb-15 10:08am    
Glad I could help.
On a side note, if you're trying to do a win32 game pretty much from scratch (as your code suggests a little bit), check this out; https://handmadehero.org/.
Fredrik has responded in a precise, clear way. I'm going to respond from a different angle.

First, to answer your initial question, consider writing your WinMain like this:

C++
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hPrevinstance, LPSTR lpcmdline, int ncmdshow)
{
        MSG msg = {0};
	Display display = Display(800, 600, "Engine",WndProc,hinst);
	if(!display.InitializeWindow())
		return 0;
 
	Directx9Api api = Directx9Api();
	if(!api.InitializeApi())
		return 0;
 
	ShowWindow(display.GetWindowHandle(), SW_SHOW);
	UpdateWindow(display.GetWindowHandle());
 
	//Step 3 the Message loop
	while ( GetMessage(&msg, display.GetWindowHandle(), 0, 0) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}


The "mMsg" data member in your Display class caught my attention.

C++
class Display
{
private:
	MSG mMsg;


I could not think of a reason for storing the current window message this way. It's passed around by the window procedure so there's no need to save it. It is not unheard of for the window procedure to be called recursively via SendMessage - which might overwrite the mMsg data member and cause confusion for any code depending on it. In short, I suggest avoiding it.

Consider making your WndProc a static member of the Display class.

C++
class Display
{
private:
    static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)


This will give the window procedure access to public and private members of Display.

The string pointer "mWindowTitle" can become a sticky issue.

C++
class Display
{
private:
	char* mWindowTitle;


Consider declaring this as const - with a word of caution in the constructor code comments - or perhaps better - make a copy of the string. Use malloc / free or new / delete or an STL std::string.

Last thing I want to point out is the window class. Consider making "mWndClass" static. If your program will only ever have one Display class, then this doesn't matter so much. If you think you'll have more than one Display instance, make the WNDCLASSEX static and shared across all instances.

Making WNDCLASSEX and WinProc both static yields a simpler constructor:

C++
// Caution: caller must guarantee lifetime of windowtitle exceeds this object.
Display::Display(int width, int height, const char* windowtitle)
{
	mWindowTitle = windowtitle;
	mWidth = width;
	mHeight = height;
	mHwnd = 0;
}


The WNDCLASSEX would of course be initialized elsewhere.

Good luck!
 
Share this answer
 
v2
Comments
merano 4-Feb-15 17:41pm    
There is no need to store mWindowTitle, mWidth and mHeight at all. They can be easy accessed over mHwnd.

For several Windows it would be better to store mHwnd as a vector.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900