home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / mciapp / app.c next >
C/C++ Source or Header  |  1997-10-05  |  51KB  |  1,680 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. //  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
  5. //  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
  6. //  A PARTICULAR PURPOSE.
  7. //
  8. //  Copyright (C) 1993 - 1997 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. //  app.c
  13. //
  14. //  Description:
  15. //      This is a sample application that demonstrates how to use the
  16. //      Media Control Interface (MCI) in Windows. This application is
  17. //      also useful as an MCI device tester.
  18. //
  19. //  History:
  20. //      11/ 8/92    created.
  21. //
  22. //==========================================================================;
  23.  
  24. #include <windows.h>
  25. #include <windowsx.h>
  26. #include <mmsystem.h>
  27. #include <commdlg.h>
  28. #include <shellapi.h>
  29. #include <stdarg.h>
  30. #include <memory.h>
  31. #include "appport.h"
  32. #include "app.h"
  33. #include "mciapp.h"
  34.  
  35. #include "debug.h"
  36.  
  37.  
  38. //
  39. //  globals, no less
  40. //
  41. HINSTANCE       ghinst;
  42. UINT            gfuAppOptions       = APP_OPTF_YIELDEXEC;
  43.  
  44. TCHAR           gszAppSection[]     = TEXT("MCI App");
  45. TCHAR           gszNull[]           = TEXT("");
  46.  
  47. TCHAR           gszAppName[APP_MAX_APP_NAME_CHARS];
  48. TCHAR           gszFileUntitled[APP_MAX_FILE_TITLE_CHARS];
  49. TCHAR           gszAppFileTitle[APP_MAX_FILE_TITLE_CHARS];
  50. TCHAR           gszAppFilePath[APP_MAX_FILE_PATH_CHARS];
  51.  
  52.  
  53. //==========================================================================;
  54. //
  55. //  Application helper functions
  56. //
  57. //
  58. //==========================================================================;
  59.  
  60. //--------------------------------------------------------------------------;
  61. //
  62. //  int AppMsgBox
  63. //
  64. //  Description:
  65. //      This function displays a message for the application in a standard
  66. //      message box.
  67. //
  68. //      Note that this function takes any valid argument list that can
  69. //      be passed to wsprintf. Because of this, the application must
  70. //      remember to cast near string pointers to FAR when built for Win 16.
  71. //      You will get a nice GP fault if you do not cast them correctly.
  72. //
  73. //  Arguments:
  74. //      HWND hwnd: Handle to parent window for message box holding the
  75. //      message.
  76. //
  77. //      UINT fuStyle: Style flags for MessageBox().
  78. //
  79. //      PCTSTR pszFormat: Format string used for wvsprintf().
  80. //
  81. //  Return (int):
  82. //      The return value is the result of MessageBox() function.
  83. //
  84. //  History:
  85. //       2/13/93    created.
  86. //
  87. //--------------------------------------------------------------------------;
  88.  
  89. int FNCGLOBAL AppMsgBox
  90. (
  91.     HWND            hwnd,
  92.     UINT            fuStyle,
  93.     PCTSTR          pszFormat,
  94.     ...
  95. )
  96. {
  97.     va_list     va;
  98.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  99.     int         n;
  100.  
  101.     //
  102.     //  format and display the message..
  103.     //
  104.     va_start(va, pszFormat);
  105.     wvsprintf(ach, pszFormat, va);
  106.     va_end(va);
  107.  
  108.     n = MessageBox(hwnd, ach, gszAppName, fuStyle);
  109.  
  110.     return (n);
  111. } // AppMsgBox()
  112.  
  113.  
  114. //--------------------------------------------------------------------------;
  115. //
  116. //  int AppMsgBoxId
  117. //
  118. //  Description:
  119. //      This function displays a message for the application. The message
  120. //      text is retrieved from the string resource table using LoadString.
  121. //
  122. //      Note that this function takes any valid argument list that can
  123. //      be passed to wsprintf. Because of this, the application must
  124. //      remember to cast near string pointers to FAR when built for Win 16.
  125. //      You will get a nice GP fault if you do not cast them correctly.
  126. //
  127. //  Arguments:
  128. //      HWND hwnd: Handle to parent window for message box holding the
  129. //      message.
  130. //
  131. //      UINT fuStyle: Style flags for MessageBox().
  132. //
  133. //      UINT uIdsFormat: String resource id to be loaded with LoadString()
  134. //      and used a the format string for wvsprintf().
  135. //
  136. //  Return (int):
  137. //      The return value is the result of MessageBox() if the string
  138. //      resource specified by uIdsFormat is valid. The return value is zero
  139. //      if the string resource failed to load.
  140. //
  141. //  History:
  142. //       2/13/93    created.
  143. //
  144. //--------------------------------------------------------------------------;
  145.  
  146. int FNCGLOBAL AppMsgBoxId
  147. (
  148.     HWND            hwnd,
  149.     UINT            fuStyle,
  150.     UINT            uIdsFormat,
  151.     ...
  152. )
  153. {
  154.     va_list     va;
  155.     TCHAR       szFormat[APP_MAX_STRING_RC_CHARS];
  156.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  157.     int         n;
  158.  
  159.     n = LoadString(ghinst, uIdsFormat, szFormat, SIZEOF(szFormat));
  160.     if (0 != n)
  161.     {
  162.         //
  163.         //  format and display the message..
  164.         //
  165.         va_start(va, uIdsFormat);
  166.         wvsprintf(ach, szFormat, va);
  167.         va_end(va);
  168.  
  169.         n = MessageBox(hwnd, ach, gszAppName, fuStyle);
  170.     }
  171.  
  172.     return (n);
  173. } // AppMsgBoxId()
  174.  
  175.  
  176. //--------------------------------------------------------------------------;
  177. //
  178. //  void AppHourGlass
  179. //
  180. //  Description:
  181. //      This function changes the cursor to that of the hour glass or
  182. //      back to the previous cursor.
  183. //
  184. //      This function can be called recursively.
  185. //
  186. //  Arguments:
  187. //      BOOL fHourGlass: TRUE if we need the hour glass.  FALSE if we need
  188. //      the arrow back.
  189. //
  190. //  Return (void):
  191. //      On return, the cursor will be what was requested.
  192. //
  193. //  History:
  194. //      11/ 8/92    created.
  195. //
  196. //--------------------------------------------------------------------------;
  197.  
  198. void FNGLOBAL AppHourGlass
  199. (
  200.     BOOL            fHourGlass
  201. )
  202. {
  203.     static HCURSOR  hcur;
  204.     static UINT     uWaiting = 0;
  205.  
  206.     if (fHourGlass)
  207.     {
  208.         if (!uWaiting)
  209.         {
  210.             hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  211.             ShowCursor(TRUE);
  212.         }
  213.  
  214.         uWaiting++;
  215.     }
  216.     else
  217.     {
  218.         --uWaiting;
  219.  
  220.         if (!uWaiting)
  221.         {
  222.             ShowCursor(FALSE);
  223.             SetCursor(hcur);
  224.         }
  225.     }
  226. } // AppHourGlass()
  227.  
  228.  
  229. //--------------------------------------------------------------------------;
  230. //
  231. //  BOOL AppYield
  232. //
  233. //  Description:
  234. //      This function yields by dispatching all messages stacked up in the
  235. //      application queue.
  236. //
  237. //  Arguments:
  238. //      HWND hwnd: Handle to main window of application if not yielding
  239. //      for a dialog. Handle to dialog box if yielding for a dialog box.
  240. //
  241. //      BOOL fIsDialog: TRUE if being called to yield for a dialog box.
  242. //
  243. //  Return (BOOL):
  244. //      The return value is always TRUE.
  245. //
  246. //  History:
  247. //       2/ 7/93    created.
  248. //
  249. //--------------------------------------------------------------------------;
  250.  
  251. BOOL FNGLOBAL AppYield
  252. (
  253.     HWND            hwnd,
  254.     BOOL            fIsDialog
  255. )
  256. {
  257.     MSG     msg;
  258.  
  259.     if (fIsDialog)
  260.     {
  261.         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  262.         {
  263.             if ((NULL == hwnd) || !IsDialogMessage(hwnd, &msg))
  264.             {
  265.                 //
  266.                 //  see comment below..
  267.                 //
  268.                 MciAppDispatchMessage(GetParent(hwnd), &msg);
  269.             }
  270.         }
  271.     }
  272.     else
  273.     {
  274.         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  275.         {
  276.             //
  277.             //  normally, we would only do the following here:
  278.             //
  279.             //      TranslateMessage(&msg);
  280.             //      DispatchMessage(&msg);
  281.             //
  282.             //  but this app is special, so dispatch messages in a
  283.             //  special way...
  284.             //
  285.             MciAppDispatchMessage(hwnd, &msg);
  286.         }
  287.     }
  288.  
  289.     return (TRUE);
  290. } // AppYield()
  291.  
  292.  
  293. //--------------------------------------------------------------------------;
  294. //
  295. //  int AppSetWindowText
  296. //
  297. //  Description:
  298. //      This function formats a string and sets the specified window text
  299. //      to the result.
  300. //
  301. //  Arguments:
  302. //      HWND hwnd: Handle to window to receive the new text.
  303. //
  304. //      PCTSTR pszFormat: Pointer to any valid format for wsprintf.
  305. //
  306. //  Return (int):
  307. //      The return value is the number of bytes that the resulting window
  308. //      text was.
  309. //
  310. //  History:
  311. //       2/ 7/93    created.
  312. //
  313. //--------------------------------------------------------------------------;
  314.  
  315. int FNCGLOBAL AppSetWindowText
  316. (
  317.     HWND            hwnd,
  318.     PCTSTR          pszFormat,
  319.     ...
  320. )
  321. {
  322.     va_list     va;
  323.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  324.     int         n;
  325.  
  326.     //
  327.     //  format and display the string in the window...
  328.     //
  329.     va_start(va, pszFormat);
  330.     n = wvsprintf(ach, pszFormat, va);
  331.     va_end(va);
  332.  
  333.     SetWindowText(hwnd, ach);
  334.  
  335.     return (n);
  336. } // AppSetWindowText()
  337.  
  338.  
  339. //--------------------------------------------------------------------------;
  340. //
  341. //  int AppSetWindowTextId
  342. //
  343. //  Description:
  344. //      This function formats a string and sets the specified window text
  345. //      to the result. The format string is extracted from the string
  346. //      table using LoadString() on the uIdsFormat argument.
  347. //
  348. //  Arguments:
  349. //      HWND hwnd: Handle to window to receive the new text.
  350. //
  351. //      UINT uIdsFormat: String resource id to be loaded with LoadString()
  352. //      and used a the format string for wvsprintf().
  353. //
  354. //  Return (int):
  355. //      The return value is the number of bytes that the resulting window
  356. //      text was. This value is zero if the LoadString() function fails
  357. //      for the uIdsFormat argument.
  358. //
  359. //  History:
  360. //       2/ 7/93    created.
  361. //
  362. //--------------------------------------------------------------------------;
  363.  
  364. int FNCGLOBAL AppSetWindowTextId
  365. (
  366.     HWND            hwnd,
  367.     UINT            uIdsFormat,
  368.     ...
  369. )
  370. {
  371.     va_list     va;
  372.     TCHAR       szFormat[APP_MAX_STRING_RC_CHARS];
  373.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  374.     int         n;
  375.  
  376.     n = LoadString(ghinst, uIdsFormat, szFormat, SIZEOF(szFormat));
  377.     if (0 != n)
  378.     {
  379.         //
  380.         //  format and display the string in the window...
  381.         //
  382.         va_start(va, uIdsFormat);
  383.         n = wvsprintf(ach, szFormat, va);
  384.         va_end(va);
  385.  
  386.         SetWindowText(hwnd, ach);
  387.     }
  388.  
  389.     return (n);
  390. } // AppSetWindowTextId()
  391.  
  392.  
  393. //--------------------------------------------------------------------------;
  394. //
  395. //  BOOL AppGetFileTitle
  396. //
  397. //  Description:
  398. //      This function extracts the file title from a file path and returns
  399. //      it in the caller's specified buffer.
  400. //
  401. //  Arguments:
  402. //      PCTSTR pszFilePath: Pointer to null terminated file path.
  403. //
  404. //      PTSTR pszFileTitle: Pointer to buffer to receive the file title.
  405. //
  406. //  Return (BOOL):
  407. //      Always returns TRUE. But should return FALSE if this function
  408. //      checked for bogus values, etc.
  409. //
  410. //  History:
  411. //       2/ 6/93    created.
  412. //
  413. //--------------------------------------------------------------------------;
  414.  
  415. BOOL FNGLOBAL AppGetFileTitle
  416. (
  417.     PCTSTR          pszFilePath,
  418.     PTSTR           pszFileTitle
  419. )
  420. {
  421.     #define IS_SLASH(c)     ('/' == (c) || '\\' == (c))
  422.  
  423.     PTSTR       pch;
  424.  
  425.     //
  426.     //  scan to the end of the file path string..
  427.     //
  428.     for (pch = pszFilePath; '\0' != *pch; pch++)
  429.         ;
  430.  
  431.     //
  432.     //  now scan back toward the beginning of the string until a slash (\),
  433.     //  colon, or start of the string is encountered.
  434.     //
  435.     while ((pch >= pszFilePath) && !IS_SLASH(*pch) && (':' != *pch))
  436.     {
  437.         pch--;
  438.     }
  439.  
  440.     //
  441.     //  finally, copy the 'title' into the destination buffer.. skip ahead
  442.     //  one char since the above loop steps back one too many chars...
  443.     //
  444.     lstrcpy(pszFileTitle, ++pch);
  445.  
  446.     return (TRUE);
  447. } // AppGetFileTitle()
  448.  
  449.  
  450. //--------------------------------------------------------------------------;
  451. //
  452. //  BOOL AppGetFileName
  453. //
  454. //  Description:
  455. //      This function is a wrapper for the Get[Open/Save]FileName commdlg
  456. //      chooser dialogs. Based on the fuFlags argument, this function will
  457. //      display the appropriate chooser dialog and return the result.
  458. //
  459. //  Arguments:
  460. //      HWND hwnd: Handle to parent window for chooser dialog.
  461. //
  462. //      PTSTR pszFilePath: Pointer to buffer to receive the file path.
  463. //
  464. //      PTSTR pszFileTitle: Pointer to buffer to receive the file title.
  465. //      This argument may be NULL, in which case no title will be returned.
  466. //
  467. //      UINT fuFlags:
  468. //
  469. //  Return (BOOL):
  470. //      The return value is TRUE if a file was chosen. It is FALSE if the
  471. //      user canceled the operation.
  472. //
  473. //  History:
  474. //       2/ 6/93    created.
  475. //
  476. //--------------------------------------------------------------------------;
  477.  
  478. BOOL FNGLOBAL AppGetFileName
  479. (
  480.     HWND            hwnd,
  481.     PTSTR           pszFilePath,
  482.     PTSTR           pszFileTitle,
  483.     UINT            fuFlags
  484. )
  485. {
  486.     #define APP_OFN_FLAGS_SAVE  (OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT)
  487.     #define APP_OFN_FLAGS_OPEN  (OFN_HIDEREADONLY | OFN_FILEMUSTEXIST)
  488.  
  489.     TCHAR           szExtDefault[APP_MAX_EXT_DEFAULT_CHARS];
  490.     TCHAR           szExtFilter[APP_MAX_EXT_FILTER_CHARS];
  491.     OPENFILENAME    ofn;
  492.     BOOL            f;
  493.     PTCHAR          pch;
  494.  
  495.  
  496.     //
  497.     //  get the extension filter and default extension for this application
  498.     //
  499.     LoadString(ghinst, IDS_OFN_EXT_DEF, szExtDefault, SIZEOF(szExtDefault));
  500.     LoadString(ghinst, IDS_OFN_EXT_FILTER, szExtFilter, SIZEOF(szExtFilter));
  501.  
  502.  
  503.     //
  504.     //  NOTE! building the filter string for the OPENFILENAME structure
  505.     //  is a bit more difficult when dealing with Unicode and C8's new
  506.     //  optimizer. it joyfully removes literal '\0' characters from
  507.     //  strings that are concatted together. if you try making each
  508.     //  string separate (array of pointers to strings), the compiler
  509.     //  will dword align them... etc, etc.
  510.     //
  511.     //  if you can think of a better way to build the silly filter string
  512.     //  for common dialogs and still work in Win 16 and Win 32 [Unicode]
  513.     //  i'd sure like to hear about it...
  514.     //
  515.     for (pch = &szExtFilter[0]; '\0' != *pch; pch++)
  516.     {
  517.         if ('!' == *pch)
  518.             *pch = '\0';
  519.     }
  520.  
  521.     //
  522.     //  initialize the OPENFILENAME members
  523.     //
  524.     memset(&ofn, 0, sizeof(OPENFILENAME));
  525.  
  526.     pszFilePath[0]          = '\0';
  527.     if (pszFileTitle)
  528.         pszFileTitle[0]     = '\0';
  529.  
  530.     ofn.lStructSize         = sizeof(OPENFILENAME);
  531.     ofn.hwndOwner           = hwnd;
  532.     ofn.lpstrFilter         = szExtFilter;
  533.     ofn.lpstrCustomFilter   = NULL;
  534.     ofn.nMaxCustFilter      = 0L;
  535.     ofn.nFilterIndex        = 1L;
  536.     ofn.lpstrFile           = pszFilePath;
  537.     ofn.nMaxFile            = APP_MAX_FILE_PATH_CHARS;
  538.     ofn.lpstrFileTitle      = pszFileTitle;
  539.     ofn.nMaxFileTitle       = pszFileTitle ? APP_MAX_FILE_TITLE_CHARS : 0;
  540.     ofn.lpstrInitialDir     = NULL;
  541.     ofn.nFileOffset         = 0;
  542.     ofn.nFileExtension      = 0;
  543.     ofn.lpstrDefExt         = szExtDefault;
  544.  
  545.     //
  546.     //  if the fuFlags.APP_GFNF_SAVE bit is set, then call GetSaveFileName()
  547.     //  otherwise call GetOpenFileName(). why commdlg was designed with
  548.     //  two separate functions for save and open only clark knows.
  549.     //
  550.     if (fuFlags & APP_GFNF_SAVE)
  551.     {
  552.         ofn.Flags = APP_OFN_FLAGS_SAVE;
  553.         f = GetSaveFileName(&ofn);
  554.     }
  555.     else
  556.     {
  557.         ofn.Flags = APP_OFN_FLAGS_OPEN;
  558.         f = GetOpenFileName(&ofn);
  559.     }
  560.  
  561.     return (f);
  562. } // AppGetFileName()
  563.  
  564.  
  565. //--------------------------------------------------------------------------;
  566. //
  567. //  BOOL AppTitle
  568. //
  569. //  Description:
  570. //      This function formats and sets the title text of the application's
  571. //      window.
  572. //
  573. //  Arguments:
  574. //      HWND hwnd: Handle to application window to set title text for.
  575. //
  576. //      PCTSTR pszFileTitle: Pointer to file title to display.
  577. //
  578. //  Return (BOOL):
  579. //      The return value is always TRUE.
  580. //
  581. //  History:
  582. //       2/ 6/93    created.
  583. //
  584. //--------------------------------------------------------------------------;
  585.  
  586. BOOL FNGLOBAL AppTitle
  587. (
  588.     HWND            hwnd,
  589.     PCTSTR          pszFileTitle
  590. )
  591. {
  592.     static  TCHAR   szFormatTitle[]     = TEXT("%s - %s");
  593.  
  594.     TCHAR       ach[APP_MAX_FILE_PATH_CHARS];
  595.  
  596.     //
  597.     //  format the title text as 'AppName - FileTitle'
  598.     //
  599.     wsprintf(ach, szFormatTitle, (LPSTR)gszAppName, (LPSTR)pszFileTitle);
  600.     SetWindowText(hwnd, ach);
  601.  
  602.     return (TRUE);
  603. } // AppTitle()
  604.  
  605.  
  606. //--------------------------------------------------------------------------;
  607. //
  608. //  BOOL AppFileNew
  609. //
  610. //  Description:
  611. //      This function is called to handle the IDM_FILE_NEW message. It is
  612. //      responsible for clearing the working area for a new unnamed file.
  613. //
  614. //  Arguments:
  615. //      HWND hwnd: Handle to application window.
  616. //
  617. //      PTSTR pszFilePath: Pointer to current null terminated file path.
  618. //      This buffer will be reinitialized if the function succeeds.
  619. //
  620. //      PTSTR pszFileTitle: Pointer to current null terminated file title.
  621. //      This buffer will be reinitialized if the function succeeds.
  622. //
  623. //  Return (BOOL):
  624. //      The return value is TRUE if the working area was cleared and is
  625. //      ready for new stuff. The return value is FALSE if the user canceled
  626. //      the operation.
  627. //
  628. //  History:
  629. //       2/ 6/93    created.
  630. //
  631. //--------------------------------------------------------------------------;
  632.  
  633. BOOL FNGLOBAL AppFileNew
  634. (
  635.     HWND            hwnd,
  636.     PTSTR           pszFilePath,
  637.     PTSTR           pszFileTitle
  638. )
  639. {
  640.     BOOL    f;
  641.  
  642.     //
  643.     //  if there is currently a file path, then we have to do some real
  644.     //  work...
  645.     //
  646.     if ('\0' != pszFilePath[0])
  647.     {
  648.         f = MciAppFileNew(hwnd, pszFilePath, pszFileTitle);
  649.         if (!f)
  650.             return (FALSE);
  651.     }
  652.  
  653.     //
  654.     //  blow away the old file path and title; set the window title and
  655.     //  return success
  656.     //
  657.     lstrcpy(pszFilePath,  gszFileUntitled);
  658.     lstrcpy(pszFileTitle, gszFileUntitled);
  659.  
  660.     AppTitle(hwnd, pszFileTitle);
  661.  
  662.     MciAppResetStatus(hwnd);
  663.     AppSetWindowTextId(GetDlgItem(hwnd, IDD_APP_TEXT_STATUS),
  664.                        IDS_MCI_SCRIPT_CREATED, (LPSTR)pszFilePath);
  665.  
  666.     SetFocus(GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT));
  667.  
  668.     return (TRUE);
  669. } // AppFileNew()
  670.  
  671.  
  672. //--------------------------------------------------------------------------;
  673. //
  674. //  BOOL AppFileOpen
  675. //
  676. //  Description:
  677. //      This function handles the IDM_FILE_OPEN message. It is responsible
  678. //      for getting a new file name from the user and opening that file
  679. //      if possible.
  680. //
  681. //  Arguments:
  682. //      HWND hwnd: Handle to application window.
  683. //
  684. //      PTSTR pszFilePath: Pointer to current null terminated file path.
  685. //      This buffer will contain the new file path if one is selected.
  686. //
  687. //      PTSTR pszFileTitle: Pointer to current null terminated file title.
  688. //      This buffer will contain the new file title if one is selected.
  689. //
  690. //  Return (BOOL):
  691. //      The return value is TRUE if a new file was selected and opened.
  692. //      It is FALSE if the user canceled the operation.
  693. //
  694. //  History:
  695. //       2/ 6/93    created.
  696. //
  697. //--------------------------------------------------------------------------;
  698.  
  699. BOOL FNLOCAL AppFileOpen
  700. (
  701.     HWND            hwnd,
  702.     PTSTR           pszFilePath,
  703.     PTSTR           pszFileTitle
  704. )
  705. {
  706.     TCHAR       szFilePath[APP_MAX_FILE_PATH_CHARS];
  707.     TCHAR       szFileTitle[APP_MAX_FILE_TITLE_CHARS];
  708.     BOOL        f;
  709.  
  710.     //
  711.     //  first test for a modified script that has not been saved. if the
  712.     //  return value is FALSE we should cancel the File.Open operation.
  713.     //
  714.     f = MciAppFileSaveModified(hwnd, pszFilePath, pszFileTitle);
  715.     if (!f)
  716.         return (FALSE);
  717.  
  718.  
  719.     //
  720.     //  get the file name of the new script into temporary buffers (so
  721.     //  if we fail to open it we can back out cleanly).
  722.     //
  723.     f = AppGetFileName(hwnd, szFilePath, szFileTitle, APP_GFNF_OPEN);
  724.     if (!f)
  725.         return (FALSE);
  726.  
  727.  
  728.     //
  729.     //  read the new script...
  730.     //
  731.     f = MciAppFileOpen(hwnd, szFilePath, NULL);
  732.     if (f)
  733.     {
  734.         //
  735.         //  copy the new file path and title into the global buffers and
  736.         //  set the window title text...
  737.         //
  738.         lstrcpy(gszAppFilePath,  szFilePath);
  739.         lstrcpy(gszAppFileTitle, szFileTitle);
  740.  
  741.         AppTitle(hwnd, szFileTitle);
  742.         MciAppResetStatus(hwnd);
  743.  
  744.         AppSetWindowTextId(GetDlgItem(hwnd, IDD_APP_TEXT_STATUS),
  745.                            IDS_MCI_SCRIPT_OPENED, (LPSTR)szFilePath);
  746.  
  747.         SetFocus(GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT));
  748.     }
  749.  
  750.     return (f);
  751. } // AppFileOpen()
  752.  
  753.  
  754. //--------------------------------------------------------------------------;
  755. //
  756. //  BOOL AppFileSave
  757. //
  758. //  Description:
  759. //      This function handles the IDM_FILE_SAVE[AS] messages. It is
  760. //      responsible for saving the current file. If a file name needs
  761. //      to be specified then the save file dialog is displayed.
  762. //
  763. //  Arguments:
  764. //      HWND hwnd: Handle to application window.
  765. //
  766. //      PTSTR pszFilePath: Pointer to current null terminated file path.
  767. //      This buffer will contain the new file path if one is selected.
  768. //
  769. //      PTSTR pszFileTitle: Pointer to current null terminated file title.
  770. //      This buffer will contain the new file title if one is selected.
  771. //
  772. //      BOOL fSaveAs: TRUE if the save file chooser should be displayed
  773. //      before saving the file. FALSE if should operate like File.Save.
  774. //
  775. //  Return (BOOL):
  776. //      The return value is TRUE if the file was saved. It is FALSE if the
  777. //      user canceled the operation or the file does not need saved.
  778. //
  779. //  History:
  780. //       2/ 6/93    created.
  781. //
  782. //--------------------------------------------------------------------------;
  783.  
  784. BOOL FNGLOBAL AppFileSave
  785. (
  786.     HWND            hwnd,
  787.     PTSTR           pszFilePath,
  788.     PTSTR           pszFileTitle,
  789.     BOOL            fSaveAs
  790. )
  791. {
  792.     TCHAR       szFilePath[APP_MAX_FILE_PATH_CHARS];
  793.     TCHAR       szFileTitle[APP_MAX_FILE_TITLE_CHARS];
  794.     BOOL        f;
  795.  
  796.     //
  797.     //  check if we should bring up the save file chooser dialog...
  798.     //
  799.     if (fSaveAs || !lstrcmp(pszFileTitle, gszFileUntitled))
  800.     {
  801.         //
  802.         //  get the file name for saving the script to into temporary
  803.         //  buffers (so if we fail to save it we can back out cleanly).
  804.         //
  805.         f = AppGetFileName(hwnd, szFilePath, szFileTitle, APP_GFNF_SAVE);
  806.         if (!f)
  807.             return (FALSE);
  808.     }
  809.     else
  810.     {
  811.         //
  812.         //  copy the file path into our temporary buffer so we don't have
  813.         //  to special case this on MciAppFileSave..
  814.         //
  815.         lstrcpy(szFilePath,  pszFilePath);
  816.         lstrcpy(szFileTitle, pszFileTitle);
  817.     }
  818.  
  819.     //
  820.     //  save the script...
  821.     //
  822.     f = MciAppFileSave(hwnd, szFilePath);
  823.     if (f)
  824.     {
  825.         //
  826.         //  copy the (possibly) new file path and title into the global
  827.         //  buffers and set the window title text...
  828.         //
  829.         lstrcpy(gszAppFilePath,  szFilePath);
  830.         lstrcpy(gszAppFileTitle, szFileTitle);
  831.  
  832.         AppTitle(hwnd, szFileTitle);
  833.  
  834.         //
  835.         //  changes have been saved, so clear the modified bit...
  836.         //
  837.         Edit_SetModify(GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT), FALSE);
  838.  
  839.         AppSetWindowTextId(GetDlgItem(hwnd, IDD_APP_TEXT_STATUS),
  840.                            IDS_MCI_SCRIPT_SAVED, (LPSTR)szFilePath);
  841.  
  842.         SetFocus(GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT));
  843.     }
  844.  
  845.     return (f);
  846. } // AppFileSave()
  847.  
  848.  
  849. //==========================================================================;
  850. //
  851. //  Main application window handling code...
  852. //
  853. //
  854. //==========================================================================;
  855.  
  856. //--------------------------------------------------------------------------;
  857. //
  858. //  LRESULT AppInitMenuPopup
  859. //
  860. //  Description:
  861. //      This function handles the WM_INITMENUPOPUP message. This message
  862. //      is sent to the window owning the menu that is going to become
  863. //      active. This gives an application the ability to modify the menu
  864. //      before it is displayed (disable/add items, etc).
  865. //
  866. //  Arguments:
  867. //      HWND hwnd: Handle to window that generated the WM_INITMENUPOPUP
  868. //      message.
  869. //
  870. //      HMENU hmenu: Handle to the menu that is to become active.
  871. //
  872. //      int nItem: Specifies the zero-based relative position of the menu
  873. //      item that invoked the popup menu.
  874. //
  875. //      BOOL fSysMenu: Specifies whether the popup menu is a System menu
  876. //      (TRUE) or it is not a System menu (FALSE).
  877. //
  878. //  Return (LRESULT):
  879. //      Returns zero if the message is processed.
  880. //
  881. //  History:
  882. //       1/ 2/93    created.
  883. //
  884. //--------------------------------------------------------------------------;
  885.  
  886. LRESULT FNLOCAL AppInitMenuPopup
  887. (
  888.     HWND            hwnd,
  889.     HMENU           hmenu,
  890.     int             nItem,
  891.     BOOL            fSysMenu
  892. )
  893. {
  894.     BOOL    f;
  895.     int     nSelStart;
  896.     int     nSelEnd;
  897.     HWND    hwndScript;
  898.  
  899.     DPF(0, "AppInitMenuPopup(hwnd=%Xh, hmenu=%Xh, nItem=%d, fSysMenu=%d)",
  900.             hwnd, hmenu, nItem, fSysMenu);
  901.  
  902.     //
  903.     //  if the system menu is what got hit, succeed immediately... this
  904.     //  application has no stuff in the system menu.
  905.     //
  906.     if (fSysMenu)
  907.         return (0L);
  908.  
  909.     //
  910.     //  initialize the menu that is being 'popped up'
  911.     //
  912.     switch (nItem)
  913.     {
  914.         case APP_MENU_ITEM_FILE:
  915.             //
  916.             //  if the script has been modified, then enable the File.Save
  917.             //  menu
  918.             //
  919.             hwndScript = GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT);
  920.             f = Edit_GetModify(hwndScript);
  921.             EnableMenuItem(hmenu, IDM_FILE_SAVE,
  922.                            (UINT)(f ? MF_ENABLED : MF_GRAYED));
  923.             break;
  924.  
  925.         case APP_MENU_ITEM_EDIT:
  926.             //
  927.             //  check to see if something is selected in the script edit
  928.             //  window and enable/disable Edit menu options appropriately
  929.             //
  930.             hwndScript = GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT);
  931.             Edit_GetSelEx(hwndScript, &nSelStart, &nSelEnd);
  932.  
  933.             f = (nSelStart != nSelEnd);
  934.             EnableMenuItem(hmenu, WM_CUT,   (UINT)(f ? MF_ENABLED : MF_GRAYED));
  935.             EnableMenuItem(hmenu, WM_COPY,  (UINT)(f ? MF_ENABLED : MF_GRAYED));
  936.             EnableMenuItem(hmenu, WM_CLEAR, (UINT)(f ? MF_ENABLED : MF_GRAYED));
  937.  
  938.             f = Edit_CanUndo(hwndScript);
  939.             EnableMenuItem(hmenu, WM_UNDO,  (UINT)(f ? MF_ENABLED : MF_GRAYED));
  940.  
  941.             f = IsClipboardFormatAvailable(CF_TEXT);
  942.             EnableMenuItem(hmenu, WM_PASTE, (UINT)(f ? MF_ENABLED : MF_GRAYED));
  943.             break;
  944.  
  945.         case APP_MENU_ITEM_DEVICE:
  946.             //
  947.             //
  948.             //
  949.             f = (0 != (gfuAppOptions & APP_OPTF_DEVICELIST));
  950.             CheckMenuItem(hmenu, IDM_DEVICE_OPENLIST,
  951.                           (UINT)(f ? MF_CHECKED : MF_UNCHECKED));
  952.  
  953.             f = (MciAppGetNumDevices(hwnd) != 0);
  954.             EnableMenuItem(hmenu, IDM_DEVICE_CLOSEALL,
  955.                            (UINT)(f ? MF_ENABLED : MF_GRAYED));
  956.             break;
  957.  
  958.         case APP_MENU_ITEM_OPTIONS:
  959.             //
  960.             //  make sure the options that need a checkmark are checked..
  961.             //
  962.             f = (0 != (gfuAppOptions & APP_OPTF_EDITONLY));
  963.             CheckMenuItem(hmenu, IDM_OPTIONS_EDITONLY,
  964.                           (UINT)(f ? MF_CHECKED : MF_UNCHECKED));
  965.  
  966.             f = (0 != (gfuAppOptions & APP_OPTF_YIELDEXEC));
  967.             CheckMenuItem(hmenu, IDM_OPTIONS_YIELDEXEC,
  968.                           (UINT)(f ? MF_CHECKED : MF_UNCHECKED));
  969.  
  970.             f = (0 != (gfuAppOptions & APP_OPTF_DEBUGLOG));
  971.             CheckMenuItem(hmenu, IDM_OPTIONS_DEBUGLOG,
  972.                           (UINT)(f ? MF_CHECKED : MF_UNCHECKED));
  973.             break;
  974.     }
  975.  
  976.     //
  977.     //  we processed the message--return 0...
  978.     //
  979.     return (0L);
  980. } // AppInitMenuPopup()
  981.  
  982.  
  983. //--------------------------------------------------------------------------;
  984. //
  985. //  LRESULT AppCommand
  986. //
  987. //  Description:
  988. //      This function handles the WM_COMMAND message.
  989. //
  990. //  Arguments:
  991. //      HWND hwnd: Handle to window receiving the WM_COMMAND message.
  992. //
  993. //      int nId: Control or menu item identifier.
  994. //
  995. //      HWND hwndCtl: Handle of control if the message is from a control.
  996. //      This argument is NULL if the message was not generated by a control.
  997. //
  998. //      UINT uCode: Notification code. This argument is 1 if the message
  999. //      was generated by an accelerator. If the message is from a menu,
  1000. //      this argument is 0.
  1001. //
  1002. //  Return (LRESULT):
  1003. //      Returns zero if the message is processed.
  1004. //
  1005. //  History:
  1006. //      11/ 8/92    created.
  1007. //
  1008. //--------------------------------------------------------------------------;
  1009.  
  1010. LRESULT FNLOCAL AppCommand
  1011. (
  1012.     HWND            hwnd,
  1013.     int             nId,
  1014.     HWND            hwndCtl,
  1015.     UINT            uCode
  1016. )
  1017. {
  1018.     BOOL        f;
  1019.  
  1020.     if (gfExecuting)
  1021.     {
  1022.         if ((IDD_ACCL_ABORT == nId) || (IDD_APP_BTN_STOP == nId))
  1023.             gfAbortExec = TRUE;
  1024.  
  1025.         return (0L);
  1026.     }
  1027.  
  1028.     switch (nId)
  1029.     {
  1030.         case IDM_FILE_NEW:
  1031.             AppFileNew(hwnd, gszAppFilePath, gszAppFileTitle);
  1032.             break;
  1033.  
  1034.         case IDM_FILE_OPEN:
  1035.             AppFileOpen(hwnd, gszAppFilePath, gszAppFileTitle);
  1036.             break;
  1037.  
  1038.         case IDM_FILE_SAVE:
  1039.             AppFileSave(hwnd, gszAppFilePath, gszAppFileTitle, FALSE);
  1040.             break;
  1041.  
  1042.         case IDM_FILE_SAVEAS:
  1043.             AppFileSave(hwnd, gszAppFilePath, gszAppFileTitle, TRUE);
  1044.             break;
  1045.  
  1046.         case IDM_FILE_ABOUT:
  1047.             DialogBox(ghinst, DLG_ABOUT, hwnd, (DLGPROC)AboutDlgProc);
  1048.             break;
  1049.  
  1050.         case IDM_FILE_EXIT:
  1051.             FORWARD_WM_CLOSE(hwnd, SendMessage);
  1052.             break;
  1053.  
  1054.  
  1055.         case WM_UNDO:
  1056.         case WM_CUT:
  1057.         case WM_COPY:
  1058.         case WM_PASTE:
  1059.         case WM_CLEAR:
  1060.             //
  1061.             //  pass edit messages received to the script edit window
  1062.             //
  1063.             SendMessage(GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT), nId, 0, 0L);
  1064.             break;
  1065.  
  1066.         case IDM_EDIT_SELECTALL:
  1067.             Edit_SetSel(GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT), 0, -1);
  1068.             break;
  1069.  
  1070.  
  1071.         case IDM_DEVICE_CLOSEALL:
  1072.             MciAppCloseAllDevices(hwnd);
  1073.             break;
  1074.  
  1075.  
  1076.         case IDM_OPTIONS_EDITONLY:
  1077.             gfuAppOptions ^= APP_OPTF_EDITONLY;
  1078.             MciAppUpdateOptions(hwnd);
  1079.             break;
  1080.  
  1081.         case IDM_OPTIONS_YIELDEXEC:
  1082.             gfuAppOptions ^= APP_OPTF_YIELDEXEC;
  1083.             MciAppUpdateOptions(hwnd);
  1084.             break;
  1085.  
  1086.         case IDM_OPTIONS_DEBUGLOG:
  1087.             gfuAppOptions ^= APP_OPTF_DEBUGLOG;
  1088.             MciAppUpdateOptions(hwnd);
  1089.             break;
  1090.  
  1091.         case IDM_DEVICE_OPENLIST:
  1092.             //
  1093.             //  bring up the device list dialog--if this event was triggered
  1094.             //  by an accelerator (uCode == 1) then do not give the focus
  1095.             //  to the dialog. if this event was triggered by the user
  1096.             //  selecting the menu option with the mouse, then give the
  1097.             //  focus to the device list dialog...
  1098.             //
  1099.             gfuAppOptions ^= APP_OPTF_DEVICELIST;
  1100.             MciAppDeviceList(hwnd, (1 != uCode));
  1101.             break;
  1102.  
  1103.         case IDM_OPTIONS_FONT:
  1104.             MciAppChooseFont(hwnd);
  1105.             break;
  1106.  
  1107.  
  1108.         case IDD_APP_BTN_STEP:
  1109.             //
  1110.             //  execute the current line in the script window
  1111.             //
  1112.             MciAppSingleStep(hwnd);
  1113.             break;
  1114.  
  1115.         case IDD_APP_BTN_RUN:
  1116.             //
  1117.             //  execute every line in the script window starting from the
  1118.             //  _first_ line..
  1119.             //
  1120.             Edit_SetSel(GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT), 0, 0);
  1121.  
  1122.             // -- Fall Through --
  1123.  
  1124.         case IDD_APP_BTN_GO:
  1125.             //
  1126.             //  execute every line in the script window starting from the
  1127.             //  _current_ line..
  1128.             //
  1129.             f = (0 != (gfuAppOptions & APP_OPTF_YIELDEXEC));
  1130.             MciAppExecute(hwnd, f);
  1131.             break;
  1132.  
  1133.  
  1134.         case IDOK:
  1135.             //
  1136.             //  when we receive an IDOK for the script window (user pressed
  1137.             //  return key), 'enter' the new line...
  1138.             //
  1139.             //  uCode will be 0 if Alt+Enter was pressed, so reverse the
  1140.             //  logic of the Edit Only option in this case
  1141.             //
  1142.             if (GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT) == hwndCtl)
  1143.             {
  1144.                 f = (0 != (gfuAppOptions & APP_OPTF_EDITONLY));
  1145.                 MciAppEnterLine(hwnd, (1 == uCode) ? f : !f);
  1146.             }
  1147.             break;
  1148.     }
  1149.  
  1150.     return (0L);
  1151. } // AppCommand()
  1152.  
  1153.  
  1154. //--------------------------------------------------------------------------;
  1155. //
  1156. //  LRESULT AppDropFiles
  1157. //
  1158. //  Description:
  1159. //      This function handles the WM_DROPFILES message. This message is
  1160. //      sent when files are 'dropped' on the window from file manager
  1161. //      (or other drag/drop servers made by ISV's that figured out the
  1162. //      undocumented internal workings of the SHELL).
  1163. //
  1164. //      A window must be registered to receive these messages either by
  1165. //      called DragAcceptFiles() or using CreateWindowEx() with the
  1166. //      WS_EX_ACCEPTFILES style bit.
  1167. //
  1168. //  Arguments:
  1169. //      HWND hwnd: Handle to window receiving the message.
  1170. //
  1171. //      HDROP hdrop: Handle to drop structure.
  1172. //
  1173. //  Return (LRESULT):
  1174. //      Returns 0 if the message is processed.
  1175. //
  1176. //  History:
  1177. //       2/ 8/93    created.
  1178. //
  1179. //--------------------------------------------------------------------------;
  1180.  
  1181. LRESULT FNLOCAL AppDropFiles
  1182. (
  1183.     HWND            hwnd,
  1184.     HDROP           hdrop
  1185. )
  1186. {
  1187.     TCHAR       szFileTitle[APP_MAX_FILE_PATH_CHARS];
  1188.     TCHAR       szFilePath[APP_MAX_FILE_PATH_CHARS];
  1189.     UINT        uNumFiles;
  1190.     UINT        u;
  1191.     BOOL        f;
  1192.     int         n;
  1193.  
  1194.     //
  1195.     //  if executing a script and this message is received, we bail...
  1196.     //  too much code to fix this...
  1197.     //
  1198.     if (gfExecuting)
  1199.     {
  1200.         MessageBeep((UINT)-1);
  1201.         goto App_Drop_Files_Exit;
  1202.     }
  1203.  
  1204.  
  1205.     //
  1206.     //  first test for a modified script that has not been saved. if the
  1207.     //  return value is FALSE we should cancel the drop operation.
  1208.     //
  1209.     f = MciAppFileSaveModified(hwnd, gszAppFilePath, gszAppFileTitle);
  1210.     if (!f)
  1211.         goto App_Drop_Files_Exit;
  1212.  
  1213.     //
  1214.     //  get number of files dropped on our window
  1215.     //
  1216.     uNumFiles = DragQueryFile(hdrop, (UINT)-1, NULL, 0);
  1217.  
  1218.     DPF(0, "AppDropFiles(hwnd=%Xh, hdrop=%Xh)--uNumFiles=%u",
  1219.              hwnd, hdrop, uNumFiles);
  1220.  
  1221.     //
  1222.     //  step through each file and stop on the one the user wants or
  1223.     //  the last file (whichever comes first).
  1224.     //
  1225.     for (u = 0; u < uNumFiles; u++)
  1226.     {
  1227.         //
  1228.         //  get the next file name and try to open it--if not a valid
  1229.         //  file, then skip to the next one (if there is one).
  1230.         //
  1231.         DragQueryFile(hdrop, u, szFilePath, SIZEOF(szFilePath));
  1232.  
  1233.  
  1234.         //
  1235.         //  attempt to open the file
  1236.         //
  1237.         f = MciAppFileOpen(hwnd, szFilePath, szFileTitle);
  1238.         if (!f)
  1239.             continue;
  1240.  
  1241.         //
  1242.         //  update display info
  1243.         //
  1244.         lstrcpy(gszAppFilePath, szFilePath);
  1245.         lstrcpy(gszAppFileTitle, szFileTitle);
  1246.  
  1247.         AppTitle(hwnd, szFileTitle);
  1248.         MciAppResetStatus(hwnd);
  1249.  
  1250.         AppSetWindowTextId(GetDlgItem(hwnd, IDD_APP_TEXT_STATUS),
  1251.                            IDS_MCI_SCRIPT_OPENED, (LPSTR)szFilePath);
  1252.  
  1253.  
  1254.         //
  1255.         //  if this is NOT the last file in the list of files that are
  1256.         //  being dropped on us, then bring up a box asking if we should
  1257.         //  continue or stop where we are..
  1258.         //
  1259.         if ((uNumFiles - 1) != u)
  1260.         {
  1261.             n = AppMsgBoxId(hwnd, MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL,
  1262.                             IDS_DROP_CONTINUE);
  1263.             if (IDNO == n)
  1264.                 break;
  1265.         }
  1266.     }
  1267.  
  1268.     //
  1269.     //  tell the shell to release the memory it allocated for beaming
  1270.     //  the file name(s) over to us... return 0 to show we processed
  1271.     //  the message.
  1272.     //
  1273. App_Drop_Files_Exit:
  1274.  
  1275.     DragFinish(hdrop);
  1276.     return (0L);
  1277. } // AppDropFiles()
  1278.  
  1279.  
  1280. //--------------------------------------------------------------------------;
  1281. //
  1282. //  LRESULT AppSize
  1283. //
  1284. //  Description:
  1285. //      This function handles the WM_SIZE message for the application's
  1286. //      window. This message is sent to the application window after the
  1287. //      size has changed (but before it is painted).
  1288. //
  1289. //  Arguments:
  1290. //      HWND hwnd: Handle to window that generated the WM_SIZE message.
  1291. //
  1292. //      UINT fuSizeType: Specifies the type of resizing requested. This
  1293. //      argument is one of the following: SIZE_MAXIMIZED, SIZE_MINIMIZED,
  1294. //      SIZE_RESTORED, SIZE_MAXHIDE, or SIZE_MAXSHOW.
  1295. //
  1296. //      int nWidth: Width of the new client area for the window.
  1297. //
  1298. //      int nHeight: Height of the new client area for the window.
  1299. //
  1300. //  Return (LRESULT):
  1301. //      Returns zero if the application processes the message.
  1302. //
  1303. //  History:
  1304. //       2/ 5/93    created.
  1305. //
  1306. //--------------------------------------------------------------------------;
  1307.  
  1308. LRESULT FNLOCAL AppSize
  1309. (
  1310.     HWND            hwnd,
  1311.     UINT            fuSizeType,
  1312.     int             nWidth,
  1313.     int             nHeight
  1314. )
  1315. {
  1316.     HWND    hwndButton;
  1317.     HWND    hwndOutput;
  1318.     HWND    hwndScript;
  1319.     HWND    hwndStatus;
  1320.     HWND    hwndSeparator;
  1321.     HWND    hwndNotify;
  1322.     HWND    hwndOptions;
  1323.     RECT    rc;
  1324.     int     nHeightButton;
  1325.     int     nWidthButton;
  1326.     int     nHeightScript;
  1327.     int     nHeightStatus;
  1328.     int     n, m;
  1329.     int     nWidthNotify;
  1330.  
  1331.     DPF(0, "AppSize(hwnd=%Xh, fuSizeType=%u, nWidth=%d, nHeight=%d)",
  1332.             hwnd, fuSizeType, nWidth, nHeight);
  1333.  
  1334.     //
  1335.     //  unless this application is the one being resized then don't waste
  1336.     //  time computing stuff that doesn't matter. this applies to being
  1337.     //  minimized also because this application does not have a custom
  1338.     //  minimized state.
  1339.     //
  1340.     if ((SIZE_RESTORED != fuSizeType) && (SIZE_MAXIMIZED != fuSizeType))
  1341.         return (0L);
  1342.  
  1343.     //
  1344.     //  for this application, we have three different sections that need
  1345.     //  to be fit into the newly sized client area--it looks roughly like
  1346.     //  this:
  1347.     //
  1348.     //  +-------------------------------------------+
  1349.     //  | - |        MCI App - ZYZSMAG.MCI      |^|v| <- title bar
  1350.     //  +-------------------------------------------+
  1351.     //  | File Edit Options                         | <- menu bar
  1352.     //  +-------------------------------------------+
  1353.     //  |{Step}{ Go }{ Run } Count:[x ] Output: zyz | <- button bar
  1354.     //  +-------------------------------------------+
  1355.     //  | MCI script window                         | <- script window
  1356.     //  |                                           |
  1357.     //  |                                           |
  1358.     //  |                                           |
  1359.     //  |                                           |
  1360.     //  |                                           |
  1361.     //  |                                           |
  1362.     //  +-------------------------------------------+
  1363.     //  | Silly status bar      | Notify: zyz | EYL | <- options status
  1364.     //  +-------------------------------------------+
  1365.     //       ^                  ^   ^
  1366.     //       +- status bar      |   +- notify window
  1367.     //                          |
  1368.     //                          +----- separator
  1369.     //
  1370.     //  the 'button bar' does not have to move or change size (except the
  1371.     //  width of the output window)
  1372.     //
  1373.     //  the 'script window' should fill all space between the bottom of
  1374.     //  the button bar and the top of the status bar.
  1375.     //
  1376.     //  the 'status bar' should sit on the bottom of the window and
  1377.     //  remain a constant height.
  1378.     //
  1379.     //  the 'notify window' should sit on the bottom of the window to the
  1380.     //  right of the status bar and remain a constant height.
  1381.     //
  1382.     //  the 'options status' window should sit in the bottom right corner
  1383.     //  and remain a constant width and height.
  1384.     //
  1385.     //  the 'separators' should be a visible separator between the status
  1386.     //  bar, notify window, and options status.
  1387.     //
  1388.  
  1389.     //
  1390.     //  first grab handles to all the windows we need to muck with...
  1391.     //
  1392.     hwndButton  = GetDlgItem(hwnd, IDD_APP_BTN_GO);
  1393.     hwndOutput  = GetDlgItem(hwnd, IDD_APP_TEXT_OUTPUT);
  1394.     hwndScript  = GetDlgItem(hwnd, IDD_APP_EDIT_SCRIPT);
  1395.     hwndStatus  = GetDlgItem(hwnd, IDD_APP_TEXT_STATUS);
  1396.     hwndNotify  = GetDlgItem(hwnd, IDD_APP_TEXT_NOTIFY);
  1397.     hwndOptions = GetDlgItem(hwnd, IDD_APP_TEXT_OPTIONS);
  1398.  
  1399.     //
  1400.     //  get the height of the button bar and status bar
  1401.     //
  1402.     GetClientRect(hwndButton, &rc);
  1403.     nHeightButton = (int)(rc.bottom - rc.top);
  1404.     nWidthButton  = (int)(rc.right - rc.left);
  1405.  
  1406.  
  1407.     //
  1408.     //  change width of output window..
  1409.     //
  1410.     GetClientRect(hwndStatus, &rc);
  1411.     nHeightStatus = (int)(rc.bottom - rc.top);
  1412.  
  1413.     n = nWidthButton * 6;
  1414.     m = (nWidth > (n + 2)) ? (nWidth - n - 2) : 0;
  1415.     rc.top = (nHeightButton - nHeightStatus) / 2;
  1416.     MoveWindow(hwndOutput, n, (int)rc.top, m, nHeightStatus, TRUE);
  1417.  
  1418.  
  1419.     //
  1420.     //  calculate the new height for the script window and move it to just
  1421.     //  below the bottom of the button bar and above the status bar (which
  1422.     //  is the height of the button bar)... note that we put the left and
  1423.     //  right edges of the script window outside of the client area because
  1424.     //  it looks better that way.
  1425.     //
  1426.     nHeightScript = nHeight - (nHeightButton * 2);
  1427.     if (nHeightScript < 0)
  1428.         nHeightScript = 0;
  1429.  
  1430.     MoveWindow(hwndScript, -1, nHeightButton, nWidth + 2, nHeightScript, TRUE);
  1431.  
  1432.  
  1433.     //
  1434.     //  put the status bar sitting on top of the bottom of the app window
  1435.     //  note that we center it in a space that is as high as the button
  1436.     //  bar so it looks better... it is assumed (correctly) that the button
  1437.     //  bar is taller than the status bar control.
  1438.     //
  1439.     //  ~                                           ~
  1440.     //  |                                           |
  1441.     //  +-------------------------------------------+
  1442.     //  | Silly status bar      | Notify: zyz | EYL |
  1443.     //  +-------------------------------------------+
  1444.     //  ^                       ^             ^     ^
  1445.     //  +------ min = 20 -------+-min = ~130 -+- 40-+
  1446.     //
  1447.     //  there is pad of 2 on the left and right of each text window (giving
  1448.     //  a separator a effective width of 5).
  1449.     //
  1450.     //
  1451.     nWidthNotify = (nWidth < (20 + 5 + 130 + 5 + 40)) ?
  1452.                         (nWidth - (20 + 5 + 5 + 40)) : 130;
  1453.  
  1454.     hwndSeparator = GetDlgItem(hwnd, IDD_APP_BOX_SEPARATOR1);
  1455.     MoveWindow(hwndSeparator, nWidth - nWidthNotify - 3 - 5 - 40,
  1456.                               nHeight - nHeightButton,
  1457.                               1, nHeightButton, TRUE);
  1458.  
  1459.  
  1460.     n = nHeightStatus + ((nHeightButton - nHeightStatus) / 2);
  1461.     MoveWindow(hwndStatus, 2, nHeight - n,
  1462.                            nWidth - nWidthNotify - 8 - 5 - 40,
  1463.                            nHeightStatus, TRUE);
  1464.  
  1465.     MoveWindow(hwndNotify, nWidth - nWidthNotify - 5 - 40, nHeight - n,
  1466.                            nWidthNotify - 2, nHeightStatus, TRUE);
  1467.  
  1468.     hwndSeparator = GetDlgItem(hwnd, IDD_APP_BOX_SEPARATOR2);
  1469.     MoveWindow(hwndSeparator, nWidth - 3 - 40,
  1470.                               nHeight - nHeightButton,
  1471.                               1, nHeightButton, TRUE);
  1472.  
  1473.     MoveWindow(hwndOptions, nWidth - 40, nHeight - n,
  1474.                            40 - 2, nHeightStatus, TRUE);
  1475.  
  1476.     //
  1477.     //  we processed the message..
  1478.     //
  1479.     return (0L);
  1480. } // AppSize()
  1481.  
  1482.  
  1483. //--------------------------------------------------------------------------;
  1484. //
  1485. //  LRESULT AppWndProc
  1486. //
  1487. //  Description:
  1488. //      This is the main application window procedure.
  1489. //
  1490. //  Arguments:
  1491. //      HWND hwnd: Handle to window.
  1492. //
  1493. //      UINT uMsg: Message being sent to the window.
  1494. //
  1495. //      WPARAM wParam: Specific argument to message.
  1496. //
  1497. //      LPARAM lParam: Specific argument to message.
  1498. //
  1499. //  Return (LRESULT):
  1500. //      The return value depends on the message that is being processed.
  1501. //
  1502. //  History:
  1503. //      11/ 8/92    created.
  1504. //
  1505. //--------------------------------------------------------------------------;
  1506.  
  1507. LRESULT FNEXPORT AppWndProc
  1508. (
  1509.     HWND            hwnd,
  1510.     UINT            uMsg,
  1511.     WPARAM          wParam,
  1512.     LPARAM          lParam
  1513. )
  1514. {
  1515.     LRESULT     lr;
  1516.  
  1517.     switch (uMsg)
  1518.     {
  1519.         case WM_CREATE:
  1520.             lr = HANDLE_WM_CREATE(hwnd, wParam, lParam, AppCreate);
  1521.             return (lr);
  1522.  
  1523.         case WM_WININICHANGE:
  1524.             HANDLE_WM_WININICHANGE(hwnd, wParam, lParam, AppWinIniChange);
  1525.             return (0L);
  1526.  
  1527.         case WM_INITMENUPOPUP:
  1528.             HANDLE_WM_INITMENUPOPUP(hwnd, wParam, lParam, AppInitMenuPopup);
  1529.             return (0L);
  1530.  
  1531.         case WM_COMMAND:
  1532.             lr = HANDLE_WM_COMMAND(hwnd, wParam, lParam, AppCommand);
  1533.             return (lr);
  1534.  
  1535.         case WM_DROPFILES:
  1536.             //
  1537.             //  some windowsx.h files have a screwed up message cracker for
  1538.             //  WM_DROPFILES. because this is a sample app, i don't want
  1539.             //  people having trouble with bogus windowsx.h files, so crack
  1540.             //  the message manually... you should use the message cracker
  1541.             //  if you know your windowsx.h file is good.
  1542.             //
  1543.             //  lr = HANDLE_WM_DROPFILES(hwnd, wParam, lParam, AppDropFiles);
  1544.             //
  1545.             lr = AppDropFiles(hwnd, (HDROP)wParam);
  1546.             return (lr);
  1547.  
  1548.         case WM_SIZE:
  1549.             //
  1550.             //  handle what we want for sizing, and then always call the
  1551.             //  default handler...
  1552.             //
  1553.             HANDLE_WM_SIZE(hwnd, wParam, lParam, AppSize);
  1554.             break;
  1555.  
  1556.         case WM_QUERYENDSESSION:
  1557.             lr = HANDLE_WM_QUERYENDSESSION(hwnd, wParam, lParam, AppQueryEndSession);
  1558.             return (lr);
  1559.  
  1560.         case WM_ENDSESSION:
  1561.             HANDLE_WM_ENDSESSION(hwnd, wParam, lParam, AppEndSession);
  1562.             return (0L);
  1563.  
  1564.         case WM_CLOSE:
  1565.             HANDLE_WM_CLOSE(hwnd, wParam, lParam, AppClose);
  1566.             return (0L);
  1567.  
  1568.         case WM_DESTROY:
  1569.             PostQuitMessage(0);
  1570.             return (0L);
  1571.  
  1572.  
  1573.         case MM_MCINOTIFY:
  1574.             MciAppHandleNotify(hwnd, wParam, LOWORD(lParam));
  1575.             break;
  1576.     }
  1577.  
  1578.     return (DefWindowProc(hwnd, uMsg, wParam, lParam));
  1579. } // AppWndProc()
  1580.  
  1581.  
  1582. //==========================================================================;
  1583. //
  1584. //  Main entry and message dispatching code
  1585. //
  1586. //
  1587. //==========================================================================;
  1588.  
  1589. //--------------------------------------------------------------------------;
  1590. //
  1591. //  int WinMain
  1592. //
  1593. //  Description:
  1594. //      This function is called by the system as the initial entry point
  1595. //      for a Windows application.
  1596. //
  1597. //  Arguments:
  1598. //      HINSTANCE hinst: Identifies the current instance of the
  1599. //      application.
  1600. //
  1601. //      HINSTANCE hinstPrev: Identifies the previous instance of the
  1602. //      application (NULL if first instance). For Win 32, this argument
  1603. //      is _always_ NULL.
  1604. //
  1605. //      LPSTR pszCmdLine: Points to null-terminated unparsed command line.
  1606. //      This string is strictly ANSI regardless of whether the application
  1607. //      is built for Unicode. To get the Unicode equivalent call the
  1608. //      GetCommandLine() function (Win 32 only).
  1609. //
  1610. //      int nCmdShow: How the main window for the application is to be
  1611. //      shown by default.
  1612. //
  1613. //  Return (int):
  1614. //      Returns result from WM_QUIT message (in wParam of MSG structure) if
  1615. //      the application is able to enter its message loop. Returns 0 if
  1616. //      the application is not able to enter its message loop.
  1617. //
  1618. //  History:
  1619. //      11/ 8/92    created.
  1620. //
  1621. //--------------------------------------------------------------------------;
  1622.  
  1623. int PASCAL WinMain
  1624. (
  1625.     HINSTANCE       hinst,
  1626.     HINSTANCE       hinstPrev,
  1627.     LPSTR           pszCmdLine,
  1628.     int             nCmdShow
  1629. )
  1630. {
  1631.     int     nResult;
  1632.     HWND    hwnd;
  1633.     MSG     msg;
  1634.  
  1635.     //
  1636.     //  our documentation states that WinMain is supposed to return 0 if
  1637.     //  we do not enter our message loop--so assume the worst...
  1638.     //
  1639.     nResult = 0;
  1640.  
  1641.     //
  1642.     //  make our instance handle global for convenience..
  1643.     //
  1644.     ghinst = hinst;
  1645.  
  1646.     //
  1647.     //  init some stuff, create window, etc.. note the explicit cast of
  1648.     //  pszCmdLine--this is to mute a warning (and an ugly ifdef) when
  1649.     //  compiling for Unicode. see AppInit() for more details.
  1650.     //
  1651.     hwnd = AppInit(hinst, hinstPrev, (LPTSTR)pszCmdLine, nCmdShow);
  1652.     if (hwnd)
  1653.     {
  1654.         //
  1655.         //  dispatch messages
  1656.         //
  1657.         while (GetMessage(&msg, NULL, 0, 0))
  1658.         {
  1659.             //
  1660.             //  do all the special stuff required for this application
  1661.             //  when dispatching messages..
  1662.             //
  1663.             MciAppDispatchMessage(hwnd, &msg);
  1664.         }
  1665.  
  1666.         //
  1667.         //  return result of WM_QUIT message.
  1668.         //
  1669.         nResult = (int)msg.wParam;
  1670.     }
  1671.  
  1672.     //
  1673.     //  shut things down, clean up, etc.
  1674.     //
  1675.     nResult = AppExit(hinst, nResult);
  1676.  
  1677.     return (nResult);
  1678. } // WinMain()
  1679.  
  1680.