home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / progwin / chap18 / mdidemo.c next >
Encoding:
C/C++ Source or Header  |  1990-11-12  |  18.0 KB  |  499 lines

  1. /*--------------------------------------------------------
  2.    MDIDEMO.C -- Multiple Document Interface Demonstration
  3.                 (c) Charles Petzold, 1990
  4.   --------------------------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <stdlib.h>
  8. #include "mdidemo.h"
  9.  
  10. long FAR PASCAL FrameWndProc  (HWND, WORD, WORD, LONG) ;
  11. BOOL FAR PASCAL CloseEnumProc (HWND, LONG) ;
  12. long FAR PASCAL HelloWndProc  (HWND, WORD, WORD, LONG) ;
  13. long FAR PASCAL RectWndProc   (HWND, WORD, WORD, LONG) ;
  14.  
  15.           // structure for storing data unique to each Hello child window
  16.  
  17. typedef struct
  18.      {
  19.      short    nColor ;
  20.      COLORREF clrText ;
  21.      }
  22.      HELLODATA ;
  23.  
  24. typedef HELLODATA NEAR *NPHELLODATA ;
  25.  
  26.           // structure for storing data unique to each Rect child window
  27.  
  28. typedef struct
  29.      {
  30.      short cxClient ;
  31.      short cyClient ;
  32.      }
  33.      RECTDATA ;
  34.  
  35. typedef RECTDATA NEAR *NPRECTDATA ;
  36.  
  37.           // global variables
  38.  
  39. char   szFrameClass [] = "MdiFrame" ;
  40. char   szHelloClass [] = "MdiHelloChild" ;
  41. char   szRectClass  [] = "MdiRectChild" ;
  42. HANDLE hInst ;
  43. HMENU  hMenuInit, hMenuHello, hMenuRect ;
  44. HMENU  hMenuInitWindow, hMenuHelloWindow, hMenuRectWindow ;
  45.  
  46. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  47.                     LPSTR lpszCmdLine, int nCmdShow)
  48.      {
  49.      HANDLE   hAccel ;
  50.      HWND     hwndFrame, hwndClient ;
  51.      MSG      msg ;
  52.      WNDCLASS wndclass ;
  53.  
  54.      hInst = hInstance ;
  55.  
  56.      if (!hPrevInstance) 
  57.           {
  58.                     // Register the frame window class
  59.  
  60.           wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  61.           wndclass.lpfnWndProc   = FrameWndProc ;
  62.           wndclass.cbClsExtra    = 0 ;
  63.           wndclass.cbWndExtra    = 0 ;
  64.           wndclass.hInstance     = hInstance ;
  65.           wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  66.           wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  67.           wndclass.hbrBackground = COLOR_APPWORKSPACE + 1 ;
  68.           wndclass.lpszMenuName  = NULL ;
  69.           wndclass.lpszClassName = szFrameClass ;
  70.  
  71.           RegisterClass (&wndclass) ;
  72.  
  73.                     // Register the Hello child window class
  74.  
  75.           wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  76.           wndclass.lpfnWndProc   = HelloWndProc ;
  77.           wndclass.cbClsExtra    = 0 ;
  78.           wndclass.cbWndExtra    = sizeof (LOCALHANDLE) ;
  79.           wndclass.hInstance     = hInstance ;
  80.           wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  81.           wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  82.           wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
  83.           wndclass.lpszMenuName  = NULL ;
  84.           wndclass.lpszClassName = szHelloClass ;
  85.  
  86.           RegisterClass (&wndclass) ;
  87.  
  88.                     // Register the Rect child window class
  89.  
  90.           wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  91.           wndclass.lpfnWndProc   = RectWndProc ;
  92.           wndclass.cbClsExtra    = 0 ;
  93.           wndclass.cbWndExtra    = sizeof (LOCALHANDLE) ;
  94.           wndclass.hInstance     = hInstance ;
  95.           wndclass.hIcon         = NULL ;
  96.           wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  97.           wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
  98.           wndclass.lpszMenuName  = NULL ;
  99.           wndclass.lpszClassName = szRectClass ;
  100.  
  101.           RegisterClass (&wndclass) ;
  102.           }
  103.                // Obtain handles to three possible menus & submenus
  104.  
  105.      hMenuInit  = LoadMenu (hInst, "MdiMenuInit") ;
  106.      hMenuHello = LoadMenu (hInst, "MdiMenuHello") ;
  107.      hMenuRect  = LoadMenu (hInst, "MdiMenuRect") ;
  108.  
  109.      hMenuInitWindow  = GetSubMenu (hMenuInit,   INIT_MENU_POS) ;
  110.      hMenuHelloWindow = GetSubMenu (hMenuHello, HELLO_MENU_POS) ;
  111.      hMenuRectWindow  = GetSubMenu (hMenuRect,   RECT_MENU_POS) ;
  112.  
  113.                // Load accelerator table
  114.  
  115.      hAccel = LoadAccelerators (hInst, "MdiAccel") ;
  116.  
  117.                // Create the frame window
  118.  
  119.      hwndFrame = CreateWindow (szFrameClass, "MDI Demonstration",
  120.                                WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  121.                                CW_USEDEFAULT, CW_USEDEFAULT,
  122.                                CW_USEDEFAULT, CW_USEDEFAULT,
  123.                                NULL, hMenuInit, hInstance, NULL) ;
  124.  
  125.      hwndClient = GetWindow (hwndFrame, GW_CHILD) ;
  126.  
  127.      ShowWindow (hwndFrame, nCmdShow) ;
  128.      UpdateWindow (hwndFrame) ;
  129.  
  130.                // Enter the modified message loop
  131.  
  132.      while (GetMessage (&msg, NULL, 0, 0))
  133.           {
  134.           if (!TranslateMDISysAccel (hwndClient, &msg) &&
  135.               !TranslateAccelerator (hwndFrame, hAccel, &msg))
  136.                {
  137.                TranslateMessage (&msg) ;
  138.                DispatchMessage (&msg) ;
  139.                }
  140.           }
  141.      return msg.wParam ;
  142.      }
  143.  
  144. long FAR PASCAL FrameWndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  145.      {
  146.      static HWND        hwndClient ;
  147.      CLIENTCREATESTRUCT clientcreate ;
  148.      FARPROC            lpfnEnum ;
  149.      HWND               hwndChild, hwndNext ;
  150.      MDICREATESTRUCT    mdicreate ;
  151.  
  152.      switch (message)
  153.           {
  154.           case WM_CREATE:          // Create the client window
  155.  
  156.                clientcreate.hWindowMenu  = hMenuInitWindow ;
  157.                clientcreate.idFirstChild = IDM_FIRSTCHILD ;
  158.  
  159.                hwndClient = CreateWindow ("MDICLIENT", NULL,
  160.                               WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
  161.                               0, 0, 0, 0, hwnd, 1, hInst,
  162.                               (LPSTR) &clientcreate) ;
  163.                return 0 ;
  164.  
  165.           case WM_COMMAND:
  166.                switch (wParam)
  167.                     {
  168.                     case IDM_NEWHELLO:       // Create a Hello child window
  169.  
  170.                          mdicreate.szClass = szHelloClass ;
  171.                          mdicreate.szTitle = "Hello" ;
  172.                          mdicreate.hOwner  = hInst ;
  173.                          mdicreate.x       = CW_USEDEFAULT ;
  174.                          mdicreate.y       = CW_USEDEFAULT ;
  175.                          mdicreate.cx      = CW_USEDEFAULT ;
  176.                          mdicreate.cy      = CW_USEDEFAULT ;
  177.                          mdicreate.style   = 0 ;
  178.                          mdicreate.lParam  = NULL ;
  179.  
  180.                          hwndChild = SendMessage (hwndClient, WM_MDICREATE, 0,
  181.                                         (LONG) (LPMDICREATESTRUCT) &mdicreate) ;
  182.                          return 0 ;
  183.  
  184.                     case IDM_NEWRECT:        // Create a Rect child window
  185.  
  186.                          mdicreate.szClass = szRectClass ;
  187.                          mdicreate.szTitle = "Rectangles" ;
  188.                          mdicreate.hOwner  = hInst ;
  189.                          mdicreate.x       = CW_USEDEFAULT ;
  190.                          mdicreate.y       = CW_USEDEFAULT ;
  191.                          mdicreate.cx      = CW_USEDEFAULT ;
  192.                          mdicreate.cy      = CW_USEDEFAULT ;
  193.                          mdicreate.style   = 0 ;
  194.                          mdicreate.lParam  = NULL ;
  195.  
  196.                          hwndChild = SendMessage (hwndClient,  WM_MDICREATE, 0,
  197.                                         (LONG) (LPMDICREATESTRUCT) &mdicreate) ;
  198.                          return 0 ;
  199.  
  200.                     case IDM_CLOSE:          // Close the active window
  201.  
  202.                          hwndChild = LOWORD (SendMessage (hwndClient,
  203.                                                   WM_MDIGETACTIVE, 0, 0L)) ;
  204.  
  205.                          if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0L))
  206.                               SendMessage (hwndClient, WM_MDIDESTROY,
  207.                                            hwndChild, 0L) ;
  208.                          return 0 ;
  209.  
  210.                     case IDM_EXIT:           // Exit the program
  211.  
  212.                          SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
  213.                          return 0 ;
  214.  
  215.                                    // Messages for arranging windows
  216.                     case IDM_TILE:
  217.                          SendMessage (hwndClient, WM_MDITILE, 0, 0L) ;
  218.                          return 0 ;
  219.  
  220.                     case IDM_CASCADE:
  221.                          SendMessage (hwndClient, WM_MDICASCADE, 0, 0L) ;
  222.                          return 0 ;
  223.  
  224.                     case IDM_ARRANGE:
  225.                          SendMessage (hwndClient, WM_MDIICONARRANGE, 0, 0L) ;
  226.                          return 0 ;
  227.  
  228.                     case IDM_CLOSEALL:       // Attempt to close all children
  229.  
  230.                          lpfnEnum = MakeProcInstance (CloseEnumProc, hInst) ;
  231.                          EnumChildWindows (hwndClient, lpfnEnum, 0L) ;
  232.                          FreeProcInstance (lpfnEnum) ;
  233.                          return 0 ;
  234.  
  235.                     default:            // Pass to active child
  236.  
  237.                          hwndChild = LOWORD (SendMessage (hwndClient,
  238.                                                 WM_MDIGETACTIVE, 0, 0L)) ;
  239.  
  240.                         if (IsWindow (hwndChild))
  241.                              SendMessage (hwndChild, WM_COMMAND,
  242.                                           wParam, lParam) ;
  243.  
  244.                         break ;        // and then to DefFrameProc
  245.                     }
  246.                break ;
  247.  
  248.           case WM_QUERYENDSESSION:
  249.           case WM_CLOSE:                     // Attempt to close all children
  250.  
  251.                SendMessage (hwnd, WM_COMMAND, IDM_CLOSEALL, 0L) ;
  252.  
  253.                if (NULL != GetWindow (hwndClient, GW_CHILD))
  254.                     return 0 ;
  255.  
  256.                break ;   // ie, call DefFrameProc ;
  257.  
  258.           case WM_DESTROY :
  259.                PostQuitMessage (0) ;
  260.                return 0 ;
  261.           }
  262.                // Pass unprocessed messages to DefFrameProc (not DefWindowProc)
  263.  
  264.      return DefFrameProc (hwnd, hwndClient, message, wParam, lParam) ;
  265.      }
  266.  
  267. BOOL FAR PASCAL CloseEnumProc (HWND hwnd, LONG lParam)
  268.      {
  269.      if (GetWindow (hwnd, GW_OWNER))         // check for icon title
  270.           return 1 ;
  271.  
  272.      SendMessage (GetParent (hwnd), WM_MDIRESTORE, hwnd, 0L) ;
  273.  
  274.      if (!SendMessage (hwnd, WM_QUERYENDSESSION, 0, 0L))
  275.           return 1 ;
  276.  
  277.      SendMessage (GetParent (hwnd), WM_MDIDESTROY, hwnd, 0L) ;
  278.           return 1 ;
  279.      }
  280.  
  281. long FAR PASCAL HelloWndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  282.      {
  283.      static COLORREF clrTextArray [] = { RGB (0,   0, 0), RGB (255, 0,   0),
  284.                                          RGB (0, 255, 0), RGB (  0, 0, 255),
  285.                                          RGB (255, 255, 255) } ;
  286.      static HWND     hwndClient, hwndFrame ;
  287.      HDC             hdc ;
  288.      HMENU           hMenu ;
  289.      LOCALHANDLE     hHelloData ;
  290.      NPHELLODATA     npHelloData ;
  291.      PAINTSTRUCT     ps ;
  292.      RECT            rect ;
  293.  
  294.      switch (message)
  295.           {
  296.           case WM_CREATE:
  297.                          // Allocate memory for window private data
  298.  
  299.                hHelloData = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT,
  300.                                         sizeof (HELLODATA)) ;
  301.  
  302.                npHelloData = (NPHELLODATA) LocalLock (hHelloData) ;
  303.                npHelloData->nColor  = IDM_BLACK ;
  304.                npHelloData->clrText = RGB (0, 0, 0) ;
  305.                LocalUnlock (hHelloData) ;
  306.                SetWindowWord (hwnd, 0, hHelloData) ;
  307.  
  308.                          // Save some window handles
  309.  
  310.                hwndClient = GetParent (hwnd) ;
  311.                hwndFrame  = GetParent (hwndClient) ;
  312.                return 0 ;
  313.  
  314.           case WM_COMMAND:
  315.                switch (wParam)
  316.                     {
  317.                     case IDM_BLACK:
  318.                     case IDM_RED:
  319.                     case IDM_GREEN:
  320.                     case IDM_BLUE:
  321.                     case IDM_WHITE:
  322.                                    // Change the text color
  323.  
  324.                          hHelloData  = GetWindowWord (hwnd, 0) ;
  325.                          npHelloData = (NPHELLODATA) LocalLock (hHelloData) ;
  326.  
  327.                          hMenu = GetMenu (hwndFrame) ;
  328.  
  329.                          CheckMenuItem (hMenu, npHelloData->nColor,
  330.                                                MF_UNCHECKED) ;
  331.                          npHelloData->nColor = wParam ;
  332.                          CheckMenuItem (hMenu, npHelloData->nColor,
  333.                                                MF_CHECKED) ;
  334.  
  335.                          npHelloData->clrText =
  336.                                clrTextArray [wParam - IDM_BLACK] ;
  337.  
  338.                          LocalUnlock (hHelloData) ;
  339.                          InvalidateRect (hwnd, NULL, FALSE) ;
  340.                     }
  341.                return 0 ;
  342.  
  343.           case WM_PAINT:
  344.                          // Paint the window
  345.  
  346.            hdc = BeginPaint (hwnd, &ps) ;
  347.  
  348.                hHelloData  = GetWindowWord (hwnd, 0) ;
  349.                npHelloData = (NPHELLODATA) LocalLock (hHelloData) ;
  350.                SetTextColor (hdc, npHelloData->clrText) ;
  351.                LocalUnlock (hHelloData) ;
  352.  
  353.                GetClientRect (hwnd, &rect) ;
  354.  
  355.                DrawText (hdc, "Hello, World!", -1, &rect,
  356.                          DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
  357.  
  358.                EndPaint (hwnd, &ps) ;
  359.                return 0 ;
  360.  
  361.           case WM_MDIACTIVATE:
  362.  
  363.                          // Set the Hello menu if gaining focus
  364.  
  365.                if (wParam == TRUE)
  366.                     SendMessage (hwndClient, WM_MDISETMENU, 0,
  367.                                  MAKELONG (hMenuHello, hMenuHelloWindow)) ;
  368.  
  369.                          // check or uncheck menu item
  370.  
  371.                hHelloData  = GetWindowWord (hwnd, 0) ;
  372.                npHelloData = (NPHELLODATA) LocalLock (hHelloData) ;
  373.                CheckMenuItem (hMenuHello, npHelloData->nColor,
  374.                               wParam ? MF_CHECKED : MF_UNCHECKED) ;
  375.                LocalUnlock (hHelloData) ;
  376.  
  377.                          // Set the Init menu if losing focus
  378.  
  379.                if (wParam == FALSE)
  380.                     SendMessage (hwndClient, WM_MDISETMENU, 0,
  381.                                  MAKELONG (hMenuInit, hMenuInitWindow)) ;
  382.  
  383.                DrawMenuBar (hwndFrame) ;
  384.                return 0 ;
  385.  
  386.           case WM_QUERYENDSESSION:
  387.           case WM_CLOSE:
  388.                if (IDOK != MessageBox (hwnd, "OK to close window?", "Hello",
  389.                                        MB_ICONQUESTION | MB_OKCANCEL))
  390.                     return 0 ;
  391.  
  392.                break ;   // ie, call DefMDIChildProc
  393.  
  394.           case WM_DESTROY:
  395.                hHelloData = GetWindowWord (hwnd, 0) ;
  396.                LocalFree (hHelloData) ;
  397.                return 0 ;
  398.           }
  399.                // Pass unprocessed message to DefMDIChildProc
  400.  
  401.      return DefMDIChildProc (hwnd, message, wParam, lParam) ;
  402.      }
  403.  
  404. long FAR PASCAL RectWndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  405.      {
  406.      static HWND hwndClient, hwndFrame ;
  407.      HPEN        hBrush ;
  408.      HDC         hdc ;
  409.      LOCALHANDLE hRectData ;
  410.      NPRECTDATA  npRectData ;
  411.      PAINTSTRUCT ps ;
  412.      short       xLeft, xRight, yTop, yBottom, nRed, nGreen, nBlue ;
  413.  
  414.      switch (message)
  415.           {
  416.           case WM_CREATE:
  417.                          // Allocate memory for window private data
  418.  
  419.                hRectData = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT,
  420.                                        sizeof (RECTDATA)) ;
  421.  
  422.                SetWindowWord (hwnd, 0, hRectData) ;
  423.  
  424.                          // Start the timer going
  425.  
  426.                SetTimer (hwnd, 1, 250, NULL) ;
  427.  
  428.                          // Save some window handles
  429.  
  430.                hwndClient = GetParent (hwnd) ;
  431.                hwndFrame  = GetParent (hwndClient) ;
  432.                return 0 ;
  433.  
  434.           case WM_SIZE:            // Save the window size
  435.  
  436.                hRectData  = GetWindowWord (hwnd, 0) ;
  437.                npRectData = (NPRECTDATA) LocalLock (hRectData) ;
  438.  
  439.                npRectData->cxClient = LOWORD (lParam) ;
  440.                npRectData->cyClient = HIWORD (lParam) ;
  441.  
  442.                LocalUnlock (hRectData) ;
  443.  
  444.                break ;        // WM_SIZE must be processed by DefMDIChildProc
  445.  
  446.           case WM_TIMER:           // Display a random rectangle
  447.  
  448.                hRectData  = GetWindowWord (hwnd, 0) ;
  449.                npRectData = (NPRECTDATA) LocalLock (hRectData) ;
  450.  
  451.                xLeft   = rand () % npRectData->cxClient ;
  452.                xRight  = rand () % npRectData->cxClient ;
  453.                yTop    = rand () % npRectData->cyClient ;
  454.                yBottom = rand () % npRectData->cyClient ;
  455.                nRed    = rand () & 255 ;
  456.                nGreen  = rand () & 255 ;
  457.                nBlue   = rand () & 255 ;
  458.  
  459.                hdc = GetDC (hwnd) ;
  460.                hBrush = CreateSolidBrush (RGB (nRed, nGreen, nBlue)) ;
  461.                SelectObject (hdc, hBrush) ;
  462.  
  463.                Rectangle (hdc, min (xLeft, xRight), min (yTop, yBottom),
  464.                                max (xLeft, xRight), max (yTop, yBottom)) ;
  465.  
  466.                ReleaseDC (hwnd, hdc) ;
  467.                DeleteObject (hBrush) ;
  468.                LocalUnlock (hRectData) ;
  469.                return 0 ;
  470.  
  471.           case WM_PAINT:           // Clear the window
  472.  
  473.                InvalidateRect (hwnd, NULL, TRUE) ;
  474.                hdc = BeginPaint (hwnd, &ps) ;
  475.                EndPaint (hwnd, &ps) ;
  476.                return 0 ;
  477.  
  478.           case WM_MDIACTIVATE:     // Set the appropriate menu
  479.                if (wParam == TRUE)
  480.                     SendMessage (hwndClient, WM_MDISETMENU, 0,
  481.                                  MAKELONG (hMenuRect, hMenuRectWindow)) ;
  482.                else
  483.                     SendMessage (hwndClient, WM_MDISETMENU, 0,
  484.                                  MAKELONG (hMenuInit, hMenuInitWindow)) ;
  485.  
  486.                DrawMenuBar (hwndFrame) ;
  487.                return 0 ;
  488.  
  489.           case WM_DESTROY:
  490.                hRectData = GetWindowWord (hwnd, 0) ;
  491.                LocalFree (hRectData) ;
  492.                KillTimer (hwnd, 1) ;
  493.                return 0 ;
  494.           }
  495.                // Pass unprocessed message to DefMDIChildProc
  496.  
  497.      return DefMDIChildProc (hwnd, message, wParam, lParam) ;
  498.      }
  499.