Jump to content
  • Advertisement
Sign in to follow this  
MindWipe

Problems with object oriented MDI design!?

This topic is 5407 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

I want to make a MDI program. I just want one type of child windows. Anyway, I've never done this before and I want good code design. But I ran into some problems. I have one class for my main window. It worked fine, but I couldn't get the child window class to work. Don't know really what I'm doing wrong. I'm sorry to throw alot of code at you like this, but I really have no clue what to do. Here's my EMain.cpp (Main window class).
#include "EGeneral.h"

EMain EMain::I;


// Constructor / Destructor

EMain::EMain()
{
	m_hWnd = NULL;
	m_hInst = NULL;

}

EMain::~EMain()
{

}

void EMain::CleanUp()
{
	for(MAPS::iterator i = m_pMaps.begin(); i < m_pMaps.end(); i++)
		delete (*i);

	m_pMaps.clear();
}
bool EMain::Initalize(HINSTANCE hInstance)
{

	SetLastError(0);

	 m_hInst = hInstance;
 	
	

	// Ensure common controls DLL is loaded for common controls
	INITCOMMONCONTROLSEX icex;
	icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
	icex.dwICC  = ICC_LISTVIEW_CLASSES;
	InitCommonControlsEx(&icex); 

	//Initalize Class
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)StaticProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, /*(LPCTSTR)IDI_MAIN*/NULL);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= TITLE;
	wcex.lpszClassName	= CLASS_NAME;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, /*(LPCTSTR)IDI_SMALL*/NULL);

	RegisterClassEx(&wcex);

	//Create Window
	m_hWnd = CreateWindow(CLASS_NAME,TITLE,WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ,CW_USEDEFAULT,CW_USEDEFAULT,640,480,NULL,NULL,hInstance,NULL);
	if(m_hWnd == NULL) return false;

 
	//Create Window Controls
	CreateToolbar();

	ShowWindow(m_hWnd,SW_SHOWDEFAULT);
	UpdateWindow(m_hWnd);

	SetWindowLong(m_hWnd,GWL_USERDATA,(LONG)this);
		 
    return true;
}

bool EMain::CreateToolbar()
{
        //Not relevant now
}
int EMain::Run()
{
	MSG	msg;
	HWND hwndClient;

	hwndClient = GetWindow (m_hWnd, GW_CHILD);

	// Main message loop
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return (int) msg.wParam;
}

LRESULT CALLBACK EMain::StaticProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	EMain	*pThis = NULL;
	pThis = (EMain*)GetWindowLong(hWnd,GWL_USERDATA);

	if(pThis)
		return pThis->Proc(hWnd,message,wParam,lParam);
	else
		return DefWindowProc(hWnd, message, wParam, lParam);
}


LRESULT CALLBACK EMain::Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{		
	static HWND hwndClient = 0;
	CLIENTCREATESTRUCT clientcreate ;
    MDICREATESTRUCT    mdicreate ;

	switch (message) 
	{
		case WM_CREATE:
          
   

          break;

		case WM_COMMAND:
			switch(wParam)
			{
				case TOOLBAR_NEW:
				{
	    
					MAP *newMap = new MAP();
			newMap->CreateWnd(m_hInst,m_hWnd);

				 
					m_pMaps.push_back(newMap);
				}
			}

		case WM_SIZE:
			//resize toolbar
			SendMessage(m_hWndToolbar,TB_AUTOSIZE,0,0);
			break;


		case WM_DESTROY:
			CleanUp();
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }

   return 0;
}



And here's my child window's class:
#include "EGeneral.h"

// Constructor / Destructor

EMapChildWindow::EMapChildWindow()
{
	m_hWnd = NULL;
	m_hInst = NULL;
}

EMapChildWindow::~EMapChildWindow()
{

}

void EMapChildWindow::CreateWnd( HINSTANCE hInstance, HWND hWndParent )
{
        m_hInst = hInstance;
	 WNDCLASSEX wcex;

	wcex.cbSize			= sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)StaticProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= m_hInst;
	wcex.hIcon			= LoadIcon(m_hInst, /*(LPCTSTR)IDI_MAIN*/NULL);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= TITLE;
	wcex.lpszClassName	= CHILDWND_CLASS_NAME;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, /*(LPCTSTR)IDI_SMALL*/NULL);

	RegisterClassEx(&wcex);
	m_hWnd = CreateMDIWindow( CHILDWND_CLASS_NAME,"Map", WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
							  CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
							  hWndParent, m_hInst, 0);

  
	ShowWindow(m_hWnd,SW_SHOWDEFAULT);
	UpdateWindow(m_hWnd);

	SetWindowLong(m_hWnd,GWL_USERDATA,(LONG)this);

}
LRESULT CALLBACK EMapChildWindow::StaticProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	EMapChildWindow	*pThis = NULL;
	pThis = (EMapChildWindow*)GetWindowLong(hWnd,GWL_USERDATA);

	if(pThis)
		return pThis->Proc(hWnd,message,wParam,lParam);
	else
		return DefWindowProc(hWnd, message, wParam, lParam);
}


LRESULT CALLBACK EMapChildWindow::Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{						 
	switch (message) 
	{
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }

   return 0;
}


The main() function looks as simple as: E->Initialize(); return E->Run(); And it runs. But I'm just not able to see any of the child windows?! I got it working by creating a normal window as a child. But I want to be able to use the MDI interface. If anyonee got any usefull code then it would help alot. I got this great MDI example but it's not at all OO. Thanks in advance! /MindWipe [Edited by - MindWipe on September 26, 2004 8:32:54 AM]

Share this post


Link to post
Share on other sites
Advertisement
Don't let the child windows return value in the windowproc be 0.
There is no general return value for window messages. Let unhandled messages be processed by DefWindowProc.
In other words, move DefWindowProc from the default-case to the bottom of the function.

Also, CW_USEDEFAULT will be set to zero for child windows. Supply real values there.

Another addon:
You might want to call SetWindowLong(m_hWnd,GWL_USERDATA,(LONG)this); in response to WM_NCCREATE (the very first message any HWND receives). Otherwise there's a whole lot of messages you won't catch in the class-member-proc (including WM_CREATE) because the user data will only be set after Create returns.

Share this post


Link to post
Share on other sites
Quote:
Original post by Endurion
Don't let the child windows return value in the windowproc be 0.
There is no general return value for window messages. Let unhandled messages be processed by DefWindowProc.
In other words, move DefWindowProc from the default-case to the bottom of the function.

Also, CW_USEDEFAULT will be set to zero for child windows. Supply real values there.

Another addon:
You might want to call SetWindowLong(m_hWnd,GWL_USERDATA,(LONG)this); in response to WM_NCCREATE (the very first message any HWND receives). Otherwise there's a whole lot of messages you won't catch in the class-member-proc (including WM_CREATE) because the user data will only be set after Create returns.


Thanks!!

But something seems to be very wrong.

Here's my new static winproc:


LRESULT CALLBACK EMain::StaticProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static EMain* pThis = NULL;


if (message == WM_NCCREATE)
{
SetWindowLong(hWnd, GWL_USERDATA, (long)((LPCREATESTRUCT(lParam))->lpCreateParams));
return 1;
}

pThis = (EMain *)GetWindowLong( hWnd, GWL_USERDATA );

if (pThis != NULL)
pThis->Proc(hWnd, message, wParam, lParam);


return DefWindowProc(hWnd, message, wParam, lParam);

}




But somehow the non-static winproc never gets called?!

/MindWipe

Share this post


Link to post
Share on other sites
I've just tested, and created an Win32 project and just pasted your code (plus the new proc) there.

The proc was called, but the creation of the child windows failed. As the error code is dumb beyond belief (file not found???) i tried using CreateWindow instead of CreateMDIWindow. This works, but will probably have problems with more than one child MDI window.

AFAIK for MDI to really work you need a MDI client as a child of the main window, and insert the MDI childs into that client.

For a good explanation about the whole MDI affair open the MSDN and simply enter MDI in the index pane. The main entry will explain how to create the MDI parent and the MDI childs.

Share this post


Link to post
Share on other sites
Quote:
Original post by Endurion
I've just tested, and created an Win32 project and just pasted your code (plus the new proc) there.

The proc was called, but the creation of the child windows failed. As the error code is dumb beyond belief (file not found???) i tried using CreateWindow instead of CreateMDIWindow. This works, but will probably have problems with more than one child MDI window.

AFAIK for MDI to really work you need a MDI client as a child of the main window, and insert the MDI childs into that client.

For a good explanation about the whole MDI affair open the MSDN and simply enter MDI in the index pane. The main entry will explain how to create the MDI parent and the MDI childs.


Ok. Thanks alot! I'll figure it out today. Might rewrite some code, it has gotten a bit messy when I've added/removed stuff all the time.

/MindWipe

Share this post


Link to post
Share on other sites
One little question, why don't you use MFC for these kinds of tasks. They have a complete set of object oriented classes available for implementing both SDI and MDI applications for windows. Just click a few times and the app wizard will generate a complete MDI applicatoin for you,

Share this post


Link to post
Share on other sites
MFC has the habit to add quite some dependencies with DLLs, even when linked statically i don't trust it to not try and use some extended stuff.

Also it's full MFC (with all controls) or nothing.

The WTL is quite a neat "variant" which overcomes a lot of those troubles.

But yes, when you don't need to care for dependencies the app wizard is a great tool.

Share this post


Link to post
Share on other sites
Well, doing it in normal Win32 isn't that hard. I just want it for a simple map editor.

I have a good example how to do MDI but it isn't OO and I've turned into somewhat of a "clean code design" - freak.

/MindWipe

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!