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