home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / vrac / mpad32.zip / MULTIPAD.C < prev    next >
C/C++ Source or Header  |  1994-04-15  |  40KB  |  982 lines

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