home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 7.ddi / MWHC.007 / EA < prev    next >
Encoding:
Text File  |  1991-09-05  |  36.7 KB  |  940 lines

  1. /***************************************************************************
  2.  *                                                                         *
  3.  *  PROGRAM     : MultiPad.c                                               *
  4.  *                                                                         *
  5.  *  PURPOSE     : To give a multi-Notepad demonstration of the new MDI     *
  6.  *                API in Windows 3.0                                       *
  7.  *                                                                         *
  8.  *  FUNCTIONS   : WinMain()           - Calls the initialization function  *
  9.  *                                      and processes message loop         *
  10.  *                                                                         *
  11.  *                MPFrameWndProc()    - Window function for the "frame"    *
  12.  *                                      window, which controls the menu    *
  13.  *                                      and contains the MDI document      *
  14.  *                                      windows as child windows.          *
  15.  *                                                                         *
  16.  *                MPMDIChildWndProc() - Window function for the individual *
  17.  *                                      document windows                   *
  18.  *                                                                         *
  19.  *                InitializeMenu()    - Handles enabling/greying of menu   *
  20.  *                                      items according to the app's state.*
  21.  *                                                                         *
  22.  *                CloseAllChildren    - Destroys all MDI child windows.    *
  23.  *                                                                         *
  24.  *                CommandHandler()    - Processes the "frame" window's     *
  25.  *                                      WM_COMMAND messages.               *
  26.  *                                                                         *
  27.  *                AboutDlgProc()      - Dialog function for the ubiquitous *
  28.  *                                      About.. dialog.                    *
  29.  *                                                                         *
  30.  *                SetWrap()           - Alters word wrapping in the edit   *
  31.  *                                      control.                           *
  32.  *                                                                         *
  33.  *                MPError()           - Flashes an error messagebox.       *
  34.  *                                                                         *
  35.  *                QueryCloseChild     - Prompts for saving current MDI     *
  36.  *                                      child window.                      *
  37.  *                                                                         *
  38.  *                QueryCloseAllChildren() - Asks whether it is OK to close *
  39.  *                                          down app.                      *
  40.  *                                                                         *
  41.  ***************************************************************************/
  42.  
  43. #include "multipad.h"
  44.  
  45. /* global variables used in this module or among more than one module */
  46. HANDLE hInst;                       /* Program instance handle               */
  47. HANDLE hAccel;                      /* Main accelerator resource             */
  48. HWND hwndFrame           = NULL;    /* Handle to main window                 */
  49. HWND hwndMDIClient       = NULL;    /* Handle to MDI client                  */
  50. HWND hwndActive          = NULL;    /* Handle to currently activated child   */
  51. HWND hwndActiveEdit      = NULL;    /* Handle to edit control                */
  52. LONG styleDefault    = WS_MAXIMIZE; /* Default style bits for child windows  */
  53.                                     /* The first window is created maximized */
  54.                                     /* to resemble Notepad.  Later children  */
  55.                                     /* are normal windows.                   */
  56. LP48STR lpMenu         = IDMULTIPAD;  /* Contains the resource id of the       */
  57.                                     /* current frame menu                    */
  58.  
  59.  
  60. /* Forward declarations of helper functions in this module */
  61. VOID NEAR PASCAL InitializeMenu (HANDLE);
  62. VOID NEAR PASCAL CommandHandler (HWND,WORD);
  63. VOID NEAR PASCAL SetWrap (HWND,BOOL);
  64. BOOL NEAR PASCAL QueryCloseAllChildren ( VOID );
  65. BOOL  NEAR PASCAL QueryCloseChild (HWND);
  66.  
  67. /****************************************************************************
  68.  *                                                                          *
  69.  *  FUNCTION   : WinMain(HANDLE, HANDLE, LPSTR, int)                        *
  70.  *                                                                          *
  71.  *  PURPOSE    : Creates the "frame" window, does some initialization and   *
  72.  *               enters the message loop.                                   *
  73.  *                                                                          *
  74.  ****************************************************************************/
  75. int NEAR PASCAL WinMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
  76.  
  77. HANDLE hInstance;
  78. HANDLE hPrevInstance;
  79. LPSTR  lpszCmdLine;
  80. int    nCmdShow;
  81. {
  82.     MSG msg;
  83.  
  84.     hInst = hInstance;
  85.  
  86.     /* If this is the first instance of the app. register window classes */
  87.     if (!hPrevInstance){
  88.         if (!InitializeApplication ())
  89.             return 0;
  90.     }
  91.  
  92.     /* Create the frame and do other initialization */
  93.     if (!InitializeInstance (lpszCmdLine, nCmdShow))
  94.         return 0;
  95.  
  96.     /* Enter main message loop */
  97.     while (GetMessage (&msg, NULL, 0, 0)){
  98.         /* If a keyboard message is for the MDI , let the MDI client
  99.          * take care of it.  Otherwise, check to see if it's a normal
  100.          * accelerator key (like F3 = find next).  Otherwise, just handle
  101.          * the message as usual.
  102.          */
  103.         if ( !TranslateMDISysAccel (hwndMDIClient, &msg) &&
  104.              !TranslateAccelerator (hwndFrame, hAccel, &msg)){
  105.             TranslateMessage (&msg);
  106.             DispatchMessage (&msg);
  107.         }
  108.     }
  109.     return 0;
  110. }
  111.  
  112. /****************************************************************************
  113.  *                                                                          *
  114.  *  FUNCTION   : MPFrameWndProc (hwnd, msg, wParam, lParam )                *
  115.  *                                                                          *
  116.  *  PURPOSE    : The window function for the "frame" window, which controls *
  117.  *               the menu and encompasses all the MDI child windows. Does   *
  118.  *               the major part of the message processing. Specifically, in *
  119.  *               response to:                                               *
  120.  *                                                                          *
  121.  *                   WM_CREATE          : Creates and displays the "frame". *
  122.  *                                                                          *
  123.  *                   WM_INITMENU        : Sets up the state of the menu.    *
  124.  *                                                                          *
  125.  *                   WM_WININICHANGE &  : If default printer characteristics*
  126.  *                   WM_DEVMODECHANGE     have been changed, reinitialises  *
  127.  *                                        printer DC.                       *
  128.  *                                                                          *
  129.  *                   WM_COMMAND         : Passes control to a command-      *
  130.  *                                        handling function.                *
  131.  *                                                                          *
  132.  *                   WM_CLOSE           : Quits the app. if all the child   *
  133.  *                                        windows agree.                    *
  134.  *                                                                          *
  135.  *                   WM_QUERYENDSESSION : Checks that all child windows     *
  136.  *                                        agree to quit.                    *
  137.  *                                                                          *
  138.  *                   WM_DESTROY         : Destroys frame window and quits   *
  139.  *                                        app.                              *
  140.  *                                                                          *
  141.  ****************************************************************************/
  142. LONG FAR PASCAL MPFrameWndProc ( hwnd, msg, wParam, lParam )
  143.  
  144. register HWND    hwnd;
  145. WORD             msg;
  146. register WORD    wParam;
  147. LONG             lParam;
  148.  
  149. {
  150.     switch (msg){
  151.         case WM_CREATE:{
  152.  
  153.             CLIENTCREATESTRUCT ccs;
  154.             HDC hdc;
  155.  
  156.             /* Find window menu where children will be listed */
  157.             ccs.hWindowMenu = GetSubMenu (GetMenu(hwnd),WINDOWMENU);
  158.             ccs.idFirstChild = IDM_WINDOWCHILD;
  159.  
  160.             /* Create the MDI client filling the client area */
  161.             hwndMDIClient = CreateWindow ("mdiclient",
  162.                                           NULL,
  163.                                           WS_CHILD | WS_CLIPCHILDREN |
  164.                                           WS_VSCROLL | WS_HSCROLL,
  165.                                           0,
  166.                                           0,
  167.                                           0,
  168.                                           0,
  169.                                           hwnd,
  170.                                           0xCAC,
  171.                                           hInst,
  172.                                           (LP48STR)&ccs);
  173.  
  174.  
  175.             ShowWindow (hwndMDIClient,SW_SHOW);
  176.  
  177.             /* Check if printer can be initialized */
  178.             if ((hdc = GetPrinterDC ()) != NULL){
  179.                 DeleteDC (hdc);
  180.             }
  181.  
  182.             break;
  183.         }
  184.  
  185.         case WM_INITMENU:
  186.             /* Set up the menu state */
  187.             InitializeMenu ((HMENU)wParam);
  188.             break;
  189.  
  190.         case WM_WININICHANGE:
  191.         case WM_DEVMODECHANGE:{
  192.  
  193.             /*  If control panel changes default printer characteristics,
  194.              *  reinitialize our printer information...
  195.              */
  196.             HDC hdc;
  197.  
  198.             if ((hdc = GetPrinterDC ()) != NULL){
  199.                 DeleteDC (hdc);
  200.             }
  201.             break;
  202.         }
  203.  
  204.  
  205.         case WM_COMMAND:
  206.             /* Direct all menu selection or accelerator commands to another
  207.              * function
  208.              */
  209.             CommandHandler (hwnd,wParam);
  210.             break;
  211.  
  212.         case WM_CLOSE:
  213.             /* don't close if any children cancel the operation */
  214.             if (!QueryCloseAllChildren ())
  215.                 break;
  216.             DestroyWindow (hwnd);
  217.             break;
  218.  
  219.         case WM_QUERYENDSESSION:
  220.             /*  Before session ends, check that all files are saved */
  221.             return QueryCloseAllChildren ();
  222.  
  223.         case WM_DESTROY:
  224.             PostQuitMessage (0);
  225.             break;
  226.  
  227.         default:
  228.             /*  use DefFrameProc() instead of DefWindowProc() since there
  229.              *  are things that have to be handled differently because of MDI
  230.              */
  231.             return DefFrameProc (hwnd,hwndMDIClient,msg,wParam,lParam);
  232.     }
  233.     return 0;
  234. }
  235.  
  236. /****************************************************************************
  237.  *                                                                          *
  238.  *  FUNCTION   : MPMDIWndProc ( hwnd, msg, wParam, lParam )                 *
  239.  *                                                                          *
  240.  *  PURPOSE    : The window function for the individual document windows,   *
  241.  *               each of which has a "note". Each of these windows contain  *
  242.  *               one multi-line edit control filling their client area.     *
  243.  *               In response to the following:                              *
  244.  *                                                                          *
  245.  *                   WM_CREATE          : Creates & diplays an edit control *
  246.  *                                        and does some initialization.     *
  247.  *                                                                          *
  248.  *                   WM_MDIACTIVATE     : Activates/deactivates the child.  *
  249.  *                                                                          *
  250.  *                   WM_SETFOCUS        : Sets focus on the edit control.   *
  251.  *                                                                          *
  252.  *                   WM_SIZE            : Resizes the edit control.         *
  253.  *                                                                          *
  254.  *                   WM_COMMAND         : Processes some of the edit        *
  255.  *                                        commands, saves files and alters  *
  256.  *                                        the edit wrap state.              *
  257.  *                                                                          *
  258.  *                   WM_CLOSE           : Closes child if it is ok to do so.*
  259.  *                                                                          *
  260.  *                   WM_QUERYENDSESSION : Same as above.                    *
  261.  *                                                                          *
  262.  ****************************************************************************/
  263.  
  264. LONG FAR PASCAL MPMDIChildWndProc ( hwnd, msg, wParam, lParam )
  265.  
  266. register HWND   hwnd;
  267. WORD            msg;
  268. register WORD   wParam;
  269. LONG            lParam;
  270.  
  271. {
  272.     HWND hwndEdit;
  273.  
  274.     switch (msg){
  275.         case WM_CREATE:
  276.             /* Create an edit control */
  277.             hwndEdit = CreateWindow ("edit",
  278.                                      NULL,
  279.                                      WS_CHILD|WS_HSCROLL|WS_MAXIMIZE|WS_VISIBLE|WS_VSCROLL|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_MULTILINE,
  280.                                      0,
  281.                                      0,
  282.                                      0,
  283.                                      0,
  284.                                      hwnd,
  285.                                      ID_EDIT,
  286.                                      hInst,
  287.                                      NULL);
  288.  
  289.             /* Remember the window handle and initialize some window attributes */
  290.             SetWindowWord (hwnd, GWW_HWNDEDIT, (WORD)hwndEdit);
  291.             SetWindowWord (hwnd, GWW_CHANGED, FALSE);
  292.             SetWindowWord (hwnd, GWW_WORDWRAP, FALSE);
  293.             SetWindowWord (hwnd, GWW_UNTITLED, TRUE);
  294.             SetFocus (hwndEdit);
  295.             break;
  296.  
  297.         case WM_MDIACTIVATE:
  298.             /* If we're activating this child, remember it */
  299.             if (wParam){
  300.                 hwndActive     = hwnd;
  301.                 hwndActiveEdit = (HWND)GetWindowWord (hwnd, GWW_HWNDEDIT);
  302.             }
  303.             else{
  304.                 hwndActive     = NULL;
  305.                 hwndActiveEdit = NULL;
  306.             }
  307.             break;
  308.  
  309.         case WM_QUERYENDSESSION:
  310.             /* Prompt to save the child */
  311.             return !QueryCloseChild (hwnd);
  312.  
  313.         case WM_CLOSE:
  314.             /* If its OK to close the child, do so, else ignore */
  315.             if (QueryCloseChild (hwnd))
  316.                 goto CallDCP;
  317.             else
  318.                 break;
  319.  
  320.         case WM_SIZE:{
  321.             RECT rc;
  322.  
  323.             /* On creation or resize, size the edit control. */
  324.             hwndEdit = GetWindowWord (hwnd, GWW_HWNDEDIT);
  325.             GetClientRect (hwnd, &rc);
  326.             MoveWindow (hwndEdit,
  327.                         rc.left,
  328.                         rc.top,
  329.                         rc.right-rc.left,
  330.                         rc.bottom-rc.top,
  331.                         TRUE);
  332.             goto CallDCP;
  333.         }
  334.  
  335.         case WM_SETFOCUS:
  336.             SetFocus (GetWindowWord (hwnd, GWW_HWNDEDIT));
  337.             break;
  338.  
  339.         case WM_COMMAND:
  340.             switch (wParam){
  341.                 case ID_EDIT:
  342.                     switch (HIWORD(lParam)){
  343.                         case EN_CHANGE:
  344.  
  345.                             /* If the contents of the edit control have changed,
  346.                                set the changed flag
  347.                              */
  348.                             SetWindowWord (hwnd, GWW_CHANGED, TRUE);
  349.                             break;
  350.  
  351.                         case EN_ERRSPACE:
  352.                             /* If the control is out of space, honk */
  353.                             MessageBeep (0);
  354.                             break;
  355.  
  356.                         default:
  357.                             goto CallDCP;
  358.                     }
  359.                     break;
  360.  
  361.                 case IDM_FILESAVE:
  362.                     /* If empty file, ignore save */
  363.                     if ((GetWindowWord(hwnd, GWW_UNTITLED)) && (!ChangeFile(hwnd)))
  364.                         break;
  365.  
  366.                     /* Save the contents of the edit control and reset the
  367.                      * changed flag
  368.                      */
  369.                     SaveFile (hwnd);
  370.                     SetWindowWord (hwnd, GWW_CHANGED, FALSE);
  371.                     break;
  372.  
  373.                 case IDM_EDITWRAP: {
  374.                     int fWrap = GetWindowWord (hwnd, GWW_WORDWRAP);
  375.  
  376.                     /* Set the wrap state, or report it */
  377.                     if (LOWORD (lParam)){
  378.                         fWrap = !fWrap;
  379.                         SetWrap (hwnd, fWrap);
  380.                     }
  381.  
  382.                     /* return wrap state */
  383.                     return fWrap;
  384.                 }
  385.  
  386.                 default:
  387.                     goto CallDCP;
  388.             }
  389.             break;
  390.  
  391.     case WM_GETTEXTLENGTH:
  392.         return 0;
  393.  
  394.         default:
  395. CallDCP:
  396.             /* Again, since the MDI default behaviour is a little different,
  397.              * call DefMDIChildProc instead of DefWindowProc()
  398.              */
  399.             return DefMDIChildProc (hwnd, msg, wParam, lParam);
  400.     }
  401.     return FALSE;
  402. }
  403.  
  404.  
  405. /****************************************************************************
  406.  *                                                                          *
  407.  *  FUNCTION   : AboutDlgProc ( hwnd, msg, wParam, lParam )                 *
  408.  *                                                                          *
  409.  *  PURPOSE    : Dialog function for the About MultiPad... dialog.          *
  410.  *                                                                          *
  411.  ****************************************************************************/
  412. BOOL FAR PASCAL AboutDlgProc ( hwnd, msg, wParam, lParam )
  413. HWND          hwnd;
  414. register WORD msg;
  415. register WORD wParam;
  416. LONG          lParam;
  417. {
  418.     switch (msg){
  419.         case WM_INITDIALOG:
  420.             /* nothing to initialize */
  421.             break;
  422.  
  423.         case WM_COMMAND:
  424.             switch (wParam){
  425.                 case IDOK:
  426.                 case IDCANCEL:
  427.                     EndDialog(hwnd, 0);
  428.                     break;
  429.  
  430.                 default:
  431.                     return FALSE;
  432.             }
  433.             break;
  434.  
  435.         default:
  436.             return FALSE;
  437.     }
  438.  
  439.     return TRUE;
  440. }
  441.  
  442. /****************************************************************************
  443.  *                                                                          *
  444.  *  FUNCTION   : Initializemenu ( hMenu )                                   *
  445.  *                                                                          *
  446.  *  PURPOSE    : Sets up greying, enabling and checking of main menu items  *
  447.  *               based on the app's state.                                  *
  448.  *                                                                          *
  449.  ****************************************************************************/
  450. VOID NEAR PASCAL InitializeMenu ( hmenu )
  451. register HANDLE hmenu;
  452. {
  453.     register WORD status;
  454.     int           i;
  455.     long          l;
  456.  
  457.     /* Is there any active child to talk to? */
  458.     if (hwndActiveEdit){
  459.         /* If edit control can respond to an undo request, enable the
  460.          * undo selection.
  461.          */
  462.         if (SendMessage (hwndActiveEdit, EM_CANUNDO, 0, 0L))
  463.             status = MF_ENABLED;
  464.         else
  465.             status = MF_GRAYED;
  466.         EnableMenuItem (hmenu, IDM_EDITUNDO, status);
  467.  
  468.         /* If edit control is non-empty, allow cut/copy/clear */
  469.         l      = SendMessage (hwndActiveEdit, EM_GETSEL, 0, 0L);
  470.         status = (HIWORD(l) == LOWORD(l)) ? MF_GRAYED : MF_ENABLED;
  471.         EnableMenuItem (hmenu, IDM_EDITCUT, status);
  472.         EnableMenuItem (hmenu, IDM_EDITCOPY, status);
  473.         EnableMenuItem (hmenu, IDM_EDITCLEAR, status);
  474.  
  475.         status=MF_GRAYED;
  476.         /* If the clipboard contains some CF_TEXT data, allow paste */
  477.         if (OpenClipboard (hwndFrame)){
  478.             int wFmt = 0;
  479.  
  480.             while ((wFmt = EnumClipboardFormats (wFmt)) != 0)
  481.                 if (wFmt == CF_TEXT){
  482.                     status = MF_ENABLED;
  483.                     break;
  484.                 }
  485.  
  486.             CloseClipboard ();
  487.         }
  488.         EnableMenuItem (hmenu, IDM_EDITPASTE, status);
  489.  
  490.         /* Set the word wrap state for the window */
  491.         if ((WORD) SendMessage (hwndActive, WM_COMMAND, IDM_EDITWRAP, 0L))
  492.             status = MF_CHECKED;
  493.         else
  494.             status = MF_UNCHECKED;
  495.         CheckMenuItem (hmenu, IDM_EDITWRAP, status);
  496.  
  497.         /* Enable search menu items only if there is a search string */
  498.         if (*szSearch)
  499.             status = MF_ENABLED;
  500.         else
  501.             status = MF_GRAYED;
  502.         EnableMenuItem (hmenu, IDM_SEARCHNEXT, status);
  503.         EnableMenuItem (hmenu, IDM_SEARCHPREV, status);
  504.  
  505.         /* Enable File/Print only if a printer is available */
  506.         status = iPrinter ? MF_ENABLED : MF_GRAYED;
  507.         EnableMenuItem (hmenu, IDM_FILEPRINT, status);
  508.  
  509.         /* select all and wrap toggle always enabled */
  510.         status = MF_ENABLED;
  511.         EnableMenuItem(hmenu, IDM_EDITSELECT, status);
  512.         EnableMenuItem(hmenu, IDM_EDITWRAP, status);
  513.         EnableMenuItem(hmenu, IDM_SEARCHFIND, status);
  514.     }
  515.     else {
  516.         /* There are no active child windows */
  517.         status = MF_GRAYED;
  518.  
  519.         /* No active window, so disable everything */
  520.         for (i = IDM_EDITFIRST; i <= IDM_EDITLAST; i++)
  521.             EnableMenuItem (hmenu, i, status);
  522.  
  523.         CheckMenuItem (hmenu, IDM_EDITWRAP, MF_UNCHECKED);
  524.  
  525.         for (i = IDM_SEARCHFIRST; i <= IDM_SEARCHLAST; i++)
  526.             EnableMenuItem (hmenu, i, status);
  527.  
  528.         EnableMenuItem (hmenu, IDM_FILEPRINT, status);
  529.  
  530.     }
  531.  
  532.     /* The following menu items are enabled if there is an active window */
  533.     EnableMenuItem (hmenu, IDM_FILESAVE, status);
  534.     EnableMenuItem (hmenu, IDM_FILESAVEAS, status);
  535.     EnableMenuItem (hmenu, IDM_WINDOWTILE, status);
  536.     EnableMenuItem (hmenu, IDM_WINDOWCASCADE, status);
  537.     EnableMenuItem (hmenu, IDM_WINDOWICONS, status);
  538.     EnableMenuItem (hmenu, IDM_WINDOWCLOSEALL, status);
  539.  
  540.     /* Allow printer setup only if printer driver supports device initialization */
  541.     if (iPrinter < 2)
  542.         status = MF_GRAYED;
  543.     EnableMenuItem ( hmenu, IDM_FILESETUP, status);
  544.  
  545. }
  546.  
  547. /****************************************************************************
  548.  *                                                                          *
  549.  *  FUNCTION   : CloseAllChildren ()                                        *
  550.  *                                                                          *
  551.  *  PURPOSE    : Destroys all MDI child windows.                            *
  552.  *                                                                          *
  553.  ****************************************************************************/
  554. VOID NEAR PASCAL CloseAllChildren (void)
  555. {
  556.     register HWND hwndT;
  557.  
  558.     /* hide the MDI client window to avoid multiple repaints */
  559.     ShowWindow(hwndMDIClient,SW_HIDE);
  560.  
  561.     /* As long as the MDI client has a child, destroy it */
  562.     while ((hwndT = GetWindow (hwndMDIClient, GW_CHILD)) != 0){
  563.  
  564.         /* Skip the icon title windows */
  565.         while (hwndT && GetWindow (hwndT, GW_OWNER))
  566.             hwndT = GetWindow (hwndT, GW_HWNDNEXT);
  567.  
  568.         if (!hwndT)
  569.             break;
  570.  
  571.         SendMessage (hwndMDIClient, WM_MDIDESTROY, (WORD)hwndT, 0L);
  572.     }
  573. }
  574.  
  575. /****************************************************************************
  576.  *                                                                          *
  577.  *  FUNCTION   : CommandHandler ()                                          *
  578.  *                                                                          *
  579.  *  PURPOSE    : Processes all "frame" WM_COMMAND messages.                 *
  580.  *                                                                          *
  581.  ****************************************************************************/
  582. VOID NEAR PASCAL CommandHandler ( hwnd, wParam )
  583. register HWND hwnd;
  584. register WORD wParam;
  585.  
  586. {
  587.     switch (wParam){
  588.         case IDM_FILENEW:
  589.             /* Add a new, empty MDI child */
  590.             AddFile (NULL);
  591.             break;
  592.  
  593.         case IDM_FILEOPEN:
  594.             ReadFile (hwnd);
  595.             break;
  596.  
  597.         case IDM_FILESAVE:
  598.             /* Save the active child MDI */
  599.             SendMessage (hwndActive, WM_COMMAND, IDM_FILESAVE, 0L);
  600.             break;
  601.  
  602.         case IDM_FILESAVEAS:
  603.             /* Save active child MDI under another name */
  604.             if (ChangeFile (hwndActive))
  605.                 SendMessage (hwndActive, WM_COMMAND, IDM_FILESAVE, 0L);
  606.             break;
  607.  
  608.         case IDM_FILEPRINT:
  609.             /* Print the active child MDI */
  610.             PrintFile (hwndActive);
  611.             break;
  612.  
  613.         case IDM_FILESETUP:
  614.             /* Set up the printer environment for this app */
  615.             GetInitializationData (hwnd);
  616.             break;
  617.  
  618.         case IDM_FILEMENU:{
  619.  
  620.               /* lengthen / shorten the size of the MDI menu */
  621.               HMENU hMenu;
  622.               HMENU hWindowMenu;
  623.               int i;
  624.  
  625.               if (lpMenu == IDMULTIPAD){
  626.                   lpMenu = IDMULTIPAD2;
  627.                   i      = SHORTMENU;
  628.               }
  629.               else{
  630.                   lpMenu = IDMULTIPAD;
  631.                   i      = WINDOWMENU;
  632.               }
  633.  
  634.               hMenu = LoadMenu (hInst, lpMenu);
  635.               hWindowMenu = GetSubMenu (hMenu, i);
  636.  
  637.               /* Set the new menu */
  638.               hMenu = (HMENU)SendMessage (hwndMDIClient,
  639.                                           WM_MDISETMENU,
  640.                                           0,
  641.                                           MAKELONG(hMenu,hWindowMenu));
  642.  
  643.               DestroyMenu (hMenu);
  644.               DrawMenuBar (hwndFrame);
  645.               break;
  646.         }
  647.  
  648.         case IDM_FILEEXIT:
  649.             /* Close Multipad */
  650.             SendMessage (hwnd, WM_CLOSE, 0, 0L);
  651.             break;
  652.  
  653.         case IDM_HELPABOUT:{
  654.             /* Bring up the ubiquitous Ego box */
  655.             FARPROC lpfn;
  656.  
  657.             lpfn = MakeProcInstance(AboutDlgProc, hInst);
  658.             DialogBox (hInst, IDD_ABOUT, hwnd, lpfn);
  659.             FreeProcInstance (lpfn);
  660.             break;
  661.         }
  662.  
  663.         /* The following are edit commands. Pass these off to the active
  664.          * child's edit control window.
  665.          */
  666.         case IDM_EDITCOPY:
  667.             SendMessage (hwndActiveEdit, WM_COPY, 0, 0L);
  668.             break;
  669.  
  670.         case IDM_EDITPASTE:
  671.             SendMessage (hwndActiveEdit, WM_PASTE, 0, 0L);
  672.             break;
  673.  
  674.         case IDM_EDITCUT:
  675.             SendMessage (hwndActiveEdit, WM_CUT, 0, 0L);
  676.             break;
  677.  
  678.         case IDM_EDITCLEAR:
  679.             SendMessage (hwndActiveEdit, EM_REPLACESEL, 0,(LONG)"");
  680.             break;
  681.  
  682.         case IDM_EDITSELECT:
  683.             SendMessage (hwndActiveEdit, EM_SETSEL, 0, MAKELONG(0, 0xe000));
  684.             break;
  685.  
  686.         case IDM_EDITUNDO:
  687.             SendMessage (hwndActiveEdit, EM_UNDO, 0, 0L);
  688.             break;
  689.  
  690.         case IDM_EDITWRAP:
  691.             SendMessage (hwndActive, WM_COMMAND, IDM_EDITWRAP, 1L);
  692.             break;
  693.  
  694.         case IDM_SEARCHFIND:
  695.             /* Put up the find dialog box */
  696.             Find ();
  697.             break;
  698.  
  699.         case IDM_SEARCHNEXT:
  700.             /* Find next occurence */
  701.             FindNext ();
  702.             break;
  703.  
  704.         case IDM_SEARCHPREV:
  705.             /* Find previous occurence */
  706.             FindPrev ();
  707.             break;
  708.  
  709.         /* The following are window commands - these are handled by the
  710.          * MDI Client.
  711.          */
  712.         case IDM_WINDOWTILE:
  713.             /* Tile MDI windows */
  714.             SendMessage (hwndMDIClient, WM_MDITILE, 0, 0L);
  715.             break;
  716.  
  717.         case IDM_WINDOWCASCADE:
  718.             /* Cascade MDI windows */
  719.             SendMessage (hwndMDIClient, WM_MDICASCADE, 0, 0L);
  720.             break;
  721.  
  722.         case IDM_WINDOWICONS:
  723.             /* Auto - arrange MDI icons */
  724.             SendMessage (hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
  725.             break;
  726.  
  727.         case IDM_WINDOWCLOSEALL:
  728.             /* Abort operation if something is not saved */
  729.             if (!QueryCloseAllChildren())
  730.                 break;
  731.  
  732.             CloseAllChildren();
  733.  
  734.             /* Show the window since CloseAllChilren() hides the window
  735.              * for fewer repaints.
  736.              */
  737.             ShowWindow( hwndMDIClient, SW_SHOW);
  738.  
  739.             break;
  740.  
  741.         default:
  742.            /*
  743.             * This is essential, since there are frame WM_COMMANDS generated
  744.             * by the MDI system for activating child windows via the
  745.             * window menu.
  746.             */
  747.             DefFrameProc(hwnd, hwndMDIClient, WM_COMMAND, wParam, 0L);
  748.     }
  749. }
  750. /****************************************************************************
  751.  *                                                                          *
  752.  *  FUNCTION   : SetWrap ()                                                 *
  753.  *                                                                          *
  754.  *  PURPOSE    : Changes the word wrapping in an edit control. Since this   *
  755.  *               cannot be done by direct means, the function creates a new *
  756.  *               edit control, moves data from the old control to the new   *
  757.  *               control and destroys the original control. Note that the   *
  758.  *               function assumes that the child being modified is currently*
  759.  *               active.                                                    *       *
  760.  *                                                                          *
  761.  ****************************************************************************/
  762.  
  763. VOID NEAR PASCAL SetWrap(hwnd, fWrap)
  764. HWND hwnd;
  765. BOOL fWrap;
  766.  
  767. {
  768.     LONG    dws;
  769.     HANDLE  hT;
  770.     HANDLE  hTT;
  771.     HWND    hwndOld;
  772.     HWND    hwndNew;
  773.  
  774.     /* Change word wrap mode */
  775.     SetWindowWord (hwnd, GWW_WORDWRAP, fWrap);
  776.  
  777.     /* Create the appropriate window style, adding a horizontal scroll
  778.      * facility if wrapping is not present.
  779.      */
  780.     dws = WS_CHILD | WS_VSCROLL | ES_AUTOVSCROLL | ES_MULTILINE;
  781.     if (!fWrap)
  782.         dws |= WS_HSCROLL | ES_AUTOHSCROLL;
  783.  
  784.     /* Create a new child window */
  785.     hwndNew = CreateWindow ( "edit",
  786.                              NULL,
  787.                              dws,
  788.                              0,
  789.                              SW_SHOW,
  790.                              0,
  791.                              0,
  792.                              hwnd,
  793.                              ID_EDIT,
  794.                              hInst,
  795.                              NULL);
  796.  
  797.     /* Get handle to current edit control */
  798.     hwndOld = GetWindowWord (hwnd, GWW_HWNDEDIT);
  799.  
  800.     /* Get the data handle of the old control */
  801.     hT = (HANDLE)SendMessage (hwndOld, EM_GETHANDLE, 0, 0L);
  802.  
  803.     /* Create a dummy data handle and make it the handle to
  804.      * the old edit control( hT still references the text of
  805.      * old control).
  806.      */
  807.     hTT = LocalAlloc (LHND, 0);
  808.     SendMessage (hwndOld, EM_SETHANDLE, hTT, 0L);
  809.  
  810.     /* Make the new window the window of interest and destroy the
  811.      * old control.
  812.      */
  813.     SetWindowWord (hwnd, GWW_HWNDEDIT, hwndNew);
  814.     hwndActiveEdit = hwndNew;
  815.     DestroyWindow (hwndOld);
  816.  
  817.     /* Cause the window to be properly sized */
  818.     SendMessage (hwnd, WM_SIZE, 0, 0L);
  819.  
  820.     /* Free the new window's old data handle and set it to
  821.      * hT (text of old edit control)
  822.      */
  823.     LocalFree ((HANDLE)SendMessage (hwndNew, EM_GETHANDLE, 0, 0L));
  824.     SendMessage (hwndNew, EM_SETHANDLE, hT, 0L);
  825.  
  826.     ShowWindow (hwndNew, SW_SHOW);
  827.  
  828.     /* Set focus to the new edit control */
  829.     SetFocus (hwndNew);
  830.  
  831. }
  832.  
  833.  
  834. /****************************************************************************
  835.  *                                                                          *
  836.  *  FUNCTION   : MPError ( hwnd, flags, id, ...)                            *
  837.  *                                                                          *
  838.  *  PURPOSE    : Flashes a Message Box to the user. The format string is    *
  839.  *               taken from the STRINGTABLE.                                *
  840.  *                                                                          *
  841.  *  RETURNS    : Returns value returned by MessageBox() to the caller.      *
  842.  *                                                                          *
  843.  ****************************************************************************/
  844. #include <stdarg.h>
  845. short FAR CDECL MPError(hwnd, bFlags, id, ...)
  846. HWND hwnd;
  847. WORD bFlags;
  848. WORD id;
  849. {
  850.     char sz[160];
  851.     char szFmt[128];
  852.  
  853.     LoadString (hInst, id, szFmt, sizeof (szFmt));
  854. #if 0
  855.     wvsprintf (sz, szFmt, (LPSTR)(&id + 1));
  856. #else
  857.     va_list ap; va_start(ap, id);
  858.     vsprintf (sz, szFmt, ap);
  859.     va_end(ap);
  860. #endif
  861.     LoadString (hInst, IDS_APPNAME, szFmt, sizeof (szFmt));
  862.     return MessageBox (hwndFrame, sz, szFmt, bFlags);
  863. }
  864.  
  865. /****************************************************************************
  866.  *                                                                          *
  867.  *  FUNCTION   : QueryCloseAllChildren()                                    *
  868.  *                                                                          *
  869.  *  PURPOSE    : Asks the child windows if it is ok to close up app. Nothing*
  870.  *               is destroyed at this point. The z-order is not changed.    *
  871.  *                                                                          *
  872.  *  RETURNS    : TRUE - If all children agree to the query.                 *
  873.  *               FALSE- If any one of them disagrees.                       *
  874.  *                                                                          *
  875.  ****************************************************************************/
  876.  
  877. BOOL NEAR PASCAL QueryCloseAllChildren(void)
  878. {
  879.     register HWND hwndT;
  880.  
  881.     for ( hwndT = GetWindow (hwndMDIClient, GW_CHILD);
  882.           hwndT;
  883.           hwndT = GetWindow (hwndT, GW_HWNDNEXT)       ){
  884.  
  885.         /* Skip if an icon title window */
  886.         if (GetWindow (hwndT, GW_OWNER))
  887.             continue;
  888.  
  889.         if (SendMessage (hwndT, WM_QUERYENDSESSION, 0, 0L))
  890.             return FALSE;
  891.     }
  892.     return TRUE;
  893. }
  894.  
  895. /****************************************************************************
  896.  *                                                                          *
  897.  *  FUNCTION   : QueryCloseChild (hwnd)                                     *
  898.  *                                                                          *
  899.  *  PURPOSE    : If the child MDI is unsaved, allow the user to save, not   *
  900.  *               save, or cancel the close operation.                       *
  901.  *                                                                          *
  902.  *  RETURNS    : TRUE  - if user chooses save or not save, or if the file   *
  903.  *                       has not changed.                                   *
  904.  *               FALSE - otherwise.                                         *
  905.  *                                                                          *
  906.  ****************************************************************************/
  907.  
  908. BOOL NEAR PASCAL QueryCloseChild(HWND hwnd)
  909. {
  910.     char         sz [64];
  911.     register int i;
  912.  
  913.     /* Return OK if edit control has not changed. */
  914.     if (!GetWindowWord (hwnd, GWW_CHANGED))
  915.         return TRUE;
  916.  
  917.     GetWindowText (hwnd, sz, sizeof(sz));
  918.  
  919.     /* Ask user whether to save / not save / cancel */
  920.     i = MPError (hwnd,
  921.                  MB_YESNOCANCEL|MB_ICONQUESTION,IDS_CLOSESAVE,
  922.                  (LPSTR)sz);
  923.  
  924.     switch (i){
  925.         case IDYES:
  926.             /* User wants file saved */
  927.             SaveFile(hwnd);
  928.             break;
  929.  
  930.         case IDNO:
  931.             /* User doesn't want file saved */
  932.             break;
  933.  
  934.         default:
  935.             /* We couldn't do the messagebox, or not ok to close */
  936.             return FALSE;
  937.     }
  938.     return TRUE;
  939. }
  940.