Skip to main content
GameDev.net gamedev.net
🔒 Locked

Unsolvable MDI problem

Started by BrentBarrett Jun 30, 2004 at 11:52 PM 0 replies 600+ views
Original Post
BrentBarrett
BrentBarrett
Ok, I've spent the past week now on this one problem. Some of you may even remember my various other posts related to an MDI problem. Well, all of them were about the same thing, it's just taken me this long to precisely pinpoint what the exact problem is. Here is what's happening: For an MDI you have the Frame window and the MDIClient window, correct? And the MDIClient window spawns Child windows. The bounds (x,y,cx,cy) of the MDIClient window are what clips the Child windows. So, if my MDIClient window has a width of 100, then any Child windows past that mark will be clipped. These are common things than any MDI programmer knows. Now, here's the kicker. Any time I resize or minimize/maximize the Frame window, it sets the MDIClient window's position to 0,0 (relative to the Frame window) and sets the MDIClient window's width and height to be equal to the width and height of the Frame window. This becomes a problem because I have a toolbar that is getting drawn over when the MDIClient window's position is changed. I've even downloaded Microsoft's example of an MDI and it suffers from the same problem. I am literally at the end of my rope here. I feel as though I've really made a dedicated effort in trying to not only solve this problem but to try and find source code that might also hold a key, but I've come up empty handed. I've been catching the WM_WINDOWPOSCHANGING message in an attempt to alter its contents and prevent the window from being resized and moved, but it still happens. Here is the code, I sincerely hope there is some master guru coder out there that can help me with this.


#include <windows.h>

LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK MDIClientWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

char szFrameClass[] = "FrameClass";
char szMDIClientClass[] = "MDIClientClass";

HINSTANCE g_hInst;
HWND g_FrameWnd;
HWND g_MDIClientWnd;

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	//globally track instance
	g_hInst = hInstance;

	WNDCLASSEX wc;
	
	//Frame Class
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = FrameWndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = g_hInst;
	wc.hIcon = NULL;
	wc.hCursor = NULL;
	wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = szFrameClass;
	wc.hIconSm = NULL;
	RegisterClassEx(&wc);

	//MDI Client Class
	wc.cbClsExtra = 0;	
	wc.cbWndExtra = 0;	
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	
	wc.hCursor = NULL;	
	wc.hIcon = NULL;	
	wc.hInstance = g_hInst;	
	wc.lpszMenuName = NULL;	
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = MDIClientWndProc;
	wc.lpszClassName = szMDIClientClass;
	RegisterClassEx(&wc);

 	g_FrameWnd = CreateWindowEx(0, 
				szFrameClass, 
				"Frame Window Title", 
				WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
				0, 0,
				800, 600,
				NULL,
				NULL,
				hInstance,
				NULL);
	ShowWindow(g_FrameWnd,nCmdShow);
	UpdateWindow(g_FrameWnd);


	MDICREATESTRUCT mdic;
	CLIENTCREATESTRUCT ccs;	

	ccs.hWindowMenu = NULL;
	ccs.idFirstChild = 5000;

	g_MDIClientWnd = CreateWindowEx(0,
				"MDICLIENT",
				NULL, 
				WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
				0, 0,
				400, 400,
				g_FrameWnd,
				NULL,
				g_hInst,
				(LPSTR) &ccs);

	mdic.x = 100;
	mdic.y = 100;
	mdic.cx = 100;
	mdic.cy = 100;
	mdic.hOwner = g_hInst;
	mdic.lParam = NULL;
	mdic.style = NULL;
	mdic.szClass = szMDIClientClass;
	mdic.szTitle = "Child Window";

	SendMessage(g_MDIClientWnd, 
		WM_MDICREATE, 
		NULL, 
		(LPARAM)(LPMDICREATESTRUCT)&mdic);

	MSG msg;
	bool Running = true;

	while(Running)
	{
		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			if(msg.message == WM_QUIT)
			{
				Running = false;
			}
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return(msg.wParam);
}

LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{

	switch(Msg)
	{
		case WM_DESTROY:
			PostQuitMessage(0);
			return(0);
	}
	return(DefFrameProc(hWnd, g_MDIClientWnd, Msg, wParam, lParam));
}

LRESULT CALLBACK MDIClientWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	return DefMDIChildProc (hWnd, Msg, wParam, lParam) ;
}
Colin Jeanne
Colin Jeanne
I had a similar problem. You need to handle WM_SIZE in your frame window and then move/size the MDIClient appropriately. This comes from my project:

case WM_SIZE:	{		CRect tool, stat;		tool.WindowRect(GetDlgItem(hwnd, IDC_TOOLBAR));		stat.WindowRect(GetDlgItem(hwnd, IDC_STATUSBAR));		MoveWindow(Client, 0, tool.Height(), LOWORD(lParam),			HIWORD(lParam) - tool.Height() - stat.Height(),			TRUE);		MoveWindow(GetDlgItem(hwnd, IDC_TOOLBAR), 0, 0, LOWORD(lParam),			tool.Height(), TRUE);		MoveWindow(GetDlgItem(hwnd, IDC_STATUSBAR), 0,			HIWORD(lParam) - stat.Height(), LOWORD(lParam),			stat.Height(), TRUE);		break;	}

It sizes the toolbar, statusbar, and MDIClient to make sure there is no overlap or malplacement.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.