Home | API | MFC | C++ | C | Previous | Next

Programming Windows API

The Multiple-Document Interface (MDI)

The multiple-document interface (MDI) is enables a user to work with more than one document at the same time. A typical MDI application must register two window classes: one for its frame window and one for its child windows. At any one time, only one document window is active (indicated by a highlighted title bar), and it appears in front of all the other document windows.

Creating an MDI Application

The first step in creating an MDI application is to register the window classes. One class will be required for the MDI frame window, and another class will be required for each different type of MDI child window. The class structure for an MDI frame window is like a normal application’s main window. The class structure for an MDI child window is filled in like the class structure for child windows with two exceptions. First, the class structure for an MDI child window should specify an ICON since the user can minimize MDI child windows within the MDI frame window. Second, the menu name should be NULL, since an MDI child window does not have its own menu.

Example

The following short program demonstrates how to create a Multiple document interface. Clicking the menubar item file followed by menu item new creates and new MDI child window.

// Multi document interface demo
#define IDI_ICON 101
#define IDC_CHILD_EDIT 200
#define IDM_FILE_EXIT 1000
#define IDM_FILE_NEW 1001
#define ID_MDI_CLIENT 1002
#define ID_MDI_FIRSTCHILD 1003
#include <windows.h>
const TCHAR ClassName[] = TEXT("MainWindowClass");
const TCHAR ChildClassName[] =TEXT( "ChildWindowClass");
HWND static hWndClient;
//HWND static mhWnd;

LRESULT CALLBACK ChildProc( HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam )
{
switch(Msg)// Handle messages from the child windows
{
case WM_CREATE:
{
HWND hEdit;
// Create Edit Control
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,TEXT("EDIT"),TEXT( ""),
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
0, 0, 100, 100, hWnd, (HMENU)IDC_CHILD_EDIT, GetModuleHandle(NULL), NULL);
if(hEdit == NULL)
MessageBox(hWnd, TEXT("Could not create edit box."),TEXT( "Error"), MB_OK | MB_ICONERROR);
}
break;
case WM_MDIACTIVATE:
{
//place code for execution prior to activation
}
case WM_SIZE:
{
HWND hEdit;
RECT rcClient;
GetClientRect(hWnd, &rcClient);
hEdit = GetDlgItem(hWnd, IDC_CHILD_EDIT);
SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
}
return DefMDIChildProc(hWnd, Msg, wParam, lParam);
break;
}
return DefMDIChildProc(hWnd, Msg, wParam, lParam);
}

LRESULT CALLBACK WndProc( HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam )
{
switch (Msg)
//main window message loop
{
case WM_CREATE:
{
HMENU hMenubar;
HMENU hMenu;
hMenubar = CreateMenu();
hMenu = CreateMenu();
AppendMenu(hMenu, MF_STRING, IDM_FILE_NEW, TEXT("New"));
AppendMenu(hMenu, MF_STRING, IDM_FILE_EXIT , TEXT("Quit"));
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu,TEXT("&File"));
SetMenu(hWnd, hMenubar);
CLIENTCREATESTRUCT ccs;
ccs.hWindowMenu = GetSubMenu(GetMenu(hWnd), 0);
ccs.idFirstChild = ID_MDI_FIRSTCHILD;
hWndClient = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("MDICLIENT"), NULL,WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,hWnd, (HMENU)ID_MDI_CLIENT, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), (LPVOID)&ccs);
if(!hWndClient)
{
MessageBox(hWnd, TEXT("Failed To Create The Client Window"),TEXT("Error"), MB_OK);
}
ShowWindow(hWndClient, SW_SHOW);
}
break;

case WM_COMMAND:
{
switch(LOWORD(wParam))
{
//create new child window
case IDM_FILE_NEW:
{
HWND hChild;
CREATESTRUCT cs;
ZeroMemory(&cs, sizeof(CREATESTRUCT));
hChild = CreateWindowEx(WS_EX_MDICHILD,ChildClassName,TEXT("Child Window"),WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hWndClient,NULL,(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),&cs);
if(!hChild)
MessageBox(hWnd, TEXT("Failed To Create The Child Window"),TEXT( "Error"), MB_OK);
}
break;
//exit application
case IDM_FILE_EXIT:
PostMessage(hWnd, WM_CLOSE, 0, 0);
break;
default:
{
if(LOWORD(wParam) >= ID_MDI_FIRSTCHILD)
DefFrameProc(hWnd, hWndClient, Msg, wParam, lParam);
else
{
HWND hChild;
hChild = (HWND)SendMessage(hWndClient, WM_MDIGETACTIVE,0,0);
if(hChild)
SendMessage(hChild, WM_COMMAND, wParam, lParam);
}
}
}
return 0;
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefFrameProc(hWnd, hWndClient, Msg, wParam, lParam);
}
return 0;
}
//winmain for main window
INT WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,INT nCmdShow )
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = ClassName;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, TEXT("Failed To Register The Window Class."),TEXT("Error"), MB_OK | MB_ICONERROR);
return 0;
}
//winmain for child window
wc.lpfnWndProc = (WNDPROC)ChildProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_3DSHADOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = ChildClassName;

if(!RegisterClassEx(&wc))
{
MessageBox(NULL,TEXT("Failed To Register The Child Window Class"),TEXT("Error"), MB_OK | MB_ICONERROR);
return 0;
}
HWND hWnd;
hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,ClassName,TEXT("MDI"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,600,400,NULL,NULL,hInstance,NULL);
if (!hWnd)
{
MessageBox(NULL, TEXT("Window Creation Failed."), TEXT("Error"), MB_OK | MB_ICONERROR);
return 0;
}
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0))
{
if (!TranslateMDISysAccel(hWndClient, &Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
return Msg.wParam;
}

Download


Home | API | MFC | C++ | C | Previous | Next
Creating a Simple Window | Common Elements | Data Types and Character Sets | The Device Context | Graphics Device Interface | Displaying Text | Displaying Graphics | Mapping Modes | Keyboard Input | Working with the Mouse | Menus | Child Windows | ScrollBar Control | The Dialog Box | Windows Message Box | Common Dialog Box | Bitmaps | Common Controls | Creating a Toolbar | Multiple Document Interface | Timers | DLL’s | Creating Custom Controls | Owner Drawn Controls | API Hooking and DLL Injection | File Management Functions | String Manipulation | System Information Functions