//************************************************************* // File name: supermdi.c // // Description: // Contains Winmain and the WndProcs. // // History: Date Author Comment // 1/1/92 JJJ Created // // Written by Microsoft Product Support Services, Windows Developer Support // Copyright (c) 1992 Microsoft Corporation. All rights reserved. //************************************************************* #include "global.h" //-------------------- global variables ------------------------- HANDLE ghInst; // Program instance handle HWND ghFrame = NULL; // Handle to main window HWND ghClient = NULL; // Handle to MDI client LONG styleDefault = 0; // Default style bits for child windows int nColor = IDM_OCEANGRAY; // Color to paint the client char szInstructions[] = "This sample demonstrates super classing of the MDI \ client window. Applications commonly super class the MDI client to change \ the background color or to have the client window accept double click or to \ change something defined by the global MDICLIENT class"; //************************************************************* // // FrameWndProc () // // Purpose: // The window function for the "frame" window, which controls // the menu and encompasses all the MDI child windows. Does // the major part of the message processing. Specifically, in // response to: // // WM_CREATE : Creates and displays the "frame". // WM_COMMAND: Passes control to a command-handling function. // WM_CLOSE : Quits the app. // WM_DESTROY: Destroys frame window and quits app. // // Parameters: // ( HWND, WORD, WORD, LONG) // Return: (LONG) // // Comments: // If cases are added for WM_MENUCHAR, WM_NEXTMENU, WM_SETFOCUS, // and WM_SIZE, note that these messages should be passed on // to DefFrameProc even if we handle them. See the SDK Reference // entry for DefFrameProc // // History: Date Author Comment // 1/1/92 JJJ Created // //************************************************************* LONG FAR PASCAL FrameWndProc ( HWND hwnd, WORD msg, WORD wParam, LONG lParam ) { switch (msg) { case WM_CREATE: { CLIENTCREATESTRUCT ccs; // Find window menu where children will be listed ccs.hWindowMenu = GetSubMenu (GetMenu(hwnd),WINDOWMENU); ccs.idFirstChild = IDM_WINDOWCHILD; // Create the MDI client ghClient = CreateWindow (szClient,NULL, WS_CHILD|WS_CLIPCHILDREN,0,0,0,0,hwnd,0,ghInst,(LPSTR)&ccs); ShowWindow (ghClient,SW_SHOW); break; } case WM_COMMAND: // Direct all menu selection or accelerator commands to // the CommandHandler function CommandHandler (hwnd,wParam); break; case WM_CLOSE: DestroyWindow (hwnd); break; case WM_DESTROY: PostQuitMessage (0); break; default: // use DefFrameProc() instead of DefWindowProc(), since there // are things that have to be handled differently because of MDI return DefFrameProc (hwnd,ghClient,msg,wParam,lParam); } return (0L); } //************************************************************* // // ChildWndProc () // // Purpose: // The window function for each "Child" window. // // Parameters: // ( HWND, WORD, WORD, LONG) // // Return: (LONG) // // Comments: // If cases are added for WM_CHILDACTIVATE, WM_GETMINMAXINFO, // WM_MENUCHAR, WM_MOVE, WM_NEXTMENU, WM_SETFOCUS, WM_SIZE, // or WM_SYSCOMMAND, these messages should be passed on // to DefMDIChildProc even if we handle them. See the SDK // Reference entry for DefMDIChildProc // // History: Date Author Comment // 1/1/92 JJJ Created // //************************************************************* LONG FAR PASCAL ChildWndProc ( HWND hwnd, WORD msg, WORD wParam, LONG lParam ) { switch (msg) { default: break; } return DefMDIChildProc (hwnd, msg, wParam, lParam); } //************************************************************* // // MyNewClientProc () // // Purpose: // The window function for superclassed client window // // Parameters: // ( HWND, WORD, WORD, LONG) // // Return: (LONG) // // Comments: // // History: Date Author Comment // 1/1/92 JJJ Created // //************************************************************* LONG FAR PASCAL MyNewClientProc ( hwnd, msg, wParam, lParam ) register HWND hwnd; WORD msg; register WORD wParam; LONG lParam; { switch (msg) { case WM_LBUTTONDBLCLK: MessageBox(hwnd, "Got a WM_LBUTTONDBLCLK", "Double Clicks", MB_OK|MB_APPLMODAL); break; case WM_RBUTTONDBLCLK: MessageBox(hwnd, "Got a WM_RBUTTONDBLCLK", "Double Clicks", MB_OK|MB_APPLMODAL); break; case WM_ERASEBKGND: { HBRUSH hBrush, hOldBrush; LONG lRetValue; if (nColor == IDM_RED) hBrush = CreateSolidBrush(RGB(255,0,0)); else if (nColor == IDM_GREEN) hBrush = CreateSolidBrush(RGB(0,255,0)); else if (nColor == IDM_BLUE) hBrush = CreateSolidBrush(RGB(0,0,255)); else if (nColor == IDM_PURPLE) hBrush = CreateSolidBrush(RGB(18,6,28)); else if (nColor == IDM_MILITARYGRAY) hBrush = CreateSolidBrush(RGB(192,192,192)); else if (nColor == IDM_OCEANGRAY) hBrush = CreateSolidBrush(RGB(192,192,192)); else hBrush = CreateSolidBrush(RGB(0,0,0)); // Change the default background brush for our super classed class hOldBrush = SetClassWord(hwnd, GCW_HBRBACKGROUND, hBrush); // Let the old Window procedure handle the message lRetValue = CallWindowProc(lpfnOldClient, hwnd, msg, wParam,lParam); // Set the class's background brush back. SetClassWord(hwnd, GCW_HBRBACKGROUND, hOldBrush); DeleteObject(hBrush); return (lRetValue); } default: break; } return CallWindowProc( lpfnOldClient,hwnd, msg, wParam, lParam); } //************************************************************* // // CommandHandler () // // Purpose: // Processes all frame window WM_COMMAND messages. // // Parameters: // ( HWND, WORD ) // // Return: () // // Comments: // // History: Date Author Comment // 1/1/92 JJJ Created // //************************************************************* VOID NEAR PASCAL CommandHandler ( HWND hwnd, WORD wParam ) { FARPROC lpProc; switch (wParam) { case IDM_RED: case IDM_GREEN: case IDM_BLUE: case IDM_PURPLE: case IDM_MILITARYGRAY: case IDM_OCEANGRAY: CheckMenuItem(GetMenu(ghFrame),nColor,MF_BYCOMMAND|MF_UNCHECKED); nColor = wParam; CheckMenuItem(GetMenu(ghFrame),nColor,MF_BYCOMMAND|MF_CHECKED); InvalidateRect(ghClient,NULL,TRUE); break; case IDM_ABOUT: lpProc = MakeProcInstance(About, ghInst); DialogBox(ghInst, "AboutBox", hwnd, lpProc); FreeProcInstance(lpProc); break; case IDM_INSTRUCTIONS: lpProc = MakeProcInstance(Instructions, ghInst); DialogBox(ghInst, "Instructions", hwnd, lpProc); FreeProcInstance(lpProc); break; case IDM_FILENEW: // Make an empty MDI child window MakeNewChild (NULL); break; case IDM_FILEEXIT: // Close application SendMessage (hwnd, WM_CLOSE, 0, 0L); break; case IDM_WINDOWTILE: // Tile MDI windows SendMessage (ghClient, WM_MDITILE, 0, 0L); break; case IDM_WINDOWCASCADE: // Cascade MDI windows SendMessage (ghClient, WM_MDICASCADE, 0, 0L); break; case IDM_WINDOWICONS: // Auto - arrange MDI icons SendMessage (ghClient, WM_MDIICONARRANGE, 0, 0L); break; case IDM_WINDOWCLOSEALL: CloseAllChildren(); break; default: // This is essential, since there are frame WM_COMMANDS generated // by the MDI system for activating child windows via the // window menu. DefFrameProc(hwnd, ghClient, WM_COMMAND, wParam, 0L); } } //************************************************************* // // CloseAllChildren () // // Purpose: // Destroys all MDI child windows. // // Parameters: // ( ) // // Return: ( ) // // Comments: // // History: Date Author Comment // 1/1/92 JJJ Created // //************************************************************* VOID NEAR PASCAL CloseAllChildren (VOID) { register HWND hwndT; // As long as the MDI client has a child, destroy it while ( hwndT = GetWindow (ghClient, GW_CHILD)) { // Skip the icon title windows while (hwndT && GetWindow (hwndT, GW_OWNER)) hwndT = GetWindow (hwndT, GW_HWNDNEXT); if (hwndT) SendMessage (ghClient, WM_MDIDESTROY, (WORD)hwndT, 0L); else break; } } //************************************************************* // // About() // // Purpose: // The About dialog box procedure. // // Parameters: // HWND hDlg - Handle to dialog window // unsigned msg - Message passed to dialog window // WORD wParam - Additional message information // LONG lParam - Additional message information // // Return: (BOOL FAR PASCAL) // TRUE - About dialog procedure handled the message. // FALSE - About dialog procedure did not handle the message. // // Comments: // // History: Date Author Comment // 1/1/92 JJJ Created // //************************************************************* BOOL FAR PASCAL About (HWND hDlg, UINT msg, WORD wParam, LONG lParam) { switch (msg) { case WM_INITDIALOG: SetDlgItemText(hDlg,ID_DESC,"Super Classed MDI Client"); SetDlgItemText(hDlg,ID_VER,"Version 1.0"); return(TRUE); case WM_COMMAND: switch (wParam) { case IDOK: case IDCANCEL: EndDialog(hDlg, TRUE); return(TRUE); default: break; } break; } return(FALSE); // Didn't process a message } /* About() */ //************************************************************* // // Instructions() // // Purpose: // The instructions dialog box procedure. // // Parameters: // HWND hDlg - Handle to dialog window // unsigned msg - Message passed to dialog window // WORD wParam - Additional message information // LONG lParam - Additional message information // // Return: (BOOL FAR PASCAL) // TRUE - dialog procedure handled the message. // FALSE - dialog procedure did not handle the message. // // Comments: // // History: Date Author Comment // 1/1/92 JJJ Created // //************************************************************* BOOL FAR PASCAL Instructions (HWND hDlg, UINT msg, WORD wParam, LONG lParam) { static HFONT hFont; switch (msg) { case WM_INITDIALOG: { /* Height = (points_size/72 points per inch) * (GetDeviceCaps(LOGPIXELSY)= pixels per inch)*/ HDC hDC; int Height; hDC = GetDC(hDlg); Height = ((GetDeviceCaps(hDC,LOGPIXELSY)*16)/72); hFont = CreateFont(Height,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE,(LPSTR)"Roman"); ReleaseDC(hDlg,hDC); SetDlgItemText(hDlg,ID_TITLE,"Purpose"); SetWindowText(GetDlgItem(hDlg,ID_INSTBOX),(LPSTR)szInstructions); SendDlgItemMessage(hDlg,ID_TITLE,WM_SETFONT,hFont,TRUE); return(TRUE); } case WM_COMMAND: if (wParam == IDOK || wParam == IDCANCEL) { EndDialog(hDlg, TRUE); DeleteObject(hFont); return(TRUE); } break; } return(FALSE); // Didn't process a message } /* Instructions() */ //************************************************************* // // WinMain () // // Purpose: // Entry Point for Windows. // // Parameters: // (HANDLE, HANDLE, LPSTR, int) // // Return: ( ) // // Comments: // // History: Date Author Comment // 1/1/92 JJJ Created // //************************************************************* int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine,int nCmdShow) { MSG msg; ghInst = hInstance; // If this is the first instance of the app. register window classes if (hPrevInstance) { MessageBox(NULL,"Cannot run multiple instances of this application","Error", MB_OK|MB_APPLMODAL); return (0); } if (!InitializeApplication ()) return (0); // Create the frame and do other initialization if (!InitializeInstance (lpszCmdLine, nCmdShow)) return (0); // Enter main message loop while (GetMessage (&msg, NULL, 0, 0)) { // If a keyboard message is for the MDI, let the MDI client // take care of it. Otherwise, just handle the message as usual if ( !TranslateMDISysAccel (ghClient, &msg)) { TranslateMessage (&msg); DispatchMessage (&msg); } } return (0); }