Archived

This topic is now archived and is closed to further replies.

JinJo

MDI window for level editor

Recommended Posts

I'm starting a level editor for a new game, an iso tile game simillar to shadowrun (snes) and fallout tactics on PC. Ive wrote two classes that the engine and editor will share these are a windows class, and a singleton dx screen class. The Problem is that my win class can only setup normal windows and i dont know how to alter it to also be able to do mdi windows. to make it easier ill post the source obvoiusly u dont need to read all of it because some of the functions are just access or helper functions. //header file
    
//e_window.h

#include "e_error.h"
//include data types if any

#include <windows.h>
#include "E_DataTypes.h"

#pragma once

//engines window class

class E_Window
{
protected:
	WNDCLASS		m_kWndClass;
	HWND			m_hWindow;
	MSG				m_kMessage;
	

public:
	//constructor / destructor

	E_Window();
	~E_Window();
	
	void Create(HINSTANCE hInstance, LPSTR szTitle, 
				Int width = CW_USEDEFAULT,	Int height = CW_USEDEFAULT, 
				UInt style = WS_OVERLAPPEDWINDOW | WS_VISIBLE);
	static LRESULT CALLBACK WndProc(HWND hWindow, UINT message, WPARAM wParam, LPARAM lParam);
	void Run(void);

	//custom functions

	virtual bool MessageHandler(UINT message, WPARAM wParam, LPARAM lParam);
	virtual bool Frame(void) = 0;
	void Cleanup(void);

	//More functions

	void SetPosition(Int width, Int height);
	POINT GetPosition(void);
	void SetSize(Int width, Int height);
	POINT GetSize(void);
	void Show(Int show);
	HWND GetHandle(void);
};
  
//cpp file

      
//e_window.cpp

#include "e_window.h"

//default constructor

E_Window::E_Window(void)
{
	m_szError = NULL;
}

//default destructor

E_Window::~E_Window(void)
{
	//do nothing

}

void E_Window::Create(HINSTANCE hInstance, LPSTR szTitle, 
					  Int width, Int height, UInt style)
{
	//visual properties

	m_kWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	m_kWndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	m_kWndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);

	//system properties

	m_kWndClass.hInstance = hInstance;
	m_kWndClass.lpfnWndProc = WndProc;
	m_kWndClass.lpszClassName = "Engine Window";

	//extra properties

	m_kWndClass.lpszMenuName = NULL;
	m_kWndClass.cbClsExtra = NULL;
	m_kWndClass.cbWndExtra = NULL;
	m_kWndClass.style = NULL;

	//register class

	if(!RegisterClass(&m_kWndClass))
	{
		m_szError = E_ErrorRegisterClass;
		Cleanup();
	}

	//create window

	m_hWindow = CreateWindow(m_kWndClass.lpszClassName, szTitle, style, 
							CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, 
							hInstance, (void*)this);
	if(!m_hWindow)
	{
		m_szError = E_ErrorCreateWindow;
	}

	SetWindowText(m_hWindow, szTitle);
}

//normal message handler, this directs all messages to the MessageHandler function

LRESULT CALLBACK E_Window::WndProc(HWND hWindow, UINT message, WPARAM wParam, LPARAM lParam)
{
	E_Window*  pkWindow   = NULL;
	bool       bProcessed = false;

	switch (message)
	{
	//Window is creating - set custom information 

	case WM_NCCREATE:
		SetWindowLong(hWindow, GWL_USERDATA, 
						(long)((LPCREATESTRUCT(lParam))->lpCreateParams));
		break;
	//Window message - Let our handler process it

	default:
		pkWindow = (E_Window *)GetWindowLong(hWindow, GWL_USERDATA);
		if (NULL != pkWindow)
		{
			bProcessed = pkWindow->MessageHandler(message, wParam, lParam);
		}
		break;
	}

	//Message not processed - let windows handle it 

	if (false == bProcessed)
	{
		return DefWindowProc(hWindow, message, wParam, lParam);
	}
	return 0;
}

//Real time message loop 

void E_Window::Run(void)
{
	while(1)	//infinate loop

	{
		//Query to see if there is any message in the queue 

		if(PeekMessage(&m_kMessage, m_hWindow, 0, 0, PM_REMOVE))
		{
			//if it is the WM_QUIT message, quit the loop 

			if(WM_QUIT == m_kMessage.message)
			{
				break;
			}
			/*if(WA_INACTIVE == m_kMessage.message)
			{
				break;
			}
			if(WA_ACTIVE == m_kMessage.message)
			{
				break;
			}
			if(WA_CLICKACTIVE  == m_kMessage.message)
			{
				break;
			}
			if(SIZE_RESTORED == m_kMessage.message)
			{
			break;
			}
			if(SIZE_MINIMIZED == m_kMessage.message)
			{
				break;
			}
			if(SIZE_MAXSHOW == m_kMessage.message)
			{
				break;
			}
			if(SIZE_MAXIMIZED == m_kMessage.message)
			{
				break;
			} 			if(SIZE_MAXHIDE == m_kMessage.message)
			{
				break;
			}*/
			else
			//Process the message normally 

			{
				TranslateMessage(&m_kMessage);
				DispatchMessage(&m_kMessage);
			}
		}
		else
		{
			//No message, do frame 

			if(false == Frame())
			{
				return;
			}
		}
	}
}

//message handler 

bool E_Window::MessageHandler(UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	//Close window 

	case WM_CLOSE:
		PostQuitMessage(0);
		return true;
		break;
	//Not handled - let Windows handle

	default:
		return false;
		break;
	}
}

void E_Window::Cleanup(void)
{
}

//Set window position 

void E_Window::SetPosition(Int x, Int y)
{
	// Set window position 

	SetWindowPos(m_hWindow, HWND_TOP, x, x, 0, 0, SWP_NOSIZE);
}

//Get window position 

POINT E_Window::GetPosition(void)
{
	RECT  rcWindow;
	POINT pPosition;

	//Get window position 

	GetWindowRect(m_hWindow, &rcWindow);
	pPosition.x = rcWindow.left;
	pPosition.y = rcWindow.top;

	return pPosition;
}

//Set window size 

void E_Window::SetSize(Int width, Int height)
{
	//Set window position 

	SetWindowPos(m_hWindow, HWND_TOP, 0, 0, width, height, SWP_NOMOVE);
}

//Get window size 

POINT E_Window::GetSize(void)
{
	RECT  rcWindow;
	POINT pSize;

	// Get window position 

	GetWindowRect (m_hWindow, &rcWindow);
	pSize.x = rcWindow.right  - rcWindow.left;
	pSize.y = rcWindow.bottom - rcWindow.top;

	return pSize;
}

//Modify window state 

void E_Window::Show(Int show)
{
	// Change window visibility 

	ShowWindow (m_hWindow, show);
}

//Return window handle

HWND E_Window::GetHandle(void)
{
	return m_hWindow;
}
    
if anyone could explain to me what adjustments i could make would be really helpful thanks. [edited by - JinJo on September 1, 2002 5:01:09 PM]

Share this post


Link to post
Share on other sites
A MDI prog involves instancing a system supplied MDIClient class that acts as a controller/parent window for the document containing child windows. A second window class has to be registered for these child windows - and there are changes that must be made to the wndproc for the main window as well as for the child windows. iirc, instead of using DefWindowProc to catch unhandled messages, the child windows have to use DefMDIChildProc. Here is how the parent-child relations for the window classes lay out:

MainFrame
\-> MDIClient
\->MDIChild1 // these stores the document
\->MDIChild2
\->MDIChild3
...
\->MDIChildN

For sample code relating how to setup a MDI app, check out the faq at winprog.org. The sample code is C++ but doesn't use classes. You'll have to figure that part out for yourself.



[edited by - lessbread on September 1, 2002 5:42:50 PM]

Share this post


Link to post
Share on other sites