A Multiple Document Interface (MDI)

 

Introduction

This is an example of an MDI.

Resource Header

#define IDR_MAIN_MENU                   101
#define IDM_FILE_NEW                    40001
#define IDM_FILE_CLOSE                  40002
#define IDM_FILE_EXIT                   40003
#define IDM_WINDOW_TILE                 40004
#define IDM_WINDOW_CASCADE              40005
#define IDM_WINDOW_ICONS                40006
#define IDM_WINDOW_CLOSE_ALL            40007

Resource Script

#include "resource.h"

/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDR_MAIN_MENU MENU 
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "&New\tCtrl+N",                40001
        MENUITEM SEPARATOR
        MENUITEM "&Close",                      40002
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                       40003
    END
    POPUP "&Window"
    BEGIN
        MENUITEM "&Tile",                       40004
        MENUITEM "C&ascade",                    40005
        MENUITEM "Arrange &Icons",              40006
        MENUITEM "Cl&ose All",                  40007
    END
END


/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE 
BEGIN
    IDM_FILE_NEW            "Creates a new document\nNew"
    IDM_FILE_CLOSE          "Closes the current document\nClose"
    IDM_FILE_EXIT           "Closes the application\nExit"
    IDM_WINDOW_TILE         "Arranges child windows in a tile format"
    IDM_WINDOW_CASCADE      "Arranges child windows in a cascade format"
    IDM_WINDOW_ICONS        "Arranges the icons of minimized child windows"
    IDM_WINDOW_CLOSE_ALL    "Closes all child windows"
END

Source Code

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

const char MainClassName[]  = "MainMDIWnd";
const char ChildClassName[] = "MDIChildWnd";

const int StartChildrenNo = 994;

HWND hWndMainFrame  = NULL;
HWND hWndChildFrame = NULL;

BOOL CreateNewDocument(HINSTANCE hInstance);
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg,
							 WPARAM wParam, LPARAM lParam);
BOOL CreateNewDocument(HINSTANCE hInstance);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX WndClsEx;
	MSG Msg;

	WndClsEx.cbSize		 = sizeof(WNDCLASSEX);
	WndClsEx.style		 = 0;
	WndClsEx.lpfnWndProc	 = MainWndProc;
	WndClsEx.cbClsExtra	 = 0;
	WndClsEx.cbWndExtra	 = 0;
	WndClsEx.hInstance	 = hInstance;
	WndClsEx.hIcon		 = LoadIcon(NULL, IDI_ASTERISK);
	WndClsEx.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	WndClsEx.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	WndClsEx.lpszMenuName  = MAKEINTRESOURCE(IDR_MAIN_MENU);
	WndClsEx.lpszClassName = MainClassName;
	WndClsEx.hIconSm		 = LoadIcon(NULL, IDI_ASTERISK);

	if(!RegisterClassEx(&WndClsEx))
	{
		MessageBox(NULL,
			       "Window Registration Failed!", "Error!",
			       MB_OK);
		return 0;
	}

	if( !CreateNewDocument(hInstance) )
		return 0;

	hWndMainFrame = CreateWindowEx(0L,
                          MainClassName,
						  "Multiple Document Application",
						  WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
						  CW_USEDEFAULT,
						  CW_USEDEFAULT,
						  CW_USEDEFAULT,
						  CW_USEDEFAULT,
						  NULL,
						  NULL,
						  hInstance,
						  NULL);

	if(hWndMainFrame == NULL)
	{
		MessageBox(NULL, "Window Creation Failed!", "Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}

	ShowWindow(hWndMainFrame, nCmdShow);
	UpdateWindow(hWndMainFrame);

	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		if (!TranslateMDISysAccel(hWndChildFrame, &Msg))
		{
			TranslateMessage(&Msg);
			DispatchMessage(&Msg);
		}
	}
	return 0;
}

HWND CreateNewMDIChild(HWND hMDIClient)
{
	MDICREATESTRUCT mcs;
	HWND NewWnd;

	mcs.szTitle = "Untitled";
	mcs.szClass = ChildClassName;
	mcs.hOwner  = GetModuleHandle(NULL);
	mcs.x = mcs.cx = CW_USEDEFAULT;
	mcs.y = mcs.cy = CW_USEDEFAULT;
	mcs.style = MDIS_ALLCHILDSTYLES;

	NewWnd = (HWND)SendMessage(hMDIClient, WM_MDICREATE, 0, (LONG)&mcs);

	if( !NewWnd )
	{
		MessageBox(NULL,
				   "Error creaing child window",
				   "Creation Error",
				   MB_OK);
	}
	return NewWnd;
}

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch(Msg)
	{
		case WM_CREATE:
		{
			CLIENTCREATESTRUCT ccs;

			ccs.hWindowMenu  = GetSubMenu(GetMenu(hWnd), 2);
			ccs.idFirstChild = StartChildrenNo;

			hWndChildFrame = CreateWindowEx(WS_EX_CLIENTEDGE,
				                           "MDICLIENT",
										   NULL,
										   WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL
										            | WS_HSCROLL | WS_VISIBLE,
				                           CW_USEDEFAULT,
										   CW_USEDEFAULT,
										   680,
										   460,
										   hWnd,
										   (HMENU)IDM_FILE_NEW,
										   GetModuleHandle(NULL),
										   (LPVOID)&ccs);

			if(hWndChildFrame == NULL)
				MessageBox(hWnd, "Could not create MDI client.", "Error", MB_OK | MB_ICONERROR);
		}
		CreateNewMDIChild(hWndChildFrame);
		break;
		case WM_SIZE:
		{
			HWND hWndMDI;
			RECT rctClient;

			GetClientRect(hWnd, &rctClient);

			hWndMDI = GetDlgItem(hWnd, IDM_FILE_NEW);
			SetWindowPos(hWndMDI, NULL, 0, 0, rctClient.right, rctClient.bottom, SWP_NOZORDER);
		}
		break;
		case WM_CLOSE:
			DestroyWindow(hWnd);
		break;
		case WM_DESTROY:
			PostQuitMessage(0);
		break;
		case WM_COMMAND:
			switch(LOWORD(wParam))
			{
				case IDM_FILE_NEW:
					CreateNewMDIChild(hWndChildFrame);
				break;
				case IDM_FILE_CLOSE:
				{
					HWND hChild = (HWND)SendMessage(hWndChildFrame, WM_MDIGETACTIVE,0,0);
					if(hChild)
					{
						SendMessage(hChild, WM_CLOSE, 0, 0);
					}
				}
				break;
				case IDM_FILE_EXIT:
					PostMessage(hWnd, WM_CLOSE, 0, 0);
				break;
				case IDM_WINDOW_TILE:
					SendMessage(hWndChildFrame, WM_MDITILE, 0, 0);
					break;

				case IDM_WINDOW_CASCADE:
					SendMessage(hWndChildFrame, WM_MDICASCADE, 0, 0);
					break;

				case IDM_WINDOW_ICONS:
					SendMessage(hWndChildFrame, WM_MDIICONARRANGE, 0, 0);
					break;

				case IDM_WINDOW_CLOSE_ALL:
				{
					HWND hWndCurrent;
					
					do {
						hWndCurrent = (HWND)SendMessage(hWndChildFrame, WM_MDIGETACTIVE,0,0);
						SendMessage(hWndCurrent, WM_CLOSE, 0, 0);
					}while(hWndCurrent);
				}
				break;

				default:
				{
					if(LOWORD(wParam) >= StartChildrenNo)
					{
						DefFrameProc(hWnd, hWndChildFrame, WM_COMMAND, wParam, lParam);
					}
					else 
					{
						HWND hWndCurrent = (HWND)SendMessage(hWndChildFrame, WM_MDIGETACTIVE,0,0);
						if( hWndCurrent )
						{
							SendMessage(hWndCurrent, WM_COMMAND, wParam, lParam);
						}
					}
				}
			}
		break;
		default:
			return DefFrameProc(hWnd, hWndChildFrame, Msg, wParam, lParam);
	}
	return 0;
}

LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
		case WM_CREATE:
		break;

		case WM_MDIACTIVATE:
		{
			HMENU hMenu, hFileMenu;
			UINT EnableFlag;

			hMenu = GetMenu(hWndMainFrame);
			if(hwnd == (HWND)lParam)
			{
				EnableFlag = MF_ENABLED;
			}
			else
			{
				EnableFlag = MF_GRAYED;
			}

			EnableMenuItem(hMenu, 1, MF_BYPOSITION | EnableFlag);
			EnableMenuItem(hMenu, 2, MF_BYPOSITION | EnableFlag);

			hFileMenu = GetSubMenu(hMenu, 0);

			EnableMenuItem(hFileMenu, IDM_FILE_CLOSE, MF_BYCOMMAND | EnableFlag);
			EnableMenuItem(hFileMenu, IDM_WINDOW_CLOSE_ALL, MF_BYCOMMAND | EnableFlag);

			DrawMenuBar(hWndMainFrame);
		}
		break;

		default:
			return DefMDIChildProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}

BOOL CreateNewDocument(HINSTANCE hInstance)
{
	WNDCLASSEX WndClsEx;

	WndClsEx.cbSize		 = sizeof(WNDCLASSEX);
	WndClsEx.style		 = CS_HREDRAW | CS_VREDRAW;
	WndClsEx.lpfnWndProc = ChildWndProc;
	WndClsEx.cbClsExtra	 = 0;
	WndClsEx.cbWndExtra	 = 0;
	WndClsEx.hInstance	 = hInstance;
	WndClsEx.hIcon		 = LoadIcon(NULL, IDI_WARNING);
	WndClsEx.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	WndClsEx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
	WndClsEx.lpszMenuName  = NULL;
	WndClsEx.lpszClassName = ChildClassName;
	WndClsEx.hIconSm		 = LoadIcon(NULL, IDI_WARNING);

	if(!RegisterClassEx(&WndClsEx))
	{
		MessageBox(NULL,
			       "There was a problem when attempting to create a document",
			       "Application Error",
				   MB_OK);
		return FALSE;
	}
	else
		return TRUE;
}
 

Home Copyright 2004 FunctionX, Inc.