Sign in to follow this  
ctaclas

window creation question

Recommended Posts

i've been following "programming role playing games with directx" by jim adams. after covering the main parts of directx, the author shows how he makes a game core, which is an easy to use layer between the directx stuff and the game code. i've been studying it and i kind of like the way he does it, so i'm trying to copy it. i'm not just doing copy and paste because i want to learn stuff. i'm trying to do the system core, which covers all the windows stuff. basically it's a base class for all the windows stuff, you create an derrived class and overload some virtual functions with the stuff you need for your application. only thing is my stuff isn't compiling. it's got something to do with the message processing function. the book i have defines the message function with virtual FAR PASCAL instead of LRESULT CALLBACK. i'm not sure why, but it's not working for me with either one. heres the code i've got:
#include <windows.h>
#ifndef APPLICATION_H
#define APPLICATION_H
class cApplication
{
	private:
		HINSTANCE	m_hInstance;
		HWND		m_hWnd;
	protected:
		char		m_className[50];
		char		m_titleName[50];

		WNDCLASSEX	m_wc;

		DWORD		m_style;
		DWORD		m_xPos;
		DWORD		m_yPos;
		DWORD		m_width;
		DWORD		m_height;
	public:
		cApplication();
		HWND		GetHwnd();
		HINSTANCE	GetHinstance();
		BOOL		Run();
		BOOL		ShowMouse(BOOL Show = TRUE);
		
		virtual FAR PASCAL MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
			{return DefWindowProc(hWnd, uMsg, wParam, lParam);} //this is where the warning comes from
		virtual BOOL Init(){return TRUE;};
		virtual BOOL Shutdown(){return TRUE;};
		virtual BOOL Frame(){return TRUE;};
};
static cApplication *g_pApplication = NULL;
static  long FAR PASCAL MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif

#include "application.h"

cApplication::cApplication()
{
	g_pApplication=this;
	m_hInstance=GetModuleHandle(NULL);

	strcpy(m_className, "ApplicationClass");
	strcpy(m_titleName, "Application Title");

	m_style		=	WS_OVERLAPPEDWINDOW;
	m_xPos		=	0;
	m_yPos		=	0;
	m_width		=	256;
	m_width		=	256;

	m_wc.cbSize			=	sizeof(WNDCLASSEX);
	m_wc.style			=	CS_CLASSDC;
	m_wc.lpfnWndProc	=	MsgProc; //this is where the compiler error comes from
	m_wc.cbClsExtra		=	0;
	m_wc.cbWndExtra		=	0;
	m_wc.hInstance		=	m_hInstance;
	m_wc.hIcon			=	LoadIcon(NULL, IDI_APPLICATION);
	m_wc.hCursor		=	LoadCursor(NULL, IDC_ARROW);
	m_wc.hbrBackground	=	NULL;
	m_wc.lpszMenuName	=	NULL;
	m_wc.lpszClassName	=	m_titleName;
	m_wc.hIconSm		=	LoadIcon(NULL, IDI_APPLICATION);
	
}

HWND cApplication::GetHwnd()
{
	return m_hWnd;
}

HINSTANCE cApplication::GetHinstance()
{
	return m_hInstance;
}

BOOL cApplication::Run()
{
	MSG Msg;

	if(RegisterClassEx(&m_wc))
		return FALSE;
	m_hWnd = CreateWindow(m_className, m_titleName, m_style, m_xPos, m_yPos, m_width, m_height, NULL, NULL, m_hInstance, NULL);
	if(m_hWnd)
		return FALSE;
	ShowWindow(m_hWnd, SW_NORMAL);
	UpdateWindow(m_hWnd);
	if(Init()==TRUE){
		ZeroMemory(&Msg, sizeof(MSG));
		while(Msg.message != WM_QUIT){
			if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)){
				TranslateMessage(&Msg);
				DispatchMessage(&Msg);
			}
				else
				{
					if(Frame() == FALSE)
						break;
				}
		}
	}
	Shutdown();
	UnregisterClass(m_className, m_hInstance);
	return TRUE;
}

long FAR PASCAL MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg){
		case WM_DESTROY:
			PostQuitMessage(0);
			return 0;
		default: return g_pApplication->MsgProc(hWnd, uMsg, wParam, lParam);
	}
}

#include "application.h"

class cApp : public cApplication
{
public:
	cApp();

};

cApp::cApp()
{
	m_width=480;
	m_height=480;
	m_style= WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
	strcpy(m_className, "Hello World");
	strcpy(m_titleName, "Hello WOrld");
}

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
{
	cApp App;
	return App.Run();
}

heres the errors and warnings i get from the compiler c:\Documents and Settings\Chris\My Documents\Visual Studio Projects\application core\application.cpp(19): error C2440: '=' : cannot convert from 'int (__stdcall cApplication::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC' There is no context in which this conversion is possible c:\Documents and Settings\Chris\My Documents\Visual Studio Projects\application core\application.h(28): warning C4244: 'return' : conversion from 'LRESULT' to 'int', possible loss of data c:\Documents and Settings\Chris\My Documents\Visual Studio Projects\application core\application.h(28): warning C4244: 'return' : conversion from 'LRESULT' to 'int', possible loss of data

Share this post


Link to post
Share on other sites
Long story short: you can't assign a normal member function pointer to be the windows procedure for a window class. The usual solution is instead to assign a static member function that gets the pointer to the class from the GWL_USERDATA portion of GetWindowLongPtr(), and then calls a member function to handle the message. The static window procedure handles the WM_NCCREATE message itself in order to set the class pointer with SetWindowLongPtr().

For more information you might want to see this article.

Share this post


Link to post
Share on other sites
Yeah, you can NOT use a Class member function for a message procedure, you must do it C-style baby - a normal C function!

For example,

The Dot "h" file:

class Application
{
public:
Application();
virtual ~Application() { }

/* Member Functions to create, run, and display the application. */
virtual BOOL Create(HINSTANCE hInstance, LPCTSTR);
virtual BOOL UnCreate(HINSTANCE hInstance);

virtual LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
...
}


And the Dot "cpp" file:


static Application* g_pApplication = NULL;

Application::Application() : m_bActive(TRUE), m_hWnd(NULL)
{
g_pApplication = this;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return g_pApplication->MsgProc(hWnd, uMsg, wParam, lParam);
}

...

LRESULT Application::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_GETMINMAXINFO:
((MINMAXINFO*) lParam)->ptMinTrackSize.x = 100;
((MINMAXINFO*) lParam)->ptMinTrackSize.y = 100;
break;

case WM_CLOSE:
PostQuitMessage(0);
return 0;
break;
}

return DefWindowProc(hWnd, uMsg, wParam, lParam);
}



You could also look into making MsgProc a friend function of the cApplication
Class.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this