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 / mmcaps / mmcaps.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  64KB  |  2,425 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. //  mmcaps.c
  13. //
  14. //  Description:
  15. //
  16. //
  17. //  History:
  18. //      11/ 8/92
  19. //
  20. //==========================================================================;
  21.  
  22. #include <windows.h>
  23. #include <windowsx.h>
  24. #include <mmsystem.h>
  25. #include <commdlg.h>
  26. #include <stdarg.h>
  27.  
  28. #include "appport.h"
  29. #include "mmcaps.h"
  30.  
  31. #include "debug.h"
  32.  
  33.  
  34. //
  35. //  globals, no less
  36. //
  37. HINSTANCE   ghinst;
  38. TCHAR       gszAppSection[]     = TEXT("MMCaps");
  39. TCHAR       gszNull[]           = TEXT("");
  40.  
  41. TCHAR       gszAppName[APP_MAX_APP_NAME_CHARS];
  42.  
  43.  
  44. //
  45. //
  46. //
  47. PZYZTABBEDLISTBOX   gptlbDrivers;
  48.  
  49. TCHAR       gszUnknown[]        = TEXT("Unknown");
  50. TCHAR       gszNotSpecified[]   = TEXT("Not Specified");
  51.  
  52. UINT        guDriverType        = MMCAPS_DRIVERTYPE_LOWLEVEL;
  53.  
  54.  
  55.  
  56. //==========================================================================;
  57. //
  58. //  Application helper functions
  59. //
  60. //
  61. //==========================================================================;
  62.  
  63. //--------------------------------------------------------------------------;
  64. //  
  65. //  BOOL AppProfileWriteBytes
  66. //  
  67. //  Description:
  68. //      This function writes a raw structure of bytes to the application's
  69. //      ini section that can later be retrieved using AppProfileReadBytes.
  70. //      This gives an application the ability to write any structure to
  71. //      the ini file and restore it later--very useful.
  72. //
  73. //      NOTE! Starting with Windows for Workgroups 3.1 there are two new
  74. //      profile functions that provide the same functionality of this
  75. //      function. Specifically, these functions are GetPrivateProfileStruct
  76. //      and WritePrivateProfileStruct. These new functions are provided
  77. //      by the Common Controls DLL. The prototypes are as follows:
  78. //
  79. //      BOOL GetPrivateProfileStruct
  80. //      (
  81. //          LPSTR       szSection,
  82. //          LPSTR       szKey,
  83. //          LPBYTE      lpStruct,
  84. //          UINT        uSizeStruct,
  85. //          LPSTR       szFile
  86. //      );
  87. //
  88. //      BOOL WritePrivateProfileStruct
  89. //      (
  90. //          LPSTR       szSection,
  91. //          LPSTR       szKey,
  92. //          LPBYTE      lpStruct,
  93. //          UINT        uSizeStruct,
  94. //          LPSTR       szFile
  95. //      );
  96. //
  97. //      If you are building an application that is for Window for Workgroups
  98. //      or newer versions of Windows, you will probably want to use the
  99. //      above functions.
  100. //
  101. //  Arguments:
  102. //      PCTSTR pszKey: Pointer to key name for the stored data.
  103. //  
  104. //      LPBYTE pbStruct: Pointer to the data to be saved.
  105. //  
  106. //      UINT cbStruct: Count in bytes of the data to store.
  107. //  
  108. //  Return (BOOL):
  109. //      The return value is TRUE if the function is successful. It is FALSE
  110. //      if it fails.
  111. //  
  112. //  History:
  113. //       3/10/93
  114. //  
  115. //--------------------------------------------------------------------------;
  116.  
  117. BOOL FNGLOBAL AppProfileWriteBytes
  118. (
  119.     PCTSTR          pszKey,
  120.     LPBYTE          pbStruct,
  121.     UINT            cbStruct
  122. )
  123. {
  124.     static TCHAR achNibbleToChar[] =
  125.     {
  126.     '0', '1', '2', '3', '4', '5', '6', '7',
  127.     '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
  128.     };
  129.     #define     NIBBLE2CHAR(x)      (achNibbleToChar[x])
  130.     
  131.     TCHAR       ach[APP_MAX_STRING_RC_CHARS];
  132.     LPTSTR      psz;
  133.     LPTSTR      pch;
  134.     UINT        cchTemp;
  135.     BOOL        fAllocated;
  136.     BOOL        fReturn;
  137.     BYTE        b;
  138.     BYTE        bChecksum;
  139.  
  140.     //
  141.     //  if pbStruct is NULL, then erase the key from the ini file, otherwise
  142.     //  format the raw bytes into a hex string and write that out...
  143.     //
  144.     fAllocated = FALSE;
  145.     psz        = NULL;
  146.     if (NULL != pbStruct)
  147.     {
  148.     //
  149.     //  check if the quick buffer can be used for formatting the output
  150.     //  text--if it cannot, then alloc space for it. note that space
  151.     //  must be available for an ending checksum byte (2 bytes for high
  152.     //  and low nibble) as well as a null terminator.
  153.     //
  154.     psz     = (LPTSTR)ach;
  155.     cchTemp = cbStruct * 2 + 3;
  156.     if (cchTemp > SIZEOF(ach))
  157.     {
  158.         psz = GlobalAllocPtr(GHND, cchTemp * sizeof(TCHAR));
  159.         if (NULL == psz)
  160.         return (FALSE);
  161.  
  162.         fAllocated = TRUE;
  163.     }
  164.   
  165.     //
  166.     //  step through all bytes in the structure and convert it to
  167.     //  a string of hex numbers...
  168.     //
  169.     bChecksum = 0;
  170.     for (pch = psz; 0 != cbStruct; cbStruct--, pbStruct++)
  171.     {
  172.         //
  173.         //  grab the next byte and add into checksum...
  174.         //
  175.         bChecksum += (b = *pbStruct);
  176.       
  177.         *pch++ = NIBBLE2CHAR((b >> (BYTE)4) & (BYTE)0x0F);
  178.         *pch++ = NIBBLE2CHAR(b & (BYTE)0x0F);
  179.     }
  180.  
  181.     //
  182.     //  add the checksum byte to the end and null terminate the hex
  183.     //  dumped string...
  184.     //
  185.     *pch++ = NIBBLE2CHAR((bChecksum >> (BYTE)4) & (BYTE)0x0F);
  186.     *pch++ = NIBBLE2CHAR(bChecksum & (BYTE)0x0F);
  187.     *pch   = '\0';
  188.     }
  189.  
  190.     //
  191.     //  write the string of hex bytes out to the ini file...
  192.     //
  193.     fReturn = WriteProfileString(gszAppSection, pszKey, psz);
  194.  
  195.     //
  196.     //  free the temporary buffer if one was allocated (lots of bytes!)
  197.     //
  198.     if (fAllocated)
  199.     GlobalFreePtr(psz);
  200.   
  201.     return (fReturn);
  202. } // AppProfileWriteBytes
  203.  
  204.  
  205. //--------------------------------------------------------------------------;
  206. //  
  207. //  BOOL AppProfileReadBytes
  208. //  
  209. //  Description:
  210. //      This function reads a previously stored structure of bytes from
  211. //      the application's ini file. This data must have been written with
  212. //      the AppProfileWriteBytes function--it is checksumed to keep bad
  213. //      data from blowing up the application.
  214. //  
  215. //      NOTE! Starting with Windows for Workgroups 3.1 there are two new
  216. //      profile functions that provide the same functionality of this
  217. //      function. Specifically, these functions are GetPrivateProfileStruct
  218. //      and WritePrivateProfileStruct. These new functions are provided
  219. //      by the Common Controls DLL. The prototypes are as follows:
  220. //
  221. //      BOOL GetPrivateProfileStruct
  222. //      (
  223. //          LPSTR       szSection,
  224. //          LPSTR       szKey,
  225. //          LPBYTE      lpStruct,
  226. //          UINT        uSizeStruct,
  227. //          LPSTR       szFile
  228. //      );
  229. //
  230. //      BOOL WritePrivateProfileStruct
  231. //      (
  232. //          LPSTR       szSection,
  233. //          LPSTR       szKey,
  234. //          LPBYTE      lpStruct,
  235. //          UINT        uSizeStruct,
  236. //          LPSTR       szFile
  237. //      );
  238. //
  239. //      If you are building an application that is for Window for Workgroups
  240. //      or newer versions of Windows, you will probably want to use the
  241. //      above functions.
  242. //  
  243. //  Arguments:
  244. //      PCTSTR pszKey: Pointer to key that contains the data.
  245. //  
  246. //      LPBYTE pbStruct: Pointer to buffer to receive the data.
  247. //  
  248. //      UINT cbStruct: Number of bytes expected.
  249. //  
  250. //  Return (BOOL):
  251. //      The return value is TRUE if the function is successful. It is FALSE
  252. //      if the function fails (bad checksum, missing key, etc).
  253. //  
  254. //  History:
  255. //       3/10/93
  256. //  
  257. //--------------------------------------------------------------------------;
  258.  
  259. BOOL FNGLOBAL AppProfileReadBytes
  260. (
  261.     PCTSTR          pszKey,
  262.     LPBYTE          pbStruct,
  263.     UINT            cbStruct
  264. )
  265. {
  266.     //
  267.     //  note that the following works for both upper and lower case, and
  268.     //  will return valid values for garbage chars
  269.     //
  270.     #define CHAR2NIBBLE(ch) (BYTE)( ((ch) >= '0' && (ch) <= '9') ?  \
  271.                 (BYTE)((ch) - '0') :                \
  272.                 ((BYTE)(10 + (ch) - 'A') & (BYTE)0x0F) )
  273.  
  274.     TCHAR       ach[APP_MAX_STRING_RC_CHARS];
  275.     LPTSTR      psz;
  276.     LPTSTR      pch;
  277.     UINT        cchTemp;
  278.     UINT        u;
  279.     BOOL        fAllocated;
  280.     BOOL        fReturn;
  281.     BYTE        b;
  282.     BYTE        bChecksum;
  283.     TCHAR       ch;
  284.  
  285.     //
  286.     //  add one the the number of bytes needed to accomodate the checksum
  287.     //  byte placed at the end by AppProfileWriteBytes...
  288.     //
  289.     cbStruct++;
  290.  
  291.     //
  292.     //  check if the quick buffer can be used for retrieving the input
  293.     //  text--if it cannot, then alloc space for it. note that there must
  294.     //  be space available for the null terminator (the +1 below).
  295.     //
  296.     fAllocated = FALSE;
  297.     psz        = (LPTSTR)ach;
  298.     cchTemp    = cbStruct * 2 + 1;
  299.     if (cchTemp > SIZEOF(ach))
  300.     {
  301.     psz = GlobalAllocPtr(GHND, cchTemp * sizeof(TCHAR));
  302.     if (NULL == psz)
  303.         return (FALSE);
  304.  
  305.     fAllocated = TRUE;
  306.     }
  307.  
  308.     //
  309.     //  read the hex string... if it is not the correct length, then assume
  310.     //  error and return.
  311.     //
  312.     fReturn = FALSE;
  313.     u = (UINT)GetProfileString(gszAppSection, pszKey, gszNull, psz, cchTemp);
  314.     if ((cbStruct * 2) == u)
  315.     {
  316.     bChecksum = 0;
  317.     for (pch = psz; 0 != cbStruct; cbStruct--, pbStruct++)
  318.     {
  319.         ch = *pch++;
  320.         b  = CHAR2NIBBLE(ch) << (BYTE)4;
  321.         ch = *pch++;
  322.         b |= CHAR2NIBBLE(ch);
  323.  
  324.         //
  325.         //  if this is not the final byte (the checksum byte), then 
  326.         //  store it and accumulate checksum..
  327.         //
  328.         if (cbStruct != 1)
  329.         bChecksum += (*pbStruct = b);
  330.     }
  331.  
  332.     //
  333.     //  check the last byte read against the checksum that we calculated
  334.     //  if they are not equal then return error...
  335.     //
  336.     fReturn = (bChecksum == b);
  337.     }
  338.  
  339.  
  340.     //
  341.     //  free the temporary buffer if one was allocated (lots of bytes!)
  342.     //
  343.     if (fAllocated)
  344.     GlobalFreePtr(psz);
  345.   
  346.     return (fReturn);
  347. } // AppProfileReadBytes
  348.  
  349.  
  350. //--------------------------------------------------------------------------;
  351. //
  352. //  int AppMsgBox
  353. //
  354. //  Description:
  355. //      This function displays a message for the application in a standard
  356. //      message box.
  357. //
  358. //      Note that this function takes any valid argument list that can
  359. //      be passed to wsprintf. Because of this, the application must
  360. //      remember to cast near string pointers to FAR when built for Win 16.
  361. //      You will get a nice GP fault if you do not cast them correctly.
  362. //
  363. //  Arguments:
  364. //      HWND hwnd: Handle to parent window for message box holding the
  365. //      message.
  366. //
  367. //      UINT fuStyle: Style flags for MessageBox().
  368. //
  369. //      PCTSTR pszFormat: Format string used for wvsprintf().
  370. //
  371. //  Return (int):
  372. //      The return value is the result of MessageBox() function.
  373. //
  374. //  History:
  375. //       2/13/93
  376. //
  377. //--------------------------------------------------------------------------;
  378.  
  379. int FNCGLOBAL AppMsgBox
  380. (
  381.     HWND            hwnd,
  382.     UINT            fuStyle,
  383.     PCTSTR          pszFormat,
  384.     ...
  385. )
  386. {
  387.     va_list     va;
  388.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  389.     int         n;
  390.  
  391.     //
  392.     //  format and display the message..
  393.     //
  394.     va_start(va, pszFormat);
  395.     wvsprintf(ach, pszFormat, va);
  396.     va_end(va);
  397.  
  398.     n = MessageBox(hwnd, ach, gszAppName, fuStyle);
  399.  
  400.     return (n);
  401. } // AppMsgBox()
  402.  
  403.  
  404. //--------------------------------------------------------------------------;
  405. //
  406. //  int AppMsgBoxId
  407. //
  408. //  Description:
  409. //      This function displays a message for the application. The message
  410. //      text is retrieved from the string resource table using LoadString.
  411. //
  412. //      Note that this function takes any valid argument list that can
  413. //      be passed to wsprintf. Because of this, the application must
  414. //      remember to cast near string pointers to FAR when built for Win 16.
  415. //      You will get a nice GP fault if you do not cast them correctly.
  416. //
  417. //  Arguments:
  418. //      HWND hwnd: Handle to parent window for message box holding the
  419. //      message.
  420. //
  421. //      UINT fuStyle: Style flags for MessageBox().
  422. //
  423. //      UINT uIdsFormat: String resource id to be loaded with LoadString()
  424. //      and used a the format string for wvsprintf().
  425. //
  426. //  Return (int):
  427. //      The return value is the result of MessageBox() if the string
  428. //      resource specified by uIdsFormat is valid. The return value is zero
  429. //      if the string resource failed to load.
  430. //
  431. //  History:
  432. //       2/13/93
  433. //
  434. //--------------------------------------------------------------------------;
  435.  
  436. int FNCGLOBAL AppMsgBoxId
  437. (
  438.     HWND            hwnd,
  439.     UINT            fuStyle,
  440.     UINT            uIdsFormat,
  441.     ...
  442. )
  443. {
  444.     va_list     va;
  445.     TCHAR       szFormat[APP_MAX_STRING_RC_CHARS];
  446.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  447.     int         n;
  448.  
  449.     n = LoadString(ghinst, uIdsFormat, szFormat, SIZEOF(szFormat));
  450.     if (0 != n)
  451.     {
  452.     //
  453.     //  format and display the message..
  454.     //
  455.     va_start(va, uIdsFormat);
  456.     wvsprintf(ach, szFormat, va);
  457.     va_end(va);
  458.  
  459.     n = MessageBox(hwnd, ach, gszAppName, fuStyle);
  460.     }
  461.  
  462.     return (n);
  463. } // AppMsgBoxId()
  464.  
  465.  
  466. //--------------------------------------------------------------------------;
  467. //
  468. //  void AppHourGlass
  469. //
  470. //  Description:
  471. //      This function changes the cursor to that of the hour glass or
  472. //      back to the previous cursor.
  473. //
  474. //      This function can be called recursively.
  475. //
  476. //  Arguments:
  477. //      BOOL fHourGlass: TRUE if we need the hour glass.  FALSE if we need
  478. //      the arrow back.
  479. //
  480. //  Return (void):
  481. //      On return, the cursor will be what was requested.
  482. //
  483. //  History:
  484. //      11/ 8/92
  485. //
  486. //--------------------------------------------------------------------------;
  487.  
  488. void FNGLOBAL AppHourGlass
  489. (
  490.     BOOL            fHourGlass
  491. )
  492. {
  493.     static HCURSOR  hcur;
  494.     static UINT     uWaiting = 0;
  495.  
  496.     if (fHourGlass)
  497.     {
  498.     if (!uWaiting)
  499.     {
  500.         hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  501.         ShowCursor(TRUE);
  502.     }
  503.  
  504.     uWaiting++;
  505.     }
  506.     else
  507.     {
  508.     --uWaiting;
  509.  
  510.     if (!uWaiting)
  511.     {
  512.         ShowCursor(FALSE);
  513.         SetCursor(hcur);
  514.     }
  515.     }
  516. } // AppHourGlass()
  517.  
  518.  
  519. //--------------------------------------------------------------------------;
  520. //
  521. //  int AppDialogBox
  522. //
  523. //  Description:
  524. //      This function is used to display a dialog modal box.
  525. //
  526. //  Arguments:
  527. //      HWND hwnd: Handle to parent window for new dialog.
  528. //
  529. //      LPCSTR pszDlg: Dialog template to use.
  530. //
  531. //      DLGPROC pfnDlg: Pointer to dialog procedure.
  532. //
  533. //      LPARAM lParam: Any lParam to be passed as lParam for WM_INITDIALOG.
  534. //
  535. //  Return (int):
  536. //      The return value is the nResult from EndDialog.
  537. //
  538. //  History:
  539. //      11/ 8/92
  540. //
  541. //--------------------------------------------------------------------------;
  542.  
  543. int FNGLOBAL AppDialogBox
  544. (
  545.     HWND            hwnd,
  546.     LPCTSTR         pszDlg,
  547.     DLGPROC         pfnDlg,
  548.     LPARAM          lParam
  549. )
  550. {
  551.     int     nResult;
  552.  
  553.     //
  554.     //  !!! NT doesn't need this--neither does Win 3.1 with C7/C8 !!!
  555.     //
  556.     //
  557.     nResult = 0;
  558.     pfnDlg  = (DLGPROC)MakeProcInstance((FARPROC)pfnDlg, ghinst);
  559.     if (NULL != pfnDlg)
  560.     {
  561.     nResult = DialogBoxParam(ghinst, pszDlg, hwnd, pfnDlg, lParam);
  562.     FreeProcInstance((FARPROC)pfnDlg);
  563.     }
  564.  
  565.     return (nResult);
  566. } // AppDialogBox()
  567.  
  568.  
  569. //--------------------------------------------------------------------------;
  570. //
  571. //  int AppSetWindowText
  572. //
  573. //  Description:
  574. //      This function formats a string and sets the specified window text
  575. //      to the result.
  576. //
  577. //  Arguments:
  578. //      HWND hwnd: Handle to window to receive the new text.
  579. //
  580. //      PCTSTR pszFormat: Pointer to any valid format for wsprintf.
  581. //
  582. //  Return (int):
  583. //      The return value is the number of bytes that the resulting window
  584. //      text was.
  585. //
  586. //  History:
  587. //       2/ 7/93
  588. //
  589. //--------------------------------------------------------------------------;
  590.  
  591. int FNCGLOBAL AppSetWindowText
  592. (
  593.     HWND            hwnd,
  594.     PCTSTR          pszFormat,
  595.     ...
  596. )
  597. {
  598.     va_list     va;
  599.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  600.     int         n;
  601.  
  602.     //
  603.     //  format and display the string in the window...
  604.     //
  605.     va_start(va, pszFormat);
  606.     n = wvsprintf(ach, pszFormat, va);
  607.     va_end(va);
  608.  
  609.     SetWindowText(hwnd, ach);
  610.  
  611.     return (n);
  612. } // AppSetWindowText()
  613.  
  614.  
  615. //--------------------------------------------------------------------------;
  616. //
  617. //  int AppSetWindowTextId
  618. //
  619. //  Description:
  620. //      This function formats a string and sets the specified window text
  621. //      to the result. The format string is extracted from the string
  622. //      table using LoadString() on the uIdsFormat argument.
  623. //
  624. //  Arguments:
  625. //      HWND hwnd: Handle to window to receive the new text.
  626. //
  627. //      UINT uIdsFormat: String resource id to be loaded with LoadString()
  628. //      and used a the format string for wvsprintf().
  629. //
  630. //  Return (int):
  631. //      The return value is the number of bytes that the resulting window
  632. //      text was. This value is zero if the LoadString() function fails
  633. //      for the uIdsFormat argument.
  634. //
  635. //  History:
  636. //       2/ 7/93
  637. //
  638. //--------------------------------------------------------------------------;
  639.  
  640. int FNCGLOBAL AppSetWindowTextId
  641. (
  642.     HWND            hwnd,
  643.     UINT            uIdsFormat,
  644.     ...
  645. )
  646. {
  647.     va_list     va;
  648.     TCHAR       szFormat[APP_MAX_STRING_RC_CHARS];
  649.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  650.     int         n;
  651.  
  652.     n = LoadString(ghinst, uIdsFormat, szFormat, SIZEOF(szFormat));
  653.     if (0 != n)
  654.     {
  655.     //
  656.     //  format and display the string in the window...
  657.     //
  658.     va_start(va, uIdsFormat);
  659.     n = wvsprintf(ach, szFormat, va);
  660.     va_end(va);
  661.  
  662.     SetWindowText(hwnd, ach);
  663.     }
  664.  
  665.     return (n);
  666. } // AppSetWindowTextId()
  667.  
  668.  
  669. //--------------------------------------------------------------------------;
  670. //  
  671. //  int AppMEditPrintF
  672. //  
  673. //  Description:
  674. //      This function is used to print formatted text into a Multiline
  675. //      Edit Control as if it were a standard console display. This is
  676. //      a very easy way to display small amounts of text information
  677. //      that can be scrolled and copied to the clip-board.
  678. //  
  679. //  Arguments:
  680. //      HWND hedit: Handle to a Multiline Edit control.
  681. //  
  682. //      PCTSTR pszFormat: Pointer to any valid format for wsprintf. If
  683. //      this argument is NULL, then the Multiline Edit Control is cleared
  684. //      of all text.
  685. //  
  686. //  Return (int):
  687. //      Returns the number of characters written into the edit control.
  688. //
  689. //  History:
  690. //      05/16/93
  691. //  
  692. //--------------------------------------------------------------------------;
  693.  
  694. int FNCGLOBAL AppMEditPrintF
  695. (
  696.     HWND            hedit,
  697.     PCTSTR          pszFormat,
  698.     ...
  699. )
  700. {
  701.     va_list     va;
  702.     TCHAR       ach[APP_MAX_STRING_RC_CHARS];
  703.     int         n;
  704.  
  705.  
  706.     //
  707.     //  if the pszFormat argument is NULL, then just clear all text in
  708.     //  the edit control..
  709.     //
  710.     if (NULL == pszFormat)
  711.     {
  712.     SetWindowText(hedit, gszNull);
  713.     return (0);
  714.     }
  715.  
  716.  
  717.     //
  718.     //  format and display the string in the window...
  719.     //
  720.     va_start(va, pszFormat);
  721.     n = wvsprintf(ach, pszFormat, va);
  722.     va_end(va);
  723.  
  724.     Edit_SetSel(hedit, (WPARAM)-1, (LPARAM)-1);
  725.     Edit_ReplaceSel(hedit, ach);
  726.  
  727.     return (n);
  728. } // AppMEditPrintF()
  729.  
  730.  
  731. //--------------------------------------------------------------------------;
  732. //
  733. //  DWORD AppGetWindowsVersion
  734. //
  735. //  Description:
  736. //      This function returns the version of Windows that the application
  737. //      is running on plus some platform information.
  738. //
  739. //  Arguments:
  740. //      PTSTR pach: Options pointer to buffer to receive text string of
  741. //      the Windows version and platform.
  742. //
  743. //  Return (LRESULT):
  744. //      The return value will be the version and platform information of
  745. //      the current operating system in the following format:
  746. //
  747. //      0xPPPPMMRR where:
  748. //
  749. //      MM      :   major version of Windows
  750. //      RR      :   minor version (revision) of Windows
  751. //      PPPP    :   the platform the application is running on which
  752. //                  will be one of the following:
  753. //
  754. //                  #ifdef WIN32
  755. //                      the HIWORD() is RESERVED except for the high bit:
  756. //                          high bit is 0 = Windows NT
  757. //                          high bit is 1 = Win32s/Windows 3.1
  758. //                  #else
  759. //                      0xMMRR = Major and Minor version of [MS-]DOS
  760. //                      GetWinFlags() & 0x8000 = Windows on OS/2 (WLO)
  761. //                      GetWinFlags() & 0x4000 = Windows on Windows NT (WOW)
  762. //                  #endif
  763. //
  764. //  History:
  765. //       2/13/93
  766. //
  767. //--------------------------------------------------------------------------;
  768.  
  769. LRESULT FNGLOBAL AppGetWindowsVersion
  770. (
  771.     PTSTR           pszEnvironment,
  772.     PTSTR           pszPlatform
  773. )
  774. {
  775.  
  776.     BYTE    bVerWinMajor;
  777.     BYTE    bVerWinMinor;
  778.     UINT    uVerEnv;
  779.     DWORD   dw;
  780.     LRESULT lr;
  781.  
  782.     dw = GetVersion();
  783.  
  784.     //
  785.     //  massage the version information into something intelligent
  786.     //
  787.     //
  788.     bVerWinMajor = LOBYTE(LOWORD(dw));
  789.     bVerWinMinor = HIBYTE(LOWORD(dw));
  790.     uVerEnv      = HIWORD(dw);
  791.     lr = MAKELPARAM(((UINT)bVerWinMajor << 8) | bVerWinMinor, uVerEnv);
  792.  
  793.     //
  794.     //  if caller wants the environment string version...
  795.     //
  796.     if (NULL != pszEnvironment)
  797.     {
  798.     //
  799.     //
  800.     //
  801. #ifdef WIN32
  802. {
  803.     static TCHAR    szFormatVersion[]   = TEXT("%s Version %u.%.2u");
  804.     static TCHAR    szEnvWinNT[]        = TEXT("Windows NT");
  805.     static TCHAR    szEnvWin32s[]       = TEXT("Win32s");
  806.  
  807.     wsprintf(pszEnvironment, szFormatVersion,
  808.          (LPSTR)((0x8000 & uVerEnv) ? szEnvWin32s : szEnvWinNT),
  809.          bVerWinMajor, bVerWinMinor);
  810. }
  811. #else
  812. {
  813. #ifndef WF_WINNT
  814.     #define WF_CPUR4000         0x0100
  815.     #define WF_CPUALPHA21064    0x0200
  816.     #define WF_WINNT            0x4000
  817.     #define WF_WLO              0x8000
  818. #endif
  819.  
  820.     static TCHAR    szFormatSubSys[]= TEXT("Windows Version %u.%.2u (%s%s)\n%s Subsystem, DOS Version %u.%.2u");
  821.     static TCHAR    szFormatDOS[]   = TEXT("Windows Version %u.%.2u (%s%s)\nDOS Version %u.%.2u");
  822.     static TCHAR    szSubSysWLO[]   = TEXT("WLO");
  823.     static TCHAR    szSubSysWOW[]   = TEXT("WOW");
  824.     static TCHAR    szModeEnhanced[]= TEXT("Enhanced");
  825.     static TCHAR    szModeStandard[]= TEXT("Standard");
  826.     static TCHAR    szEnvPaging[]   = TEXT(", Paging");
  827.  
  828.     DWORD   dwWinFlags;
  829.     PTSTR   pszMode;
  830.  
  831.     BYTE    bVerEnvMajor    = HIBYTE(LOWORD(uVerEnv));
  832.     BYTE    bVerEnvMinor    = LOBYTE(LOWORD(uVerEnv));
  833.  
  834.     dwWinFlags = GetWinFlags();
  835.  
  836.     pszMode = (dwWinFlags & WF_ENHANCED) ? szModeEnhanced : szModeStandard;
  837.     if (dwWinFlags & (WF_WLO | WF_WINNT))
  838.     {
  839.     wsprintf(pszEnvironment, szFormatSubSys, bVerWinMajor, bVerWinMinor,
  840.          (LPSTR)pszMode,
  841.          (LPSTR)((dwWinFlags & WF_PAGING) ? szEnvPaging : gszNull),
  842.          (LPSTR)((dwWinFlags & WF_WINNT) ? szSubSysWOW : szSubSysWLO),
  843.          bVerEnvMajor, bVerEnvMinor);
  844.     }
  845.     else
  846.     {
  847.     wsprintf(pszEnvironment, szFormatDOS, bVerWinMajor, bVerWinMinor,
  848.          (LPSTR)pszMode,
  849.          (LPSTR)((dwWinFlags & WF_PAGING) ? szEnvPaging : gszNull),
  850.          bVerEnvMajor, bVerEnvMinor);
  851.     }
  852. }
  853. #endif
  854.     }
  855.  
  856.     //
  857.     //  if caller wants the platform string version...
  858.     //
  859.     if (NULL != pszPlatform)
  860.     {
  861. #ifdef WIN32
  862. {
  863.     static TCHAR    szFormatPlatform[]  = TEXT("%s%u, %u Processor(s)");
  864.     static TCHAR    szProcessorIntel[]  = TEXT("Intel ");
  865.     static TCHAR    szProcessorMIPS[]   = TEXT("MIPS R");
  866.     static TCHAR    szProcessorAlpha[]  = TEXT("DEC Alpha ");
  867.     static TCHAR    szProcessorDunno[]  = TEXT("Dunno zYz");
  868.  
  869.     SYSTEM_INFO sysinfo;
  870.     PTSTR       pszProcessor;
  871.  
  872.     //
  873.     //  this is absolutely silly. one would think that the dwOemId member
  874.     //  would provide something useful like the processor class... but
  875.     //  no, it doesn't--it is always 0.
  876.     //
  877.     GetSystemInfo(&sysinfo);
  878.     switch (sysinfo.dwProcessorType)
  879.     {
  880.     case PROCESSOR_INTEL_386:
  881.     case PROCESSOR_INTEL_486:
  882.         pszProcessor = szProcessorIntel;
  883.         break;
  884.  
  885.     case PROCESSOR_MIPS_R4000:
  886.         pszProcessor = szProcessorMIPS;
  887.         break;
  888.  
  889.     case PROCESSOR_ALPHA_21064:
  890.         pszProcessor = szProcessorAlpha;
  891.         break;
  892.  
  893.     default:
  894.         pszProcessor = szProcessorDunno;
  895.         break;
  896.     }
  897.  
  898.     //
  899.     //
  900.     //
  901.     wsprintf(pszPlatform, szFormatPlatform, (LPSTR)pszProcessor,
  902.          sysinfo.dwProcessorType, sysinfo.dwNumberOfProcessors);
  903. }
  904. #else
  905. {
  906.     static TCHAR    szPlat286[]         = TEXT("80286");
  907.     static TCHAR    szPlat386[]         = TEXT("80386");
  908.     static TCHAR    szPlat486[]         = TEXT("i486");
  909.     static TCHAR    szPlatR4000[]       = TEXT("MIPS R4000, Emulation: ");
  910.     static TCHAR    szPlatAlpha21064[]  = TEXT("Alpha 21064, Emulation: ");
  911.     static TCHAR    szPlat80x87[]       = TEXT(", 80x87");
  912.  
  913.     DWORD   dwWinFlags;
  914.  
  915.     dwWinFlags = GetWinFlags();
  916.     pszPlatform[0] = '\0';
  917.  
  918.     if (dwWinFlags & (WF_WLO | WF_WINNT))
  919.     {
  920.     if (dwWinFlags & WF_CPUR4000)
  921.         lstrcpy(pszPlatform, szPlatR4000);
  922.     else if (dwWinFlags & WF_CPUALPHA21064)
  923.         lstrcpy(pszPlatform, szPlatAlpha21064);
  924.     }
  925.  
  926.     if (dwWinFlags & WF_CPU286)
  927.     lstrcat(pszPlatform, szPlat286);
  928.     else if (dwWinFlags & WF_CPU386)
  929.     lstrcat(pszPlatform, szPlat386);
  930.     else if (dwWinFlags & WF_CPU486)
  931.     lstrcat(pszPlatform, szPlat486);
  932.  
  933.     if (dwWinFlags & WF_80x87)
  934.     lstrcat(pszPlatform, szPlat80x87);
  935. }
  936. #endif
  937.     }
  938.  
  939.     //
  940.     //  return the result
  941.     //
  942.     return (lr);
  943. } // AppGetWindowsVersion()
  944.  
  945.  
  946. //--------------------------------------------------------------------------;
  947. //
  948. //  HFONT AppChooseFont
  949. //
  950. //  Description:
  951. //      This function is a wrapper for the ChooseFont() common dialog.
  952. //      The purpose of this function is to let the user choose a font that
  953. //      looks good to them--regardless of how stupid it really looks.
  954. //
  955. //  Arguments:
  956. //      HWND hwnd: Handle to parent window for chooser dialog.
  957. //
  958. //      HFONT hfont: Handle to current font (default for chooser dialog).
  959. //
  960. //      PLOGFONT plf: Pointer to optional LOGFONT structure to receive a
  961. //      copy of the LOGFONT information for the newly chosen font.
  962. //
  963. //  Return (HFONT):
  964. //      The return value is the newly chosen font. If no new font was chosen
  965. //      then the return value is NULL.
  966. //
  967. //  History:
  968. //       2/ 7/93
  969. //
  970. //--------------------------------------------------------------------------;
  971.  
  972. HFONT FNGLOBAL AppChooseFont
  973. (
  974.     HWND            hwnd,
  975.     HFONT           hfont,
  976.     PLOGFONT        plf
  977. )
  978. {
  979.     LOGFONT     lf;
  980.     CHOOSEFONT  cf;
  981.     BOOL        f;
  982.     HFONT       hfontNew;
  983.  
  984.     //
  985.     //  get the font info for the current font...
  986.     //
  987.     GetObject(hfont, sizeof(LOGFONT), (LPVOID)&lf);
  988.  
  989.     //
  990.     //  fill in the choosefont structure
  991.     //
  992.     cf.lStructSize  = sizeof(CHOOSEFONT);
  993.     cf.hwndOwner    = hwnd;
  994.     cf.hDC          = NULL;
  995.     cf.Flags        = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT;
  996.     cf.lCustData    = 0;
  997.     cf.lpfnHook     = NULL;
  998.     cf.hInstance    = NULL;
  999.     cf.nFontType    = SCREEN_FONTTYPE;
  1000.     cf.lpLogFont    = (LPLOGFONT)&lf;
  1001.  
  1002.     //
  1003.     //  splash a dialog into the user's face..
  1004.     //
  1005.     hfontNew = NULL;
  1006.     f = ChooseFont(&cf);
  1007.     if (f)
  1008.     {
  1009.     //
  1010.     //  create the new font..
  1011.     //
  1012.     hfontNew = CreateFontIndirect(&lf);
  1013.     if (NULL == hfontNew)
  1014.         return (NULL);
  1015.  
  1016.     //
  1017.     //  copy the logfont structure if caller wants it
  1018.     //
  1019.     if (NULL != plf)
  1020.         *plf = lf;
  1021.     }
  1022.  
  1023.     //
  1024.     //  return the new font (if one was chosen)
  1025.     //
  1026.     return (hfontNew);
  1027. } // AppChooseFont()
  1028.  
  1029.  
  1030. //==========================================================================;
  1031. //
  1032. //  Misc rarely used application dialogs and stuff...
  1033. //
  1034. //
  1035. //==========================================================================;
  1036.  
  1037. //--------------------------------------------------------------------------;
  1038. //
  1039. //  BOOL AboutDlgProc
  1040. //
  1041. //  Description:
  1042. //      This dialog procedure is used for the ubiquitous about box.
  1043. //
  1044. //  Arguments:
  1045. //      HWND hwnd: Handle to window.
  1046. //
  1047. //      UINT uMsg: Message being sent to the window.
  1048. //
  1049. //      WPARAM wParam: Specific argument to message.
  1050. //
  1051. //      LPARAM lParam: Specific argument to message.
  1052. //
  1053. //  Return (BOOL):
  1054. //      The return value is specific to the message that was received. For
  1055. //      the most part, it is FALSE if this dialog procedure does not handle
  1056. //      a message.
  1057. //
  1058. //  History:
  1059. //       1/ 2/93
  1060. //
  1061. //--------------------------------------------------------------------------;
  1062.  
  1063. BOOL FNEXPORT AboutDlgProc
  1064. (
  1065.     HWND            hwnd,
  1066.     UINT            uMsg,
  1067.     WPARAM          wParam,
  1068.     LPARAM          lParam
  1069. )
  1070. {
  1071.     HWND    hwndT;
  1072.     PTSTR   pach;
  1073.     UINT    u;
  1074.  
  1075.     switch (uMsg)
  1076.     {
  1077.     case WM_INITDIALOG:
  1078.         //
  1079.         //  display some OS version information
  1080.         //
  1081.         //
  1082.         pach = (PTSTR)LocalAlloc(LPTR, APP_MAX_STRING_RC_BYTES);
  1083.         if (NULL == pach)
  1084.         return (TRUE);
  1085.  
  1086.         AppGetWindowsVersion(pach, NULL);
  1087.         hwndT = GetDlgItem(hwnd, IDD_ABOUT_VERSION_OS);
  1088.         SetWindowText(hwndT, pach);
  1089.  
  1090.         AppGetWindowsVersion(NULL, pach);
  1091.         hwndT = GetDlgItem(hwnd, IDD_ABOUT_VERSION_PLATFORM);
  1092.         SetWindowText(hwndT, pach);
  1093.  
  1094.         wsprintf(pach, "MMREG.H V%u.%.02u",
  1095.              (_INC_MMREG / 100), (_INC_MMREG % 100));
  1096.         hwndT = GetDlgItem(hwnd, IDD_ABOUT_VERSION_MMSYSTEM);
  1097.         SetWindowText(hwndT, pach);
  1098.  
  1099.         LocalFree((HLOCAL)pach);
  1100.  
  1101.         //
  1102.         //  return nonzero to set the input focus to the control
  1103.         //  identified by the (hwndFocus = (HWND)wParam) argument.
  1104.         //  a zero return tells the dialog manager that this function
  1105.         //  has set the focus using SetFocus.
  1106.         //
  1107.         return (TRUE);
  1108.  
  1109.     case WM_COMMAND:
  1110.         u = GET_WM_COMMAND_ID(wParam, lParam);
  1111.         if ((IDOK == u) || (IDCANCEL == u))
  1112.         {
  1113.         EndDialog(hwnd, (IDOK == u));
  1114.         }
  1115.         break;
  1116.     }
  1117.  
  1118.     return (FALSE);
  1119. } // AboutDlgProc()
  1120.  
  1121.  
  1122. //==========================================================================;
  1123. //
  1124. //  Initialization and exit code...
  1125. //
  1126. //
  1127. //==========================================================================;
  1128.  
  1129. TCHAR   gszKeyWindow[]      = TEXT("Window");
  1130. TCHAR   gszKeyFont[]        = TEXT("Font");
  1131.  
  1132. //--------------------------------------------------------------------------;
  1133. //
  1134. //  BOOL MMCapsChooseFont
  1135. //
  1136. //  Description:
  1137. //      This function lets the user choose a new font for the script window.
  1138. //      After a new font is chosen, the font structure is stored to the
  1139. //      .ini file so it can be restored on the next run of this application.
  1140. //
  1141. //  Arguments:
  1142. //      HWND hwnd: Handle to main window.
  1143. //
  1144. //  Return (BOOL):
  1145. //      The return value is TRUE if a new font was chosen. It is FALSE if
  1146. //      the user canceled the operation.
  1147. //
  1148. //  History:
  1149. //       2/ 7/93
  1150. //
  1151. //--------------------------------------------------------------------------;
  1152.  
  1153. BOOL FNGLOBAL MMCapsChooseFont
  1154. (
  1155.     HWND            hwnd
  1156. )
  1157. {
  1158.     LOGFONT     lf;
  1159.     HWND        hlb;
  1160.     HFONT       hfont;
  1161.     HFONT       hfontNew;
  1162.  
  1163.     hlb = GetDlgItem(hwnd, IDD_APP_LIST_DEVICES);
  1164.  
  1165.     //
  1166.     //  get the current font and pass it to the choose font dialog
  1167.     //
  1168.     hfont = GetWindowFont(gptlbDrivers->hlb);
  1169.  
  1170.     hfontNew = AppChooseFont(hwnd, hfont, &lf);
  1171.     if (NULL == hfontNew)
  1172.     return (FALSE);
  1173.  
  1174.     //
  1175.     //  select the new font into the script window and delete the old one
  1176.     //
  1177.     TlbSetFont(gptlbDrivers, hfontNew, TRUE);
  1178.     DeleteFont(hfont);
  1179.  
  1180.  
  1181.     //
  1182.     //  save the complete description of the chosen font so there can be
  1183.     //  no strangness in the font mapping next run. this is overkill, but
  1184.     //  it works...
  1185.     //
  1186.     AppProfileWriteBytes(gszKeyFont, (LPBYTE)&lf, sizeof(lf));
  1187.  
  1188.     return (TRUE);
  1189. } // MMCapsChooseFont()
  1190.  
  1191.  
  1192. //--------------------------------------------------------------------------;
  1193. //  
  1194. //  BOOL MMCapsSettingsRestore
  1195. //  
  1196. //  Description:
  1197. //      This function restores state information for the application. This
  1198. //      function is called just after the main window is created (it has
  1199. //      not been ShowWindow()'d). This function will generate the call
  1200. //      to ShowWindow before returning.
  1201. //
  1202. //  Arguments:
  1203. //      HWND hwnd: Handle to main window that has just been created but
  1204. //      not shown.
  1205. //
  1206. //      int nCmdShow: The state that the application window should show as.
  1207. //
  1208. //  Return (BOOL):
  1209. //      The return value is always TRUE.
  1210. //  
  1211. //  History:
  1212. //      05/11/93
  1213. //  
  1214. //--------------------------------------------------------------------------;
  1215.  
  1216. BOOL FNLOCAL MMCapsSettingsRestore
  1217. (
  1218.     HWND            hwnd,
  1219.     int             nCmdShow
  1220. )
  1221. {
  1222.     WINDOWPLACEMENT wp;
  1223.     PRECT           prc;
  1224.     HFONT           hfont;
  1225.     LOGFONT         lf;
  1226.     RECT            rc;
  1227.     POINT           pt;
  1228.     int             n;
  1229.     BOOL            f;
  1230.  
  1231.  
  1232.  
  1233.     //
  1234.     //  restore the user's preferred font.
  1235.     //
  1236.     hfont = NULL;
  1237.     f = AppProfileReadBytes(gszKeyFont, (LPBYTE)&lf, sizeof(lf));
  1238.     if (f)
  1239.     {
  1240.     hfont = CreateFontIndirect(&lf);
  1241.     }
  1242.  
  1243.     if (NULL == hfont)
  1244.     {
  1245.     hfont = GetStockFont(ANSI_VAR_FONT);
  1246.     }
  1247.  
  1248.     TlbSetFont(gptlbDrivers, hfont, TRUE);
  1249.  
  1250.  
  1251.     //
  1252.     //  grab the stored window position and size from the .ini file...
  1253.     //  there must be four arguments stored or the entry is considered
  1254.     //  invalid.
  1255.     //
  1256.     prc = &wp.rcNormalPosition;
  1257.     f = AppProfileReadBytes(gszKeyWindow, (LPBYTE)prc, sizeof(*prc));
  1258.     if (f)
  1259.     {
  1260.     //
  1261.     //  to make sure the user can always get at the window, check to
  1262.     //  see if the midpoint of the caption is visible--if it is not,
  1263.     //  then default to the default position used when creating the
  1264.     //  window.
  1265.     //
  1266.     n = (prc->right - prc->left) / 2;
  1267.     pt.x = (n + prc->left);
  1268.  
  1269.     n = GetSystemMetrics(SM_CYCAPTION) / 2 + GetSystemMetrics(SM_CXFRAME);
  1270.     pt.y = (n + prc->top);
  1271.  
  1272.     GetWindowRect(GetDesktopWindow(), &rc);
  1273.     if (PtInRect(&rc, pt))
  1274.     {
  1275.         //
  1276.         //  fill out the window placement structure--default the
  1277.         //  maximized and minimized states to default placement by
  1278.         //  getting its current placement.
  1279.         //
  1280.         wp.length = sizeof(wp);
  1281.         GetWindowPlacement(hwnd, &wp);
  1282.  
  1283.         wp.flags           = 0;
  1284.         wp.showCmd         = nCmdShow;
  1285.  
  1286.         SetWindowPlacement(hwnd, &wp);
  1287.         return (TRUE);
  1288.     }
  1289.     }
  1290.  
  1291.     //
  1292.     //  show defaulted and succeed
  1293.     //
  1294.     ShowWindow(hwnd, nCmdShow);
  1295.     return (TRUE);
  1296. } // MMCapsSettingsRestore()
  1297.  
  1298.  
  1299. //--------------------------------------------------------------------------;
  1300. //  
  1301. //  BOOL MMCapsSettingsSave
  1302. //  
  1303. //  Description:
  1304. //      This function saves the current state information for the application.
  1305. //      It is called just before the main window is closed (destroyed); or
  1306. //      as Windows is exiting (query end session).
  1307. //
  1308. //      Note that this function should not destroy any resources--it can
  1309. //      be called at any time to save a snapshot of the application state.
  1310. //
  1311. //  Arguments:
  1312. //      HWND hwnd: Handle to main window that will be destroyed shortly.
  1313. //
  1314. //  Return (BOOL):
  1315. //      The return value is always TRUE.
  1316. //  
  1317. //  History:
  1318. //      05/11/93
  1319. //  
  1320. //--------------------------------------------------------------------------;
  1321.  
  1322. BOOL FNLOCAL MMCapsSettingsSave
  1323. (
  1324.     HWND            hwnd
  1325. )
  1326. {
  1327.     WINDOWPLACEMENT wp;
  1328.     PRECT           prc;
  1329.     BOOL            f;
  1330.  
  1331.     //
  1332.     //  save the current window placement--only store the size and location
  1333.     //  of the restored window. maximized and minimized states should
  1334.     //  remain defaulted on the next invocation of this application.
  1335.     //
  1336.     wp.length = sizeof(wp);
  1337.     f = GetWindowPlacement(hwnd, &wp);
  1338.     if (f)
  1339.     {
  1340.     prc = &wp.rcNormalPosition;
  1341.  
  1342.     DPF(0, "WindowPlacement: show=%d, minX=%d, minY=%d, maxX=%d, maxY=%d",
  1343.          wp.showCmd, wp.ptMinPosition.x, wp.ptMinPosition.y,
  1344.          wp.ptMaxPosition.x, wp.ptMaxPosition.y);
  1345.  
  1346.     DPF(0, "                 normX=%d, normY=%d, normW=%d, normH=%d",
  1347.          prc->left, prc->top, prc->right, prc->bottom);
  1348.  
  1349.     //
  1350.     //  save the _bounding rectangle_ of the restored window state...
  1351.     //
  1352.     AppProfileWriteBytes(gszKeyWindow, (LPBYTE)prc, sizeof(*prc));
  1353.     }
  1354.  
  1355.  
  1356.     //
  1357.     //  succeed
  1358.     //
  1359.     return (TRUE);
  1360. } // MMCapsSettingsSave()
  1361.  
  1362.  
  1363. //==========================================================================;
  1364. //
  1365. //
  1366. //
  1367. //
  1368. //==========================================================================;
  1369.  
  1370. //--------------------------------------------------------------------------;
  1371. //
  1372. //  BOOL MMCapsDlgProc
  1373. //
  1374. //  Description:
  1375. //      This dialog procedure is used to display driver capabilities.
  1376. //
  1377. //  Arguments:
  1378. //      HWND hwnd: Handle to window.
  1379. //
  1380. //      UINT uMsg: Message being sent to the window.
  1381. //
  1382. //      WPARAM wParam: Specific argument to message.
  1383. //
  1384. //      LPARAM lParam: Specific argument to message.
  1385. //
  1386. //  Return (BOOL):
  1387. //      The return value is specific to the message that was received. For
  1388. //      the most part, it is FALSE if this dialog procedure does not handle
  1389. //      a message.
  1390. //
  1391. //  History:
  1392. //       1/ 2/93
  1393. //
  1394. //--------------------------------------------------------------------------;
  1395.  
  1396. BOOL FNEXPORT MMCapsDlgProc
  1397. (
  1398.     HWND            hwnd,
  1399.     UINT            uMsg,
  1400.     WPARAM          wParam,
  1401.     LPARAM          lParam
  1402. )
  1403. {
  1404.     HWND        hedit;
  1405.     UINT        u;
  1406.  
  1407.     switch (uMsg)
  1408.     {
  1409.     case WM_INITDIALOG:
  1410.         hedit = GetDlgItem(hwnd, IDD_DEVCAPS_EDIT_DETAILS);
  1411.         SetWindowFont(hedit, GetStockFont(ANSI_FIXED_FONT), FALSE);
  1412.  
  1413.         //
  1414.         //
  1415.         //
  1416.         switch (guDriverType)
  1417.         {
  1418.         case MMCAPS_DRIVERTYPE_LOWLEVEL:
  1419.             MMCapsDetailLowLevel(hedit, lParam);
  1420.             break;
  1421.  
  1422. #if 0
  1423.         case MMCAPS_DRIVERTYPE_MCI:
  1424.             MMCapsDetailMCI(hedit, lParam);
  1425.             break;
  1426.  
  1427.         case MMCAPS_DRIVERTYPE_ACM:
  1428.             MMCapsDetailACM(hedit, lParam);
  1429.             break;
  1430.  
  1431.         case MMCAPS_DRIVERTYPE_VIDEO:
  1432.             MMCapsDetailVideo(hedit, lParam);
  1433.             break;
  1434. #endif
  1435.         }
  1436.  
  1437.         //
  1438.         //  return nonzero to set the input focus to the control
  1439.         //  identified by the (hwndFocus = (HWND)wParam) argument.
  1440.         //  a zero return tells the dialog manager that this function
  1441.         //  has set the focus using SetFocus.
  1442.         //
  1443.         return (TRUE);
  1444.  
  1445.     case WM_COMMAND:
  1446.         u = GET_WM_COMMAND_ID(wParam, lParam);
  1447.         if ((IDOK == u) || (IDCANCEL == u))
  1448.         {
  1449.         EndDialog(hwnd, (IDOK == u));
  1450.         }
  1451.         break;
  1452.     }
  1453.  
  1454.     return (FALSE);
  1455. } // MMCapsDlgProc()
  1456.  
  1457.  
  1458. //==========================================================================;
  1459. //
  1460. //
  1461. //
  1462. //
  1463. //==========================================================================;
  1464.  
  1465. //--------------------------------------------------------------------------;
  1466. //  
  1467. //  BOOL MMCapsRefreshDriverList
  1468. //  
  1469. //  Description:
  1470. //  
  1471. //  
  1472. //  Arguments:
  1473. //      HWND hwnd: Handle of main window.
  1474. //  
  1475. //  Return (BOOL):
  1476. //  
  1477. //  History:
  1478. //      05/16/93
  1479. //  
  1480. //--------------------------------------------------------------------------;
  1481.  
  1482. BOOL FNLOCAL MMCapsRefreshDriverList
  1483. (
  1484.     PZYZTABBEDLISTBOX   ptlb
  1485. )
  1486. {
  1487.     static UINT     uIdPrev = (UINT)-1;
  1488.  
  1489.     BOOL        fComplete;
  1490.  
  1491.     //
  1492.     //
  1493.     //
  1494.     SetWindowRedraw(ptlb->hlb, FALSE);
  1495.     ListBox_ResetContent(ptlb->hlb);
  1496.  
  1497.  
  1498.     //
  1499.     //  only force complete update if the driver type is different from
  1500.     //  previous...
  1501.     //
  1502.     fComplete = (guDriverType != uIdPrev);
  1503.     uIdPrev = guDriverType;
  1504.  
  1505.     //
  1506.     //
  1507.     //
  1508.     switch (guDriverType)
  1509.     {
  1510.     case MMCAPS_DRIVERTYPE_LOWLEVEL:
  1511.         MMCapsEnumerateLowLevel(ptlb, fComplete);
  1512.         break;
  1513.  
  1514.  
  1515. #if 0
  1516.     case MMCAPS_DRIVERTYPE_MCI:
  1517.         MMCapsEnumerateMCI(ptlb, fComplete);
  1518.         break;
  1519.  
  1520.     case MMCAPS_DRIVERTYPE_ACM:
  1521.         MMCapsEnumerateACM(ptlb, fComplete);
  1522.         break;
  1523.  
  1524.     case MMCAPS_DRIVERTYPE_VIDEO:
  1525.         MMCapsEnumerateVideo(ptlb, fComplete);
  1526.         break;
  1527.  
  1528.     case MMCAPS_DRIVERTYPE_DRIVERS:
  1529.         MMCapsEnumerateDrivers(ptlb, fComplete);
  1530.         break;
  1531. #endif
  1532.  
  1533.     }
  1534.  
  1535.     //
  1536.     //
  1537.     //
  1538.     SetWindowRedraw(ptlb->hlb, TRUE);
  1539.  
  1540.     return (TRUE);
  1541. } // MMCapsRefreshDriverList()
  1542.  
  1543.  
  1544. //==========================================================================;
  1545. //
  1546. //  Main application window handling code...
  1547. //
  1548. //
  1549. //==========================================================================;
  1550.  
  1551. //--------------------------------------------------------------------------;
  1552. //
  1553. //  LRESULT AppCreate
  1554. //
  1555. //  Description:
  1556. //      This function is called to handle the WM_CREATE message for the
  1557. //      application's window. The application should finish the creation
  1558. //      of the window (create controls, allocate resources, etc). The
  1559. //      window has not been displayed (CreateWindow[Ex] has not returned).
  1560. //
  1561. //  Arguments:
  1562. //      HWND hwnd: Handle to the window that is in the process of being
  1563. //      created.
  1564. //
  1565. //      LPCREATESTRUCT pcs: Pointer to a CREATESTRUCT that contains info
  1566. //      about the window being created.
  1567. //
  1568. //  Return (LRESULT):
  1569. //      The return value should be nonzero if the application wishes to
  1570. //      let the window finish being created. A return of zero tells
  1571. //      CreateWindow[Ex] to fail the creation of the window.
  1572. //
  1573. //  History:
  1574. //      11/ 8/92
  1575. //
  1576. //--------------------------------------------------------------------------;
  1577.  
  1578. LRESULT FNGLOBAL AppCreate
  1579. (
  1580.     HWND            hwnd,
  1581.     LPCREATESTRUCT  pcs
  1582. )
  1583. {
  1584.     DPF(0, "AppCreate(hwnd=%Xh, cs.x=%d, cs.y=%d, cs.cx=%d, cs.cy=%d)",
  1585.         hwnd, pcs->x, pcs->y, pcs->cx, pcs->cy);
  1586.  
  1587.     //
  1588.     //  create the driver selection listbox
  1589.     //
  1590.     gptlbDrivers = TlbCreate(hwnd, IDD_APP_LIST_DEVICES, NULL);
  1591.     if (NULL == gptlbDrivers)
  1592.     return (0L);
  1593.  
  1594.     //
  1595.     //
  1596.     //
  1597.     MMCapsRefreshDriverList(gptlbDrivers);
  1598.  
  1599.  
  1600.     //
  1601.     //  we want the focus to default to the device listbox window
  1602.     //
  1603.     SetFocus(gptlbDrivers->hlb);
  1604.  
  1605.  
  1606.     //
  1607.     //  return nonzero to succeed the creation of the window
  1608.     //
  1609.     return (1L);
  1610. } // AppCreate()
  1611.  
  1612.  
  1613. //--------------------------------------------------------------------------;
  1614. //
  1615. //  LRESULT AppQueryEndSession
  1616. //
  1617. //  Description:
  1618. //      This function handles the WM_QUERYENDSESSION. This message is sent
  1619. //      by USER when ExitWindows has been called to end the Windows session.
  1620. //      This function can stop Windows from exiting if it is not convenient
  1621. //      for Windows to end.
  1622. //
  1623. //      Giving the user the option to save modified data before continueing
  1624. //      with the shutdown of Windows is a good idea.
  1625. //
  1626. //      Telling Windows to continue with the exit procedure does not
  1627. //      necessarily mean Windows will exit. All applications are queried
  1628. //      for shutdown approval. When the actual decision is made on whether
  1629. //      Windows will exit, WM_ENDSESSION will be sent with the result.
  1630. //
  1631. //  Arguments:
  1632. //      HWND hwnd: Handle to window that received the message.
  1633. //
  1634. //  Return (LRESULT):
  1635. //      Returns zero to STOP Windows from exiting. Returns non-zero to
  1636. //      allows windows to shut down.
  1637. //
  1638. //  History:
  1639. //       2/ 9/93
  1640. //
  1641. //--------------------------------------------------------------------------;
  1642.  
  1643. LRESULT FNGLOBAL AppQueryEndSession
  1644. (
  1645.     HWND            hwnd
  1646. )
  1647. {
  1648.     DPF(0, "AppQueryEndSession(hwnd=%Xh)", hwnd);
  1649.  
  1650.     //
  1651.     //  tell Windows to proceed with the shutdown process!
  1652.     //
  1653.     return (1L);
  1654. } // AppQueryEndSession()
  1655.  
  1656.  
  1657. //--------------------------------------------------------------------------;
  1658. //
  1659. //  LRESULT AppEndSession
  1660. //
  1661. //  Description:
  1662. //      This function is called to handle the WM_ENDSESSION message. This
  1663. //      message is generated after the application answers the
  1664. //      WM_QUERYENDSESSION message. The purpose of the WM_ENDSESSION
  1665. //      message is to tell the application if Windows will be exiting
  1666. //      (TRUE  == fEndSession) or the end session was canceled by an
  1667. //      application (FALSE == fEndSession).
  1668. //
  1669. //  Arguments:
  1670. //      HWND hwnd: Handle to window that received the message.
  1671. //
  1672. //      BOOL fEndSession: TRUE if Windows is exiting. FALSE if the end
  1673. //      session was canceled.
  1674. //
  1675. //  Return (LRESULT):
  1676. //      Returns zero if the message is processed. Note that an application
  1677. //      cannot halt the termination of Windows from this message--the
  1678. //      WM_QUERYENDSESSION is the only message that allows that behaviour.
  1679. //      If fEndSession is TRUE, Windows *WILL* exit--whether you like it
  1680. //      or not.
  1681. //
  1682. //  History:
  1683. //       2/ 9/93
  1684. //
  1685. //--------------------------------------------------------------------------;
  1686.  
  1687. LRESULT FNGLOBAL AppEndSession
  1688. (
  1689.     HWND            hwnd,
  1690.     BOOL            fEndSession
  1691. )
  1692. {
  1693.     DPF(0, "AppEndSession(hwnd=%Xh, fEndSession=%d)", hwnd, fEndSession);
  1694.  
  1695.     //
  1696.     //  we processed the message, return zero..
  1697.     //
  1698.     return (0L);
  1699. } // AppEndSession()
  1700.  
  1701.  
  1702. //--------------------------------------------------------------------------;
  1703. //
  1704. //  LRESULT AppClose
  1705. //
  1706. //  Description:
  1707. //      This function handles the WM_CLOSE message for the application.
  1708. //      If the application should close, DestroyWindow() must be called
  1709. //      by this function. Otherwise the application will not close.
  1710. //
  1711. //  Arguments:
  1712. //      HWND hwnd: Handle to window that generated the WM_CLOSE message.
  1713. //
  1714. //  Return (LRESULT):
  1715. //      There return value is zero. The DestroyWindow function will have
  1716. //      been called if the application should actually close.
  1717. //
  1718. //  History:
  1719. //       2/ 6/93
  1720. //
  1721. //--------------------------------------------------------------------------;
  1722.  
  1723. LRESULT FNGLOBAL AppClose
  1724. (
  1725.     HWND            hwnd
  1726. )
  1727. {
  1728.     HWND        hlb;
  1729.     HFONT       hfont;
  1730.  
  1731.  
  1732.     DPF(0, "AppClose(hwnd=%Xh)", hwnd);
  1733.  
  1734.     //
  1735.     //  save any settings that should be saved on app termination...
  1736.     //
  1737.     MMCapsSettingsSave(hwnd);
  1738.  
  1739.  
  1740.     //
  1741.     //  if the Shift key is held down during the close message, then just
  1742.     //  save the current state but don't destroy the window... this is
  1743.     //  useful if the user does not want to exit the app and rerun it
  1744.     //  to make sure the state is saved--just before the user does something
  1745.     //  that may crash Windows or something..
  1746.     //
  1747.     if (GetKeyState(VK_SHIFT) < 0)
  1748.     {
  1749.     return (0L);
  1750.     }
  1751.  
  1752.  
  1753.     //
  1754.     //  destroy the font we are using... before deleting the font, select
  1755.     //  the system font back into the script window so the font won't
  1756.     //  be 'in use' anymore.
  1757.     //
  1758.     hlb = GetDlgItem(hwnd, IDD_APP_LIST_DEVICES);
  1759.  
  1760.     hfont = GetWindowFont(hlb);
  1761.     SetWindowFont(hlb, NULL, FALSE);
  1762.     DeleteFont(hfont);
  1763.  
  1764.     //
  1765.     //  make the window close and terminate the application
  1766.     //
  1767.     DestroyWindow(hwnd);
  1768.  
  1769.     return (0L);
  1770. } // AppClose()
  1771.  
  1772.  
  1773. //--------------------------------------------------------------------------;
  1774. //
  1775. //  LRESULT AppInitMenuPopup
  1776. //
  1777. //  Description:
  1778. //      This function handles the WM_INITMENUPOPUP message. This message
  1779. //      is sent to the window owning the menu that is going to become
  1780. //      active. This gives an application the ability to modify the menu
  1781. //      before it is displayed (disable/add items, etc).
  1782. //
  1783. //  Arguments:
  1784. //      HWND hwnd: Handle to window that generated the WM_INITMENUPOPUP
  1785. //      message.
  1786. //
  1787. //      HMENU hmenu: Handle to the menu that is to become active.
  1788. //
  1789. //      int nItem: Specifies the zero-based relative position of the menu
  1790. //      item that invoked the popup menu.
  1791. //
  1792. //      BOOL fSysMenu: Specifies whether the popup menu is a System menu
  1793. //      (TRUE) or it is not a System menu (FALSE).
  1794. //
  1795. //  Return (LRESULT):
  1796. //      Returns zero if the message is processed.
  1797. //
  1798. //  History:
  1799. //       1/ 2/93
  1800. //
  1801. //--------------------------------------------------------------------------;
  1802.  
  1803. LRESULT FNLOCAL AppInitMenuPopup
  1804. (
  1805.     HWND            hwnd,
  1806.     HMENU           hmenu,
  1807.     int             nItem,
  1808.     BOOL            fSysMenu
  1809. )
  1810. {
  1811.     UINT        u;
  1812.  
  1813.     DPF(0, "AppInitMenuPopup(hwnd=%Xh, hmenu=%Xh, nItem=%d, fSysMenu=%d)",
  1814.         hwnd, hmenu, nItem, fSysMenu);
  1815.  
  1816.     //
  1817.     //  if the system menu is what got hit, succeed immediately... this
  1818.     //  application has no stuff in the system menu.
  1819.     //
  1820.     if (fSysMenu)
  1821.     return (0L);
  1822.  
  1823.     //
  1824.     //  initialize the menu that is being 'popped up'
  1825.     //
  1826.     switch (nItem)
  1827.     {
  1828.     case APP_MENU_ITEM_FILE:
  1829.         break;
  1830.  
  1831.     case APP_MENU_ITEM_DRIVERS:
  1832.         for (u = IDM_DRIVERS_LOWLEVEL; u <= IDM_DRIVERS_DRIVERS; u++)
  1833.         {
  1834.         UINT    uCheck;
  1835.  
  1836.         uCheck = (u == guDriverType) ? MF_CHECKED : MF_UNCHECKED;
  1837.         CheckMenuItem(hmenu, u, uCheck);
  1838.         }
  1839.         break;
  1840.     }
  1841.  
  1842.     //
  1843.     //  we processed the message--return 0...
  1844.     //
  1845.     return (0L);
  1846. } // AppInitMenuPopup()
  1847.  
  1848.  
  1849. //--------------------------------------------------------------------------;
  1850. //
  1851. //  LRESULT AppCommand
  1852. //
  1853. //  Description:
  1854. //      This function handles the WM_COMMAND message.
  1855. //
  1856. //  Arguments:
  1857. //      HWND hwnd: Handle to window receiving the WM_COMMAND message.
  1858. //
  1859. //      int nId: Control or menu item identifier.
  1860. //
  1861. //      HWND hwndCtl: Handle of control if the message is from a control.
  1862. //      This argument is NULL if the message was not generated by a control.
  1863. //
  1864. //      UINT uCode: Notification code. This argument is 1 if the message
  1865. //      was generated by an accelerator. If the message is from a menu,
  1866. //      this argument is 0.
  1867. //
  1868. //  Return (LRESULT):
  1869. //      Returns zero if the message is processed.
  1870. //
  1871. //  History:
  1872. //      11/ 8/92
  1873. //
  1874. //--------------------------------------------------------------------------;
  1875.  
  1876. LRESULT FNLOCAL AppCommand
  1877. (
  1878.     HWND            hwnd,
  1879.     int             nId,
  1880.     HWND            hwndCtl,
  1881.     UINT            uCode
  1882. )
  1883. {
  1884.     int         n;
  1885.     LRESULT     lr;
  1886.  
  1887.     switch (nId)
  1888.     {
  1889.     case IDM_FILE_FONT:
  1890.         MMCapsChooseFont(hwnd);
  1891.         break;
  1892.  
  1893.     case IDM_FILE_ABOUT:
  1894.         AppDialogBox(hwnd, DLG_ABOUT, (DLGPROC)AboutDlgProc, 0L);
  1895.         break;
  1896.  
  1897.     case IDM_FILE_EXIT:
  1898.         FORWARD_WM_CLOSE(hwnd, SendMessage);
  1899.         break;
  1900.  
  1901.  
  1902.     case IDM_DRIVERS_LOWLEVEL:
  1903.     case IDM_DRIVERS_MCI:
  1904.     case IDM_DRIVERS_ACM:
  1905.     case IDM_DRIVERS_VIDEO:
  1906.     case IDM_DRIVERS_DRIVERS:
  1907.         if ((UINT)nId == guDriverType)
  1908.         break;
  1909.  
  1910.         guDriverType = (UINT)nId;
  1911.  
  1912.         // -- fall through -- //
  1913.  
  1914.     case IDM_UPDATE:
  1915.         MMCapsRefreshDriverList(gptlbDrivers);
  1916.         break;
  1917.  
  1918.  
  1919.     case IDD_APP_LIST_DEVICES:
  1920.         switch (uCode)
  1921.         {
  1922.         case LBN_SELCHANGE:
  1923.             break;
  1924.  
  1925.         case LBN_DBLCLK:
  1926.             n  = ListBox_GetCurSel(hwndCtl);
  1927.             lr = ListBox_GetItemData(hwndCtl, n);
  1928.             AppDialogBox(hwnd, DLG_DEVCAPS, (DLGPROC)MMCapsDlgProc, lr);
  1929.             break;
  1930.         }
  1931.         break;
  1932.     }
  1933.  
  1934.     return (0L);
  1935. } // AppCommand()
  1936.  
  1937.  
  1938. //--------------------------------------------------------------------------;
  1939. //
  1940. //  LRESULT AppSize
  1941. //
  1942. //  Description:
  1943. //      This function handles the WM_SIZE message for the application's
  1944. //      window. This message is sent to the application window after the
  1945. //      size has changed (but before it is painted).
  1946. //
  1947. //  Arguments:
  1948. //      HWND hwnd: Handle to window that generated the WM_SIZE message.
  1949. //
  1950. //      UINT fuSizeType: Specifies the type of resizing requested. This
  1951. //      argument is one of the following: SIZE_MAXIMIZED, SIZE_MINIMIZED,
  1952. //      SIZE_RESTORED, SIZE_MAXHIDE, or SIZE_MAXSHOW.
  1953. //
  1954. //      int nWidth: Width of the new client area for the window.
  1955. //
  1956. //      int nHeight: Height of the new client area for the window.
  1957. //
  1958. //  Return (LRESULT):
  1959. //      Returns zero if the application processes the message.
  1960. //
  1961. //  History:
  1962. //       2/ 5/93
  1963. //
  1964. //--------------------------------------------------------------------------;
  1965.  
  1966. LRESULT FNLOCAL AppSize
  1967. (
  1968.     HWND            hwnd,
  1969.     UINT            fuSizeType,
  1970.     int             nWidth,
  1971.     int             nHeight
  1972. )
  1973. {
  1974.     RECT        rc;
  1975.  
  1976.     DPF(0, "AppSize(hwnd=%Xh, fuSizeType=%u, nWidth=%d, nHeight=%d)",
  1977.         hwnd, fuSizeType, nWidth, nHeight);
  1978.  
  1979.     //
  1980.     //  unless this application is the one being resized then don't waste
  1981.     //  time computing stuff that doesn't matter. this applies to being
  1982.     //  minimized also because this application does not have a custom
  1983.     //  minimized state.
  1984.     //
  1985.     if ((SIZE_RESTORED != fuSizeType) && (SIZE_MAXIMIZED != fuSizeType))
  1986.     return (0L);
  1987.  
  1988.  
  1989.     //
  1990.     //  size the devices listbox to be the total size of the client area--
  1991.     //  inflate the rect by one so borders are not visible. note that 
  1992.     //  we need to leave room at the top for the title text which is one
  1993.     //  line of text in height...
  1994.     //
  1995.     GetClientRect(hwnd, &rc);
  1996.     InflateRect(&rc, 1, 1);
  1997.  
  1998.  
  1999.     TlbMove(gptlbDrivers, &rc, FALSE);
  2000.  
  2001.  
  2002.     //
  2003.     //  we processed the message..
  2004.     //
  2005.     return (0L);
  2006. } // AppSize()
  2007.  
  2008.  
  2009. //--------------------------------------------------------------------------;
  2010. //  
  2011. //  LRESULT AppPaint
  2012. //  
  2013. //  Description:
  2014. //  
  2015. //  
  2016. //  Arguments:
  2017. //      HWND hwnd:
  2018. //  
  2019. //  Return (LRESULT):
  2020. //  
  2021. //  History:
  2022. //      05/11/93
  2023. //  
  2024. //--------------------------------------------------------------------------;
  2025.  
  2026. LRESULT FNLOCAL AppPaint
  2027. (
  2028.     HWND            hwnd
  2029. )
  2030. {
  2031.     PAINTSTRUCT ps;
  2032.  
  2033.     //
  2034.     //
  2035.     //
  2036.     BeginPaint(hwnd, &ps);
  2037.  
  2038.     TlbPaint(gptlbDrivers, hwnd, ps.hdc);
  2039.  
  2040.     EndPaint(hwnd, &ps);
  2041.  
  2042.     //
  2043.     //  we processed the message
  2044.     //
  2045.     return (0L);
  2046. } // AppPaint()
  2047.  
  2048.  
  2049. //--------------------------------------------------------------------------;
  2050. //
  2051. //  LRESULT AppWndProc
  2052. //
  2053. //  Description:
  2054. //      This is the main application window procedure.
  2055. //
  2056. //  Arguments:
  2057. //      HWND hwnd: Handle to window.
  2058. //
  2059. //      UINT uMsg: Message being sent to the window.
  2060. //
  2061. //      WPARAM wParam: Specific argument to message.
  2062. //
  2063. //      LPARAM lParam: Specific argument to message.
  2064. //
  2065. //  Return (LRESULT):
  2066. //      The return value depends on the message that is being processed.
  2067. //
  2068. //  History:
  2069. //      11/ 8/92
  2070. //
  2071. //--------------------------------------------------------------------------;
  2072.  
  2073. LRESULT FNEXPORT AppWndProc
  2074. (
  2075.     HWND            hwnd,
  2076.     UINT            uMsg,
  2077.     WPARAM          wParam,
  2078.     LPARAM          lParam
  2079. )
  2080. {
  2081.     LRESULT     lr;
  2082.  
  2083.     switch (uMsg)
  2084.     {
  2085.     case WM_CREATE:
  2086.         lr = HANDLE_WM_CREATE(hwnd, wParam, lParam, AppCreate);
  2087.         return (lr);
  2088.  
  2089.     case WM_INITMENUPOPUP:
  2090.         HANDLE_WM_INITMENUPOPUP(hwnd, wParam, lParam, AppInitMenuPopup);
  2091.         return (0L);
  2092.  
  2093.     case WM_COMMAND:
  2094.         lr = HANDLE_WM_COMMAND(hwnd, wParam, lParam, AppCommand);
  2095.         return (lr);
  2096.  
  2097.     case WM_SIZE:
  2098.         //
  2099.         //  handle what we want for sizing, and then always call the
  2100.         //  default handler...
  2101.         //
  2102.         HANDLE_WM_SIZE(hwnd, wParam, lParam, AppSize);
  2103.         break;
  2104.  
  2105.     case WM_PAINT:
  2106.         HANDLE_WM_PAINT(hwnd, wParam, lParam, AppPaint);
  2107.         break;
  2108.  
  2109.     case WM_QUERYENDSESSION:
  2110.         lr = HANDLE_WM_QUERYENDSESSION(hwnd, wParam, lParam, AppQueryEndSession);
  2111.         return (lr);
  2112.  
  2113.     case WM_ENDSESSION:
  2114.         HANDLE_WM_ENDSESSION(hwnd, wParam, lParam, AppEndSession);
  2115.         return (0L);
  2116.  
  2117.     case WM_CLOSE:
  2118.         HANDLE_WM_CLOSE(hwnd, wParam, lParam, AppClose);
  2119.         return (0L);
  2120.  
  2121.     case WM_DESTROY:
  2122.         PostQuitMessage(0);
  2123.         return (0L);
  2124.     }
  2125.  
  2126.     return (DefWindowProc(hwnd, uMsg, wParam, lParam));
  2127. } // AppWndProc()
  2128.  
  2129.  
  2130. //==========================================================================;
  2131. //
  2132. //
  2133. //
  2134. //
  2135. //==========================================================================;
  2136.  
  2137. //--------------------------------------------------------------------------;
  2138. //
  2139. //  BOOL AppInit
  2140. //
  2141. //  Description:
  2142. //      This function is called to initialize a new instance of the
  2143. //      application. We want to parse our command line, create our window,
  2144. //      allocate resources, etc.
  2145. //
  2146. //      The arguments passed to this function are exactly the same as
  2147. //      those passed to WinMain.
  2148. //
  2149. //  Arguments:
  2150. //      HINSTANCE hinst: Identifies the current instance of the
  2151. //      application.
  2152. //
  2153. //      HINSTANCE hinstPrev: Identifies the previous instance of the
  2154. //      application (NULL if first instance). For Win 32, this argument
  2155. //      is _always_ NULL.
  2156. //
  2157. //      LPTSTR pszCmdLine: Points to null-terminated unparsed command line.
  2158. //      If the application is compiled for Unicode, then this argument is
  2159. //      ignored.
  2160. //
  2161. //      int nCmdShow: How the main window for the application is to be
  2162. //      shown by default.
  2163. //
  2164. //  Return (HWND):
  2165. //      Returns the newly created handle to the applications main window.
  2166. //      This handle is NULL if something went wrong and tells the application
  2167. //      to exit immediately.
  2168. //
  2169. //  History:
  2170. //      11/ 8/92
  2171. //
  2172. //--------------------------------------------------------------------------;
  2173.  
  2174. HWND FNGLOBAL AppInit
  2175. (
  2176.     HINSTANCE       hinst,
  2177.     HINSTANCE       hinstPrev,
  2178.     LPTSTR          pszCmdLine,
  2179.     int             nCmdShow
  2180. )
  2181. {
  2182.     LRESULT FNEXPORT AppWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  2183.  
  2184.     HWND        hwnd;
  2185.     WNDCLASS    wc;
  2186.  
  2187.     DPF(0, "AppInit(hinst=%Xh, hinstPrev=%Xh, pszCmdLine='%s', nCmdShow=%d)",
  2188.         hinst, hinstPrev, pszCmdLine, nCmdShow);
  2189.  
  2190.     LoadString(hinst, IDS_APP_NAME, gszAppName, SIZEOF(gszAppName));
  2191.  
  2192.  
  2193.     //
  2194.     //  determine whether a new window class needs to be registered for
  2195.     //  this application. for Win 16, this only needs to be done for the
  2196.     //  first instance of the application created. for Win 32, this must
  2197.     //  be done for EVERY instance of the application.
  2198.     //
  2199.     if (NULL == hinstPrev)
  2200.     {
  2201.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  2202.     wc.lpfnWndProc   = (WNDPROC)AppWndProc;
  2203.     wc.cbClsExtra    = 0;
  2204.     wc.cbWndExtra    = 0;
  2205.     wc.hInstance     = hinst;
  2206.     wc.hIcon         = LoadIcon(hinst, ICON_APP);
  2207.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  2208.     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  2209.     wc.lpszMenuName  = MENU_APP;
  2210.     wc.lpszClassName = gszAppName;
  2211.  
  2212.     if (!RegisterClass(&wc))
  2213.         return (NULL);
  2214.     }
  2215.  
  2216.  
  2217.     //
  2218.     //  create the application's main window
  2219.     //
  2220.     //  style bits available:
  2221.     //      WS_EX_ACCEPTFILES   :  will receive WM_DROPFILES messages
  2222.     //      WS_EX_DLGMODALFRAME :  creates window with double border
  2223.     //      WS_EX_NOPARENTNOTIFY:  won't receive WM_PARENTNOTIFY messages
  2224.     //      WS_EX_TOPMOST       :  puts window in topmost space
  2225.     //      WS_EX_TRANSPARENT   :  a very bizarre style indeed (Win 16 only)
  2226.     //
  2227.     hwnd = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
  2228.               gszAppName,
  2229.               gszAppName,
  2230.               WS_OVERLAPPEDWINDOW,
  2231.               APP_WINDOW_XOFFSET,
  2232.               APP_WINDOW_YOFFSET,
  2233.               APP_WINDOW_WIDTH,
  2234.               APP_WINDOW_HEIGHT,
  2235.               NULL,
  2236.               NULL,
  2237.               hinst,
  2238.               NULL);
  2239.  
  2240.     if (NULL == hwnd)
  2241.     return (NULL);
  2242.  
  2243. #ifdef UNICODE
  2244.     //
  2245.     //  the application--which is different than the pszCmdLine argument
  2246.     //  passed through WinMain()...
  2247.     //
  2248.     //  so, skip over the command name to get to the argument string
  2249.     //
  2250.     pszCmdLine = GetCommandLine();
  2251.     if (NULL != pszCmdLine)
  2252.     {
  2253.     while (('\0' != *pszCmdLine) && (' ' != *pszCmdLine++))
  2254.         ;
  2255.     }
  2256. #endif
  2257.  
  2258.  
  2259.     //
  2260.     //
  2261.     //
  2262.     //
  2263.     MMCapsSettingsRestore(hwnd, nCmdShow);
  2264.  
  2265.  
  2266.     //
  2267.     //  finally, get the window displayed and return success
  2268.     //
  2269.     //  the ShowWindow call is made during MMCapsInit
  2270.     //
  2271. //  ShowWindow(hwnd, nCmdShow);
  2272. //  UpdateWindow(hwnd);
  2273.  
  2274.     return (hwnd);
  2275. } // AppInit()
  2276.  
  2277.  
  2278. //--------------------------------------------------------------------------;
  2279. //
  2280. //  int AppExit
  2281. //
  2282. //  Description:
  2283. //      This function is called just before the application exits from
  2284. //      WinMain. Its purpose is to clean up any resources that were allocated
  2285. //      for running the application: brushes, heaps, etc..
  2286. //
  2287. //  Arguments:
  2288. //      HINSTANCE hinst: Identifies the current instance of the
  2289. //      application that is exiting.
  2290. //
  2291. //      int nResult: The result of the WM_QUIT message (in wParam of the
  2292. //      MSG structure. This argument will usually be 0 (even if the message
  2293. //      loop was never entered).
  2294. //
  2295. //  Return (int):
  2296. //      The return value is usually nResult--be we give this function the
  2297. //      opportunity to modify its value.
  2298. //
  2299. //  History:
  2300. //      11/ 8/92
  2301. //
  2302. //--------------------------------------------------------------------------;
  2303.  
  2304. int FNGLOBAL AppExit
  2305. (
  2306.     HINSTANCE       hinst,
  2307.     int             nResult
  2308. )
  2309. {
  2310.     DPF(0, "AppExit(hinst=%Xh, nResult=%d)", hinst, nResult);
  2311.  
  2312.     //
  2313.     //
  2314.     //
  2315.     //
  2316.  
  2317.     return (nResult);
  2318. } // AppExit()
  2319.  
  2320.  
  2321. //==========================================================================;
  2322. //
  2323. //  Main entry and message dispatching code
  2324. //
  2325. //
  2326. //==========================================================================;
  2327.  
  2328. //--------------------------------------------------------------------------;
  2329. //
  2330. //  int WinMain
  2331. //
  2332. //  Description:
  2333. //      This function is called by the system as the initial entry point
  2334. //      for a Windows application.
  2335. //
  2336. //  Arguments:
  2337. //      HINSTANCE hinst: Identifies the current instance of the
  2338. //      application.
  2339. //
  2340. //      HINSTANCE hinstPrev: Identifies the previous instance of the
  2341. //      application (NULL if first instance). For Win 32, this argument
  2342. //      is _always_ NULL.
  2343. //
  2344. //      LPSTR pszCmdLine: Points to null-terminated unparsed command line.
  2345. //      This string is strictly ANSI regardless of whether the application
  2346. //      is built for Unicode. To get the Unicode equivalent call the
  2347. //      GetCommandLine() function (Win 32 only).
  2348. //
  2349. //      int nCmdShow: How the main window for the application is to be
  2350. //      shown by default.
  2351. //
  2352. //  Return (int):
  2353. //      Returns result from WM_QUIT message (in wParam of MSG structure) if
  2354. //      the application is able to enter its message loop. Returns 0 if
  2355. //      the application is not able to enter its message loop.
  2356. //
  2357. //  History:
  2358. //      11/ 8/92
  2359. //
  2360. //--------------------------------------------------------------------------;
  2361.  
  2362. int PASCAL WinMain
  2363. (
  2364.     HINSTANCE       hinst,
  2365.     HINSTANCE       hinstPrev,
  2366.     LPSTR           pszCmdLine,
  2367.     int             nCmdShow
  2368. )
  2369. {
  2370.     int     nResult;
  2371.     HWND    hwnd;
  2372.     MSG     msg;
  2373.     HACCEL  haccl;
  2374.  
  2375.     //
  2376.     //  our documentation states that WinMain is supposed to return 0 if
  2377.     //  we do not enter our message loop--so assume the worst...
  2378.     //
  2379.     nResult = 0;
  2380.  
  2381.     //
  2382.     //  make our instance handle global for convenience..
  2383.     //
  2384.     ghinst = hinst;
  2385.  
  2386.     //
  2387.     //  init some stuff, create window, etc.. note the explicit cast of
  2388.     //  pszCmdLine--this is to mute a warning (and an ugly ifdef) when
  2389.     //  compiling for Unicode. see AppInit() for more details.
  2390.     //
  2391.     hwnd = AppInit(hinst, hinstPrev, (LPTSTR)pszCmdLine, nCmdShow);
  2392.     if (hwnd)
  2393.     {
  2394.     haccl = LoadAccelerators(hinst, ACCEL_APP);
  2395.  
  2396.     //
  2397.     //  dispatch messages
  2398.     //
  2399.     while (GetMessage(&msg, NULL, 0, 0))
  2400.     {
  2401.         //
  2402.         //  do all the special stuff required for this application
  2403.         //  when dispatching messages..
  2404.         //
  2405.         if (!TranslateAccelerator(hwnd, haccl, &msg))
  2406.         {
  2407.         TranslateMessage(&msg);
  2408.         DispatchMessage(&msg);
  2409.         }
  2410.     }
  2411.  
  2412.     //
  2413.     //  return result of WM_QUIT message.
  2414.     //
  2415.     nResult = (int)msg.wParam;
  2416.     }
  2417.  
  2418.     //
  2419.     //  shut things down, clean up, etc.
  2420.     //
  2421.     nResult = AppExit(hinst, nResult);
  2422.  
  2423.     return (nResult);
  2424. } // WinMain()
  2425.