home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / d / d020_1_4 / 5.ddi / MULTIPAD / MULTIPAD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-01  |  26.2 KB  |  934 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. LPSTR 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. int  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.                       (LPSTR)&ccs);
  173.  
  174.  
  175.         ShowWindow (hwndMDIClient,SW_SHOW);
  176.  
  177.         /* Check if printer can be initialized */
  178.         if (hdc = GetPrinterDC ()){
  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 ()){
  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.     default:
  392. CallDCP:
  393.         /* Again, since the MDI default behaviour is a little different,
  394.          * call DefMDIChildProc instead of DefWindowProc()
  395.          */
  396.         return DefMDIChildProc (hwnd, msg, wParam, lParam);
  397.     }
  398.     return FALSE;
  399. }
  400.  
  401.  
  402. /****************************************************************************
  403.  *                                        *
  404.  *  FUNCTION   : AboutDlgProc ( hwnd, msg, wParam, lParam )            *
  405.  *                                        *
  406.  *  PURPOSE    : Dialog function for the About MultiPad... dialog.        *
  407.  *                                        *
  408.  ****************************************************************************/
  409. BOOL FAR PASCAL AboutDlgProc ( hwnd, msg, wParam, lParam )
  410. HWND          hwnd;
  411. register WORD msg;
  412. register WORD wParam;
  413. LONG          lParam;
  414. {
  415.     switch (msg){
  416.     case WM_INITDIALOG:
  417.         /* nothing to initialize */
  418.         break;
  419.  
  420.     case WM_COMMAND:
  421.         switch (wParam){
  422.         case IDOK:
  423.         case IDCANCEL:
  424.             EndDialog(hwnd, 0);
  425.             break;
  426.  
  427.         default:
  428.             return FALSE;
  429.         }
  430.         break;
  431.  
  432.     default:
  433.         return FALSE;
  434.     }
  435.  
  436.     return TRUE;
  437. }
  438.  
  439. /****************************************************************************
  440.  *                                        *
  441.  *  FUNCTION   : Initializemenu ( hMenu )                    *
  442.  *                                        *
  443.  *  PURPOSE    : Sets up greying, enabling and checking of main menu items  *
  444.  *         based on the app's state.                                  *
  445.  *                                        *
  446.  ****************************************************************************/
  447. VOID NEAR PASCAL InitializeMenu ( hmenu )
  448. register HANDLE hmenu;
  449. {
  450.     register WORD status;
  451.     int       i;
  452.     int       j;
  453.     long      l;
  454.  
  455.     /* Is there any active child to talk to? */
  456.     if (hwndActiveEdit){
  457.     /* If edit control can respond to an undo request, enable the
  458.      * undo selection.
  459.      */
  460.     if (SendMessage (hwndActiveEdit, EM_CANUNDO, 0, 0L))
  461.         status = MF_ENABLED;
  462.     else
  463.         status = MF_GRAYED;
  464.     EnableMenuItem (hmenu, IDM_EDITUNDO, status);
  465.  
  466.     /* If edit control is non-empty, allow cut/copy/clear */
  467.     l      = SendMessage (hwndActiveEdit, EM_GETSEL, 0, 0L);
  468.     status = (HIWORD(l) == LOWORD(l)) ? MF_GRAYED : MF_ENABLED;
  469.     EnableMenuItem (hmenu, IDM_EDITCUT, status);
  470.     EnableMenuItem (hmenu, IDM_EDITCOPY, status);
  471.     EnableMenuItem (hmenu, IDM_EDITCLEAR, status);
  472.  
  473.     status=MF_GRAYED;
  474.     /* If the clipboard contains some CF_TEXT data, allow paste */
  475.     if (OpenClipboard (hwndFrame)){
  476.         int wFmt = 0;
  477.  
  478.         while (wFmt = EnumClipboardFormats (wFmt))
  479.         if (wFmt == CF_TEXT){
  480.             status = MF_ENABLED;
  481.             break;
  482.         }
  483.  
  484.         CloseClipboard ();
  485.     }
  486.     EnableMenuItem (hmenu, IDM_EDITPASTE, status);
  487.  
  488.     /* Set the word wrap state for the window */
  489.     if ((WORD) SendMessage (hwndActive, WM_COMMAND, IDM_EDITWRAP, 0L))
  490.         status = MF_CHECKED;
  491.     else
  492.         status = MF_UNCHECKED;
  493.     CheckMenuItem (hmenu, IDM_EDITWRAP, status);
  494.  
  495.     /* Enable search menu items only if there is a search string */
  496.     if (*szSearch)
  497.         status = MF_ENABLED;
  498.     else
  499.         status = MF_GRAYED;
  500.     EnableMenuItem (hmenu, IDM_SEARCHNEXT, status);
  501.     EnableMenuItem (hmenu, IDM_SEARCHPREV, status);
  502.  
  503.     /* Enable File/Print only if a printer is available */
  504.     status = iPrinter ? MF_ENABLED : MF_GRAYED;
  505.     EnableMenuItem (hmenu, IDM_FILEPRINT, status);
  506.  
  507.     /* select all and wrap toggle always enabled */
  508.     status = MF_ENABLED;
  509.     EnableMenuItem(hmenu, IDM_EDITSELECT, status);
  510.     EnableMenuItem(hmenu, IDM_EDITWRAP, status);
  511.     EnableMenuItem(hmenu, IDM_SEARCHFIND, status);
  512.     }
  513.     else {
  514.     /* There are no active child windows */
  515.     status = MF_GRAYED;
  516.  
  517.     /* No active window, so disable everything */
  518.     for (i = IDM_EDITFIRST; i <= IDM_EDITLAST; i++)
  519.         EnableMenuItem (hmenu, i, status);
  520.  
  521.     CheckMenuItem (hmenu, IDM_EDITWRAP, MF_UNCHECKED);
  522.  
  523.     for (i = IDM_SEARCHFIRST; i <= IDM_SEARCHLAST; i++)
  524.         EnableMenuItem (hmenu, i, status);
  525.  
  526.     EnableMenuItem (hmenu, IDM_FILEPRINT, status);
  527.  
  528.     }
  529.  
  530.     /* The following menu items are enabled if there is an active window */
  531.     EnableMenuItem (hmenu, IDM_FILESAVE, status);
  532.     EnableMenuItem (hmenu, IDM_FILESAVEAS, status);
  533.     EnableMenuItem (hmenu, IDM_WINDOWTILE, status);
  534.     EnableMenuItem (hmenu, IDM_WINDOWCASCADE, status);
  535.     EnableMenuItem (hmenu, IDM_WINDOWICONS, status);
  536.     EnableMenuItem (hmenu, IDM_WINDOWCLOSEALL, status);
  537.  
  538.     /* Allow printer setup only if printer driver supports device initialization */
  539.     if (iPrinter < 2)
  540.     status = MF_GRAYED;
  541.     EnableMenuItem ( hmenu, IDM_FILESETUP, status);
  542.  
  543. }
  544.  
  545. /****************************************************************************
  546.  *                                        *
  547.  *  FUNCTION   : CloseAllChildren ()                        *
  548.  *                                        *
  549.  *  PURPOSE    : Destroys all MDI child windows.                *
  550.  *                                        *
  551.  ****************************************************************************/
  552. VOID NEAR PASCAL CloseAllChildren ()
  553. {
  554.     register HWND hwndT;
  555.  
  556.     /* hide the MDI client window to avoid multiple repaints */
  557.     ShowWindow(hwndMDIClient,SW_HIDE);
  558.  
  559.     /* As long as the MDI client has a child, destroy it */
  560.     while ( hwndT = GetWindow (hwndMDIClient, GW_CHILD)){
  561.  
  562.     /* Skip the icon title windows */
  563.     while (hwndT && GetWindow (hwndT, GW_OWNER))
  564.         hwndT = GetWindow (hwndT, GW_HWNDNEXT);
  565.  
  566.     if (!hwndT)
  567.         break;
  568.  
  569.     SendMessage (hwndMDIClient, WM_MDIDESTROY, (WORD)hwndT, 0L);
  570.     }
  571. }
  572.  
  573. /****************************************************************************
  574.  *                                        *
  575.  *  FUNCTION   : CommandHandler ()                        *
  576.  *                                        *
  577.  *  PURPOSE    : Processes all "frame" WM_COMMAND messages.            *
  578.  *                                        *
  579.  ****************************************************************************/
  580. VOID NEAR PASCAL CommandHandler ( hwnd, wParam )
  581. register HWND hwnd;
  582. register WORD wParam;
  583.  
  584. {
  585.     switch (wParam){
  586.     case IDM_FILENEW:
  587.         /* Add a new, empty MDI child */
  588.         AddFile (NULL);
  589.         break;
  590.  
  591.     case IDM_FILEOPEN:
  592.         ReadFile (hwnd);
  593.         break;
  594.  
  595.     case IDM_FILESAVE:
  596.         /* Save the active child MDI */
  597.         SendMessage (hwndActive, WM_COMMAND, IDM_FILESAVE, 0L);
  598.         break;
  599.  
  600.     case IDM_FILESAVEAS:
  601.         /* Save active child MDI under another name */
  602.         if (ChangeFile (hwndActive))
  603.         SendMessage (hwndActive, WM_COMMAND, IDM_FILESAVE, 0L);
  604.         break;
  605.  
  606.     case IDM_FILEPRINT:
  607.         /* Print the active child MDI */
  608.         PrintFile (hwndActive);
  609.         break;
  610.  
  611.     case IDM_FILESETUP:
  612.         /* Set up the printer environment for this app */
  613.         GetInitializationData (hwnd);
  614.         break;
  615.  
  616.     case IDM_FILEMENU:{
  617.  
  618.           /* lengthen / shorten the size of the MDI menu */
  619.           HMENU hMenu;
  620.           HMENU hWindowMenu;
  621.           int i;
  622.  
  623.           if (lpMenu == IDMULTIPAD){
  624.           lpMenu = IDMULTIPAD2;
  625.           i     = SHORTMENU;
  626.           }
  627.           else{
  628.           lpMenu = IDMULTIPAD;
  629.           i     = WINDOWMENU;
  630.           }
  631.  
  632.           hMenu = LoadMenu (hInst, lpMenu);
  633.           hWindowMenu = GetSubMenu (hMenu, i);
  634.  
  635.           /* Set the new menu */
  636.           hMenu = (HMENU)SendMessage (hwndMDIClient,
  637.                       WM_MDISETMENU,
  638.                       0,
  639.                       MAKELONG(hMenu,hWindowMenu));
  640.  
  641.           DestroyMenu (hMenu);
  642.           DrawMenuBar (hwndFrame);
  643.           break;
  644.     }
  645.  
  646.     case IDM_FILEEXIT:
  647.         /* Close Multipad */
  648.         SendMessage (hwnd, WM_CLOSE, 0, 0L);
  649.         break;
  650.  
  651.     case IDM_HELPABOUT:{
  652.         /* Bring up the ubiquitous Ego box */
  653.         FARPROC lpfn;
  654.  
  655.         lpfn = MakeProcInstance(AboutDlgProc, hInst);
  656.         DialogBox (hInst, IDD_ABOUT, hwnd, lpfn);
  657.         FreeProcInstance (lpfn);
  658.         break;
  659.     }
  660.  
  661.     /* The following are edit commands. Pass these off to the active
  662.      * child's edit control window.
  663.      */
  664.     case IDM_EDITCOPY:
  665.         SendMessage (hwndActiveEdit, WM_COPY, 0, 0L);
  666.         break;
  667.  
  668.     case IDM_EDITPASTE:
  669.         SendMessage (hwndActiveEdit, WM_PASTE, 0, 0L);
  670.         break;
  671.  
  672.     case IDM_EDITCUT:
  673.         SendMessage (hwndActiveEdit, WM_CUT, 0, 0L);
  674.         break;
  675.  
  676.     case IDM_EDITCLEAR:
  677.         SendMessage (hwndActiveEdit, EM_REPLACESEL, 0,( LONG)(LPSTR)"");
  678.         break;
  679.  
  680.     case IDM_EDITSELECT:
  681.         SendMessage (hwndActiveEdit, EM_SETSEL, 0, MAKELONG(0, 0xe000));
  682.         break;
  683.  
  684.     case IDM_EDITUNDO:
  685.         SendMessage (hwndActiveEdit, EM_UNDO, 0, 0L);
  686.         break;
  687.  
  688.     case IDM_EDITWRAP:
  689.         SendMessage (hwndActive, WM_COMMAND, IDM_EDITWRAP, 1L);
  690.         break;
  691.  
  692.     case IDM_SEARCHFIND:
  693.         /* Put up the find dialog box */
  694.         Find ();
  695.         break;
  696.  
  697.     case IDM_SEARCHNEXT:
  698.         /* Find next occurence */
  699.         FindNext ();
  700.         break;
  701.  
  702.     case IDM_SEARCHPREV:
  703.         /* Find previous occurence */
  704.         FindPrev ();
  705.         break;
  706.  
  707.     /* The following are window commands - these are handled by the
  708.      * MDI Client.
  709.      */
  710.     case IDM_WINDOWTILE:
  711.         /* Tile MDI windows */
  712.         SendMessage (hwndMDIClient, WM_MDITILE, 0, 0L);
  713.         break;
  714.  
  715.     case IDM_WINDOWCASCADE:
  716.         /* Cascade MDI windows */
  717.         SendMessage (hwndMDIClient, WM_MDICASCADE, 0, 0L);
  718.         break;
  719.  
  720.     case IDM_WINDOWICONS:
  721.         /* Auto - arrange MDI icons */
  722.         SendMessage (hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
  723.         break;
  724.  
  725.     case IDM_WINDOWCLOSEALL:
  726.         /* Abort operation if something is not saved */
  727.         if (!QueryCloseAllChildren())
  728.         break;
  729.  
  730.         CloseAllChildren();
  731.  
  732.         /* Show the window since CloseAllChilren() hides the window
  733.          * for fewer repaints.
  734.          */
  735.         ShowWindow( hwndMDIClient, SW_SHOW);
  736.  
  737.         break;
  738.  
  739.     default:
  740.        /*
  741.         * This is essential, since there are frame WM_COMMANDS generated
  742.         * by the MDI system for activating child windows via the
  743.         * window menu.
  744.         */
  745.         DefFrameProc(hwnd, hwndMDIClient, WM_COMMAND, wParam, 0L);
  746.     }
  747. }
  748. /****************************************************************************
  749.  *                                        *
  750.  *  FUNCTION   : SetWrap ()                            *
  751.  *                                        *
  752.  *  PURPOSE    : Changes the word wrapping in an edit control. Since this   *
  753.  *         cannot be done by direct means, the function creates a new *
  754.  *         edit control, moves data from the old control to the new   *
  755.  *         control and destroys the original control. Note that the   *
  756.  *         function assumes that the child being modified is currently*
  757.  *         active.                            *        *
  758.  *                                        *
  759.  ****************************************************************************/
  760.  
  761. VOID NEAR PASCAL SetWrap(hwnd, fWrap)
  762. HWND hwnd;
  763. BOOL fWrap;
  764.  
  765. {
  766.     LONG    dws;
  767.     HANDLE  hT;
  768.     HANDLE  hTT;
  769.     HWND    hwndOld;
  770.     HWND    hwndNew;
  771.     RECT    rc;
  772.  
  773.     /* Change word wrap mode */
  774.     SetWindowWord (hwnd, GWW_WORDWRAP, fWrap);
  775.  
  776.     /* Create the appropriate window style, adding a horizontal scroll
  777.      * facility if wrapping is not present.
  778.      */
  779.     dws = WS_CHILD | WS_VSCROLL | ES_AUTOVSCROLL | ES_MULTILINE;
  780.     if (!fWrap)
  781.     dws |= WS_HSCROLL | ES_AUTOHSCROLL;
  782.  
  783.     /* Create a new child window */
  784.     hwndNew = CreateWindow ( "edit",
  785.                  NULL,
  786.                  dws,
  787.                  0,
  788.                  SW_SHOW,
  789.                  0,
  790.                  0,
  791.                  hwnd,
  792.                  ID_EDIT,
  793.                  hInst,
  794.                  NULL);
  795.  
  796.     /* Get handle to current edit control */
  797.     hwndOld = GetWindowWord (hwnd, GWW_HWNDEDIT);
  798.  
  799.     /* Get the data handle of the old control */
  800.     hT = (HANDLE)SendMessage (hwndOld, EM_GETHANDLE, 0, 0L);
  801.  
  802.     /* Create a dummy data handle and make it the handle to
  803.      * the old edit control( hT still references the text of
  804.      * old control).
  805.      */
  806.     hTT = LocalAlloc (LHND, 0);
  807.     SendMessage (hwndOld, EM_SETHANDLE, hTT, 0L);
  808.  
  809.     /* Make the new window the window of interest and destroy the
  810.      * old control.
  811.      */
  812.     SetWindowWord (hwnd, GWW_HWNDEDIT, hwndNew);
  813.     hwndActiveEdit = hwndNew;
  814.     DestroyWindow (hwndOld);
  815.  
  816.     /* Cause the window to be properly sized */
  817.     SendMessage (hwnd, WM_SIZE, 0, 0L);
  818.  
  819.     /* Free the new window's old data handle and set it to
  820.      * hT (text of old edit control)
  821.      */
  822.     LocalFree ((HANDLE)SendMessage (hwndNew, EM_GETHANDLE, 0, 0L));
  823.     SendMessage (hwndNew, EM_SETHANDLE, hT, 0L);
  824.  
  825.     ShowWindow (hwndNew, SW_SHOW);
  826.  
  827.     /* Set focus to the new edit control */
  828.     SetFocus (hwndNew);
  829.  
  830. }
  831.  
  832.  
  833. /****************************************************************************
  834.  *                                        *
  835.  *  FUNCTION   : MPError ( hwnd, flags, id, ...)                *
  836.  *                                        *
  837.  *  PURPOSE    : Flashes a Message Box to the user. The format string is    *
  838.  *         taken from the STRINGTABLE.                    *
  839.  *                                        *
  840.  *  RETURNS    : Returns value returned by MessageBox() to the caller.        *
  841.  *                                        *
  842.  ****************************************************************************/
  843. short FAR CDECL MPError(hwnd, bFlags, id, ...)
  844. HWND hwnd;
  845. WORD bFlags;
  846. WORD id;
  847. {
  848.     char sz[160];
  849.     char szFmt[128];
  850.  
  851.     LoadString (hInst, id, szFmt, sizeof (szFmt));
  852.     wvsprintf (sz, szFmt, (LPSTR)(&id + 1));
  853.     LoadString (hInst, IDS_APPNAME, szFmt, sizeof (szFmt));
  854.     return MessageBox (hwndFrame, sz, szFmt, bFlags);
  855. }
  856.  
  857.  
  858. /****************************************************************************
  859.  *                                        *
  860.  *  FUNCTION   : QueryCloseAllChildren()                    *
  861.  *                                        *
  862.  *  PURPOSE    : Asks the child windows if it is ok to close up app. Nothing*
  863.  *         is destroyed at this point. The z-order is not changed.    *
  864.  *                                        *
  865.  *  RETURNS    : TRUE - If all children agree to the query.            *
  866.  *         FALSE- If any one of them disagrees.                *
  867.  *                                        *
  868.  ****************************************************************************/
  869.  
  870. BOOL NEAR PASCAL QueryCloseAllChildren()
  871. {
  872.     register HWND hwndT;
  873.  
  874.     for ( hwndT = GetWindow (hwndMDIClient, GW_CHILD);
  875.       hwndT;
  876.       hwndT = GetWindow (hwndT, GW_HWNDNEXT)       ){
  877.  
  878.     /* Skip if an icon title window */
  879.     if (GetWindow (hwndT, GW_OWNER))
  880.         continue;
  881.  
  882.     if (SendMessage (hwndT, WM_QUERYENDSESSION, 0, 0L))
  883.         return FALSE;
  884.     }
  885.     return TRUE;
  886. }
  887.  
  888. /****************************************************************************
  889.  *                                        *
  890.  *  FUNCTION   : QueryCloseChild (hwnd)                     *
  891.  *                                        *
  892.  *  PURPOSE    : If the child MDI is unsaved, allow the user to save, not   *
  893.  *               save, or cancel the close operation.                       *
  894.  *                                        *
  895.  *  RETURNS    : TRUE  - if user chooses save or not save, or if the file   *
  896.  *                       has not changed.                                   *
  897.  *         FALSE - otherwise.                        *
  898.  *                                        *
  899.  ****************************************************************************/
  900.  
  901. BOOL NEAR PASCAL QueryCloseChild(hwnd)
  902. register HWND hwnd;
  903. {
  904.     char     sz [64];
  905.     register int i;
  906.  
  907.     /* Return OK if edit control has not changed. */
  908.     if (!GetWindowWord (hwnd, GWW_CHANGED))
  909.     return TRUE;
  910.  
  911.     GetWindowText (hwnd, sz, sizeof(sz));
  912.  
  913.     /* Ask user whether to save / not save / cancel */
  914.     i = MPError (hwnd,
  915.          MB_YESNOCANCEL|MB_ICONQUESTION,IDS_CLOSESAVE,
  916.          (LPSTR)sz);
  917.  
  918.     switch (i){
  919.     case IDYES:
  920.         /* User wants file saved */
  921.         SaveFile(hwnd);
  922.         break;
  923.  
  924.     case IDNO:
  925.         /* User doesn't want file saved */
  926.         break;
  927.  
  928.     default:
  929.         /* We couldn't do the messagebox, or not ok to close */
  930.         return FALSE;
  931.     }
  932.     return TRUE;
  933. }
  934.