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