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 / mixapp / mixapp.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  31KB  |  1,178 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (C) 1993 - 1997  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. //  mixapp.c
  13. //
  14. //==========================================================================;
  15.  
  16. #include <windows.h>
  17. #include <windowsx.h>
  18. #include <mmsystem.h>
  19. #include <stdarg.h>
  20.  
  21. #include "mixapp.h"
  22.  
  23. #include "debug.h"
  24.  
  25.  
  26. //
  27. //  globals, no less
  28. //
  29. HINSTANCE   ghinst;
  30. UINT        gfuAppOptions;
  31.  
  32. TCHAR       gszNull[]           = TEXT("");
  33. TCHAR       gszCRLF[]           = TEXT("\r\n");
  34.  
  35. TCHAR       gszAppName[APP_MAX_APP_NAME_CHARS];
  36.  
  37.  
  38.  
  39.  
  40. //
  41. //
  42. //
  43. PTABBEDLISTBOX      gptlbLines;
  44. HMIXER              ghmx;
  45.  
  46.  
  47.  
  48. BOOL                gfDisplayingControl     = FALSE;
  49. DWORD               gdwControlID;
  50. HWND                ghdlgControl;
  51. MIXERLINE           gmxl;
  52. MIXERCONTROL        gmxctrl;
  53.  
  54.  
  55.  
  56. //==========================================================================;
  57. //
  58. //  Application helper functions
  59. //
  60. //
  61. //==========================================================================;
  62.  
  63. //--------------------------------------------------------------------------;
  64. //
  65. //  void AppHourGlass
  66. //
  67. //  Description:
  68. //      This function changes the cursor to that of the hour glass or
  69. //      back to the previous cursor.
  70. //
  71. //      This function can be called recursively.
  72. //
  73. //  Arguments:
  74. //      BOOL fHourGlass: TRUE if we need the hour glass.  FALSE if we need
  75. //      the arrow back.
  76. //
  77. //  Return (void):
  78. //      On return, the cursor will be what was requested.
  79. //
  80. //  History:
  81. //      11/ 8/92
  82. //
  83. //--------------------------------------------------------------------------;
  84.  
  85. void FNGLOBAL AppHourGlass
  86. (
  87.     BOOL                    fHourGlass
  88. )
  89. {
  90.     static HCURSOR  hcur;
  91.     static UINT     uWaiting = 0;
  92.  
  93.     if (fHourGlass)
  94.     {
  95.         if (!uWaiting)
  96.         {
  97.             hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  98.             ShowCursor(TRUE);
  99.         }
  100.  
  101.         uWaiting++;
  102.     }
  103.     else
  104.     {
  105.         --uWaiting;
  106.  
  107.         if (!uWaiting)
  108.         {
  109.             ShowCursor(FALSE);
  110.             SetCursor(hcur);
  111.         }
  112.     }
  113. } // AppHourGlass()
  114.  
  115.  
  116. //--------------------------------------------------------------------------;
  117. //
  118. //  int AppMsgBox
  119. //
  120. //  Description:
  121. //      This function displays a message for the application in a standard
  122. //      message box.
  123. //
  124. //      Note that this function takes any valid argument list that can
  125. //      be passed to wsprintf. Because of this, the application must
  126. //      remember to cast near string pointers to FAR when built for Win 16.
  127. //      You will get a nice GP fault if you do not cast them correctly.
  128. //
  129. //  Arguments:
  130. //      HWND hwnd: Handle to parent window for message box holding the
  131. //      message.
  132. //
  133. //      UINT fuStyle: Style flags for MessageBox().
  134. //
  135. //      PTSTR pszFormat: Format string used for wvsprintf().
  136. //
  137. //  Return (int):
  138. //      The return value is the result of MessageBox() function.
  139. //
  140. //  History:
  141. //       2/13/93
  142. //
  143. //--------------------------------------------------------------------------;
  144.  
  145. int FNCGLOBAL AppMsgBox
  146. (
  147.     HWND                    hwnd,
  148.     UINT                    fuStyle,
  149.     PTSTR                  pszFormat,
  150.     ...
  151. )
  152. {
  153.     va_list     va;
  154.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  155.     int         n;
  156.  
  157.     //
  158.     //  format and display the message..
  159.     //
  160.     va_start(va, pszFormat);
  161.     wvsprintf(ach, pszFormat, va);
  162.     va_end(va);
  163.  
  164.     n = MessageBox(hwnd, ach, gszAppName, fuStyle);
  165.  
  166.     return (n);
  167. } // AppMsgBox()
  168.  
  169.  
  170. //--------------------------------------------------------------------------;
  171. //
  172. //  int AppSetWindowText
  173. //
  174. //  Description:
  175. //      This function formats a string and sets the specified window text
  176. //      to the result.
  177. //
  178. //  Arguments:
  179. //      HWND hwnd: Handle to window to receive the new text.
  180. //
  181. //      PTSTR pszFormat: Pointer to any valid format for wsprintf.
  182. //
  183. //  Return (int):
  184. //      The return value is the number of bytes that the resulting window
  185. //      text was.
  186. //
  187. //  History:
  188. //       2/ 7/93
  189. //
  190. //--------------------------------------------------------------------------;
  191.  
  192. int FNCGLOBAL AppSetWindowText
  193. (
  194.     HWND                    hwnd,
  195.     PTSTR                  pszFormat,
  196.     ...
  197. )
  198. {
  199.     va_list     va;
  200.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  201.     int         n;
  202.  
  203.     //
  204.     //  format and display the string in the window...
  205.     //
  206.     va_start(va, pszFormat);
  207.     n = wvsprintf(ach, pszFormat, va);
  208.     va_end(va);
  209.  
  210.     SetWindowText(hwnd, ach);
  211.  
  212.     return (n);
  213. } // AppSetWindowText()
  214.  
  215.  
  216. //--------------------------------------------------------------------------;
  217. //
  218. //  void MixAppDebugLog
  219. //
  220. //  Description:
  221. //      This function logs information to the debugger if the Debug Log
  222. //      option is set. You can then run DBWin (or something similar)
  223. //      to redirect the output whereever you want. Very useful for debugging
  224. //      ACM drivers.
  225. //
  226. //  Arguments:
  227. //      PTSTR pszFormat: Pointer to any valid format for wsprintf.
  228. //
  229. //  Return (void):
  230. //      None.
  231. //
  232. //  History:
  233. //       2/ 7/93
  234. //
  235. //--------------------------------------------------------------------------;
  236.  
  237. void FNCGLOBAL MixAppDebugLog
  238. (
  239.     PTSTR                  pszFormat,
  240.     ...
  241. )
  242. {
  243.     static  TCHAR   szDebugLogSeparator[] = TEXT("=============================================================================\r\n");
  244.  
  245.     va_list     va;
  246.     TCHAR       ach[APP_MAX_STRING_ERROR_CHARS];
  247.  
  248.  
  249.     //
  250.     //  !!! UNICODE !!!
  251.     //
  252.     //
  253.     if (0 != (APP_OPTF_DEBUGLOG & gfuAppOptions))
  254.     {
  255.         if (NULL == pszFormat)
  256.         {
  257.             OutputDebugString(szDebugLogSeparator);
  258.             return;
  259.         }
  260.  
  261.         //
  262.         //  format and display the string in a message box...
  263.         //
  264.         va_start(va, pszFormat);
  265.         wvsprintf(ach, pszFormat, va);
  266.         va_end(va);
  267.  
  268.         OutputDebugString(ach);
  269.     }
  270. } // MixAppDebugLog()
  271.  
  272.  
  273. //--------------------------------------------------------------------------;
  274. //
  275. //  int MEditPrintF
  276. //
  277. //  Description:
  278. //      This function is used to print formatted text into a Multiline
  279. //      Edit Control as if it were a standard console display. This is
  280. //      a very easy way to display small amounts of text information
  281. //      that can be scrolled and copied to the clip-board.
  282. //
  283. //  Arguments:
  284. //      HWND hedit: Handle to a Multiline Edit control.
  285. //
  286. //      PTSTR pszFormat: Pointer to any valid format for wsprintf. If
  287. //      this argument is NULL, then the Multiline Edit Control is cleared
  288. //      of all text.
  289. //
  290. //
  291. //  Return (int):
  292. //      Returns the number of characters written into the edit control.
  293. //
  294. //  Notes:
  295. //      The pszFormat string can contain combinations of escapes that
  296. //      modify the default behaviour of this function. Escapes are single
  297. //      character codes placed at the _beginning_ of the format string.
  298. //
  299. //      Current escapes defined are:
  300. //
  301. //      ~   :   Suppresses the default CR/LF added to the end of the
  302. //              printed line. Since the most common use of this function
  303. //              is to output a whole line of text with a CR/LF, that is
  304. //              the default.
  305. //
  306. //      `   :   Suppresses logging to the debug terminal (regardless of
  307. //              the global debug log options flag).
  308. //
  309. //  History:
  310. //      05/16/93
  311. //
  312. //--------------------------------------------------------------------------;
  313.  
  314. int FNCGLOBAL MEditPrintF
  315. (
  316.     HWND                    hedit,
  317.     PTSTR                   pszFormat,
  318.     ...
  319. )
  320. {
  321.     va_list     va;
  322.     TCHAR       ach[APP_MAX_STRING_RC_CHARS];
  323.     int         n;
  324.     BOOL        fCRLF;
  325.     BOOL        fDebugLog;
  326.  
  327.     //
  328.     //  default the escapes
  329.     //
  330.     fCRLF     = TRUE;
  331.     fDebugLog = (0 != (APP_OPTF_DEBUGLOG & gfuAppOptions));
  332.  
  333.  
  334.     //
  335.     //  if the pszFormat argument is NULL, then just clear all text in
  336.     //  the edit control..
  337.     //
  338.     if (NULL == pszFormat)
  339.     {
  340.         SetWindowText(hedit, gszNull);
  341.  
  342.         if (fDebugLog)
  343.             MixAppDebugLog(NULL);
  344.  
  345.         return (0);
  346.     }
  347.  
  348.     //
  349.     //  format and display the string in the window... first search for
  350.     //  escapes to modify default behaviour.
  351.     //
  352.     for (;;)
  353.     {
  354.         switch (*pszFormat)
  355.         {
  356.             case '~':
  357.                 fCRLF = FALSE;
  358.                 pszFormat++;
  359.                 continue;
  360.  
  361.             case '`':
  362.                 fDebugLog = FALSE;
  363.                 pszFormat++;
  364.                 continue;
  365.         }
  366.  
  367.         break;
  368.     }
  369.  
  370.     va_start(va, pszFormat);
  371.     n = wvsprintf(ach, pszFormat, va);
  372.     va_end(va);
  373.  
  374.     Edit_SetSel(hedit, (WPARAM)-1, (LPARAM)-1);
  375.     Edit_ReplaceSel(hedit, ach);
  376.  
  377.     if (fDebugLog)
  378.         MixAppDebugLog(ach);
  379.  
  380.     if (fCRLF)
  381.     {
  382.         Edit_SetSel(hedit, (WPARAM)-1, (LPARAM)-1);
  383.         Edit_ReplaceSel(hedit, gszCRLF);
  384.  
  385.         if (fDebugLog)
  386.             MixAppDebugLog(gszCRLF);
  387.     }
  388.  
  389.     return (n);
  390. } // MEditPrintF()
  391.  
  392.  
  393. //==========================================================================;
  394. //
  395. //
  396. //
  397. //
  398. //==========================================================================;
  399.  
  400. //--------------------------------------------------------------------------;
  401. //
  402. //  HMIXER MixAppNewDevice
  403. //
  404. //  Description:
  405. //
  406. //
  407. //  Arguments:
  408. //      HWND hwnd:
  409. //
  410. //      HMIXER hmxCur:
  411. //
  412. //      UINT uMxId:
  413. //
  414. //  Return (HMIXER):
  415. //
  416. //  History:
  417. //      09/25/93
  418. //
  419. //--------------------------------------------------------------------------;
  420.  
  421. HMIXER FNGLOBAL MixAppNewDevice
  422. (
  423.     HWND                    hwnd,
  424.     HMIXER                  hmxCur,
  425.     UINT                    uMxId
  426. )
  427. {
  428.     MMRESULT            mmr;
  429.     HMIXER              hmx;
  430.     MIXERCAPS           mxcaps;
  431.  
  432.  
  433.     //
  434.     //
  435.     //
  436.     mmr = mixerGetDevCaps(uMxId, &mxcaps, sizeof(mxcaps));
  437.     if (MMSYSERR_NOERROR != mmr)
  438.     {
  439.         AppMsgBox(NULL, MB_OK | MB_ICONEXCLAMATION,
  440.                 "mixerGetDevCaps() failed on uMxId=%u, mmr=%u!",
  441.                 uMxId, mmr);
  442.         return (hmxCur);
  443.     }
  444.  
  445.  
  446.     //
  447.     //
  448.     //
  449.     mmr = mixerOpen(&hmx, uMxId, (DWORD)(UINT)hwnd, 0L, CALLBACK_WINDOW);
  450.     if (MMSYSERR_NOERROR != mmr)
  451.     {
  452.         AppMsgBox(NULL, MB_OK | MB_ICONEXCLAMATION,
  453.                 "mixerOpen() failed on uMxId=%u, mmr=%u!",
  454.                 uMxId, mmr);
  455.         return (hmxCur);
  456.     }
  457.  
  458.  
  459.     if (NULL != hmxCur)
  460.     {
  461.         mmr = mixerClose(hmxCur);
  462.         if (MMSYSERR_NOERROR != mmr)
  463.         {
  464.             AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  465.                       "mixerClose() failed on hmx=%.04Xh, mmr=%u!",
  466.                       hmxCur, mmr);
  467.         }
  468.  
  469.         hmxCur = NULL;
  470.     }
  471.  
  472.  
  473.     AppSetWindowText(hwnd, "Mixer Device: %s", (LPSTR)mxcaps.szPname);
  474.  
  475.     return (hmx);
  476. } // MixAppNewDevice()
  477.  
  478.  
  479. //--------------------------------------------------------------------------;
  480. //
  481. //  BOOL MixAppDisplayDevCaps
  482. //
  483. //  Description:
  484. //
  485. //
  486. //  Arguments:
  487. //      HWND hedit:
  488. //
  489. //      UINT uMxId:
  490. //
  491. //      LPMIXERCAPS pmxcaps:
  492. //
  493. //  Return (BOOL):
  494. //
  495. //  History:
  496. //      09/25/93
  497. //
  498. //--------------------------------------------------------------------------;
  499.  
  500. BOOL FNLOCAL MixAppDisplayDevCaps
  501. (
  502.     HWND                    hedit,
  503.     UINT                    uMxId,
  504.     LPMIXERCAPS             pmxcaps
  505. )
  506. {
  507.     static TCHAR    szDisplayTitle[]    = TEXT("[Mixer Device Capabilities]\r\n");
  508.  
  509.     SetWindowRedraw(hedit, FALSE);
  510.  
  511.     //
  512.     //
  513.     //
  514.     MEditPrintF(hedit, NULL);
  515.     MEditPrintF(hedit, szDisplayTitle);
  516.  
  517.     MEditPrintF(hedit, "%18s: %u", (LPTSTR)"Device Id", uMxId);
  518.  
  519.     MEditPrintF(hedit, "%18s: %u", (LPTSTR)"Manufacturer Id", pmxcaps->wMid);
  520.     MEditPrintF(hedit, "%18s: %u", (LPTSTR)"Product Id", pmxcaps->wPid);
  521.     MEditPrintF(hedit, "%18s: %u.%.02u", (LPTSTR)"Driver Version",
  522.                 (pmxcaps->vDriverVersion >> 8),
  523.                 (pmxcaps->vDriverVersion & 0x00FF));
  524.     MEditPrintF(hedit, "%18s: '%s'", (LPTSTR)"Device Name", (LPSTR)pmxcaps->szPname);
  525.     MEditPrintF(hedit, "%18s: %.08lXh", (LPTSTR)"Support Flags", pmxcaps->fdwSupport);
  526.     MEditPrintF(hedit, "%18s: %lu", (LPTSTR)"Destinations", pmxcaps->cDestinations);
  527.  
  528.     SetWindowRedraw(hedit, TRUE);
  529.  
  530.     return (TRUE);
  531. } // MixAppDisplayDevCaps()
  532.  
  533.  
  534. //--------------------------------------------------------------------------;
  535. //
  536. //  BOOL MixAppDlgProcDevice
  537. //
  538. //  Description:
  539. //
  540. //
  541. //  Arguments:
  542. //      HWND hwnd:
  543. //
  544. //      UINT uMsg:
  545. //
  546. //      WPARAM wParam:
  547. //
  548. //      LPARAM lParam:
  549. //
  550. //  Return (BOOL):
  551. //
  552. //  History:
  553. //      09/25/93
  554. //
  555. //--------------------------------------------------------------------------;
  556.  
  557. BOOL CALLBACK MixAppDlgProcDevice
  558. (
  559.     HWND            hwnd,
  560.     UINT            uMsg,
  561.     WPARAM          wParam,
  562.     LPARAM          lParam
  563. )
  564. {
  565.     UINT                cMixerDevs;
  566.     UINT                u;
  567.     UINT                uMxId;
  568.     UINT                uId;
  569.     UINT                uCmd;
  570.     HWND                hcb;
  571.     HWND                hedit;
  572.     MIXERCAPS           mxcaps;
  573.  
  574.     //
  575.     //
  576.     //
  577.     switch (uMsg)
  578.     {
  579.         case WM_INITDIALOG:
  580.             hedit = GetDlgItem(hwnd, IDD_MADEVICE_EDIT_CAPABILITIES);
  581.             SetWindowFont(hedit, GetStockFont(SYSTEM_FIXED_FONT), FALSE);
  582.  
  583.             SetWindowLong(hwnd, DWL_USER, lParam);
  584.  
  585.             uMxId = (UINT)lParam;
  586.  
  587.             //
  588.             //
  589.             //
  590.             hcb = GetDlgItem(hwnd, IDD_MADEVICE_COMBO_DEVICE);
  591.  
  592.             cMixerDevs = mixerGetNumDevs();
  593.             for (u = 0; u < cMixerDevs; u++)
  594.             {
  595.                 mixerGetDevCaps(u, &mxcaps, sizeof(mxcaps));
  596.                 ComboBox_AddString(hcb, mxcaps.szPname);
  597.  
  598.                 if (uMxId == u)
  599.                 {
  600.                     hedit = GetDlgItem(hwnd, IDD_MADEVICE_EDIT_CAPABILITIES);
  601.                     MixAppDisplayDevCaps(hedit, uMxId, &mxcaps);
  602.                 }
  603.             }
  604.  
  605.             ComboBox_SetCurSel(hcb, uMxId);
  606.             return (TRUE);
  607.  
  608.  
  609.         case WM_COMMAND:
  610.             uId = GET_WM_COMMAND_ID(wParam, lParam);
  611.  
  612.             switch (uId)
  613.             {
  614.                 case IDOK:
  615.                     hcb   = GetDlgItem(hwnd, IDD_MADEVICE_COMBO_DEVICE);
  616.                     uMxId = ComboBox_GetCurSel(hcb);
  617.                     if (CB_ERR != uMxId)
  618.                     {
  619.                         EndDialog(hwnd, uMxId);
  620.                         break;
  621.                     }
  622.  
  623.                     // -- fall through -- //
  624.  
  625.                 case IDCANCEL:
  626.                     uMxId = (UINT)GetWindowLong(hwnd, DWL_USER);
  627.                     EndDialog(hwnd, uMxId);
  628.                     break;
  629.  
  630.  
  631.                 case IDD_MADEVICE_COMBO_DEVICE:
  632.                     uCmd = GET_WM_COMMAND_CMD(wParam, lParam);
  633.                     hcb  = GET_WM_COMMAND_HWND(wParam, lParam);
  634.                     switch (uCmd)
  635.                     {
  636.                         case CBN_SELCHANGE:
  637.                             uMxId = ComboBox_GetCurSel(hcb);
  638.                             if (CB_ERR == uMxId)
  639.                                 break;
  640.  
  641.                             mixerGetDevCaps(uMxId, &mxcaps, sizeof(mxcaps));
  642.  
  643.                             hedit = GetDlgItem(hwnd, IDD_MADEVICE_EDIT_CAPABILITIES);
  644.                             MixAppDisplayDevCaps(hedit, uMxId, &mxcaps);
  645.                             break;
  646.                     }
  647.             }
  648.             return (TRUE);
  649.     }
  650.  
  651.     return (FALSE);
  652. } // MixAppDlgProcDevice()
  653.  
  654.  
  655.  
  656. //==========================================================================;
  657. //
  658. //  Main application window handling code...
  659. //
  660. //
  661. //==========================================================================;
  662.  
  663. //--------------------------------------------------------------------------;
  664. //
  665. //  LRESULT AppInitMenuPopup
  666. //
  667. //  Description:
  668. //      This function handles the WM_INITMENUPOPUP message. This message
  669. //      is sent to the window owning the menu that is going to become
  670. //      active. This gives an application the ability to modify the menu
  671. //      before it is displayed (disable/add items, etc).
  672. //
  673. //  Arguments:
  674. //      HWND hwnd: Handle to window that generated the WM_INITMENUPOPUP
  675. //      message.
  676. //
  677. //      HMENU hmenu: Handle to the menu that is to become active.
  678. //
  679. //      int nItem: Specifies the zero-based relative position of the menu
  680. //      item that invoked the popup menu.
  681. //
  682. //      BOOL fSysMenu: Specifies whether the popup menu is a System menu
  683. //      (TRUE) or it is not a System menu (FALSE).
  684. //
  685. //  Return (LRESULT):
  686. //      Returns zero if the message is processed.
  687. //
  688. //  History:
  689. //       1/ 2/93
  690. //
  691. //--------------------------------------------------------------------------;
  692.  
  693. LRESULT FNLOCAL AppInitMenuPopup
  694. (
  695.     HWND                    hwnd,
  696.     HMENU                   hmenu,
  697.     int                     nItem,
  698.     BOOL                    fSysMenu
  699. )
  700. {
  701.     int                 n;
  702.     BOOL                f;
  703.  
  704.     DPF(1, "AppInitMenuPopup(hwnd=%Xh, hmenu=%Xh, nItem=%d, fSysMenu=%d)",
  705.             hwnd, hmenu, nItem, fSysMenu);
  706.  
  707.     //
  708.     //  if the system menu is what got hit, succeed immediately... this
  709.     //  application has no stuff in the system menu.
  710.     //
  711.     if (fSysMenu)
  712.         return (0L);
  713.  
  714.     //
  715.     //  initialize the menu that is being 'popped up'
  716.     //
  717.     switch (nItem)
  718.     {
  719.         case APP_MENU_ITEM_FILE:
  720.             f = (0 != mixerGetNumDevs());
  721.             EnableMenuItem(hmenu, IDM_FILE_MIXER_DEVICE, (UINT)(f ? MF_ENABLED : MF_GRAYED));
  722.  
  723.             f = (0 != (gfuAppOptions & APP_OPTF_DEBUGLOG));
  724.             CheckMenuItem(hmenu, IDM_FILE_DEBUG_LOG, (UINT)(f ? MF_CHECKED : MF_UNCHECKED));
  725.             break;
  726.  
  727.         case APP_MENU_ITEM_VIEW:
  728.             n = ListBox_GetCurSel(gptlbLines->hlb);
  729.             f = (LB_ERR != n);
  730.  
  731.             EnableMenuItem(hmenu, IDM_VIEW_LINE_INFO,  (UINT)(f ? MF_ENABLED : MF_GRAYED));
  732.             EnableMenuItem(hmenu, IDM_VIEW_LINE_CONTROLS,  (UINT)(f ? MF_ENABLED : MF_GRAYED));
  733.             break;
  734.     }
  735.  
  736.     //
  737.     //  we processed the message--return 0...
  738.     //
  739.     return (0L);
  740. } // AppInitMenuPopup()
  741.  
  742.  
  743. //--------------------------------------------------------------------------;
  744. //
  745. //  LRESULT AppCommand
  746. //
  747. //  Description:
  748. //      This function handles the WM_COMMAND message.
  749. //
  750. //  Arguments:
  751. //      HWND hwnd: Handle to window receiving the WM_COMMAND message.
  752. //
  753. //      int nId: Control or menu item identifier.
  754. //
  755. //      HWND hwndCtl: Handle of control if the message is from a control.
  756. //      This argument is NULL if the message was not generated by a control.
  757. //
  758. //      UINT uCode: Notification code. This argument is 1 if the message
  759. //      was generated by an accelerator. If the message is from a menu,
  760. //      this argument is 0.
  761. //
  762. //  Return (LRESULT):
  763. //      Returns zero if the message is processed.
  764. //
  765. //  History:
  766. //      11/ 8/92
  767. //
  768. //--------------------------------------------------------------------------;
  769.  
  770. LRESULT FNLOCAL AppCommand
  771. (
  772.     HWND                    hwnd,
  773.     int                     nId,
  774.     HWND                    hwndCtl,
  775.     UINT                    uCode
  776. )
  777. {
  778.     int                 n;
  779.     UINT                uMxId;
  780.     LRESULT             lr;
  781.  
  782.     switch (nId)
  783.     {
  784.         case IDM_FILE_MIXER_DEVICE:
  785.             mixerGetID((HMIXEROBJ)ghmx, &uMxId, MIXER_OBJECTF_HMIXER);
  786.             n = DialogBoxParam(ghinst, DLG_MIXAPP_DEVICE, hwnd, (DLGPROC)MixAppDlgProcDevice, uMxId);
  787.             if ((UINT)n != uMxId)
  788.             {
  789.                 uMxId = (UINT)n;
  790.                 ghmx  = MixAppNewDevice(hwnd, ghmx, uMxId);
  791.  
  792.                 MixAppRefreshLineList(hwnd, gptlbLines);
  793.             }
  794.             break;
  795.  
  796.         case IDM_FILE_FONT:
  797.             MixAppChooseFont(hwnd);
  798.             break;
  799.  
  800.         case IDM_FILE_DEBUG_LOG:
  801.             gfuAppOptions ^= APP_OPTF_DEBUGLOG;
  802.             break;
  803.  
  804.         case IDM_FILE_ABOUT:
  805.             DialogBox(ghinst, DLG_ABOUT, hwnd, (DLGPROC)AboutDlgProc);
  806.             break;
  807.  
  808.         case IDM_FILE_EXIT:
  809.             FORWARD_WM_CLOSE(hwnd, SendMessage);
  810.             break;
  811.  
  812.  
  813.         case IDM_VIEW_LINE_INFO:
  814.             n  = ListBox_GetCurSel(gptlbLines->hlb);
  815.             if (LB_ERR == n)
  816.                 break;
  817.  
  818.             lr = ListBox_GetItemData(gptlbLines->hlb, n);
  819.             DialogBoxParam(ghinst, DLG_LINEINFO, hwnd, (DLGPROC)MixAppDlgProcLineInfo, lr);
  820.             break;
  821.  
  822.         case IDM_VIEW_LINE_CONTROLS:
  823.             n  = ListBox_GetCurSel(gptlbLines->hlb);
  824.             if (LB_ERR == n)
  825.                 break;
  826.  
  827.             lr = ListBox_GetItemData(gptlbLines->hlb, n);
  828.             DialogBoxParam(ghinst, DLG_LINECONTROLS, hwnd, (DLGPROC)MixAppDlgProcLineControls, lr);
  829.             break;
  830.  
  831.  
  832.         case IDM_UPDATE:
  833.             MixAppRefreshLineList(hwnd, gptlbLines);
  834.             break;
  835.  
  836.  
  837.         case IDD_APP_LIST_LINES:
  838.             switch (uCode)
  839.             {
  840.                 case LBN_SELCHANGE:
  841.                     break;
  842.  
  843.                 case LBN_DBLCLK:
  844.                     n  = ListBox_GetCurSel(hwndCtl);
  845.                     if (LB_ERR == n)
  846.                         break;
  847.  
  848.                     lr = ListBox_GetItemData(hwndCtl, n);
  849.                     if (GetKeyState(VK_CONTROL) < 0)
  850.                     {
  851.                         DialogBoxParam(ghinst, DLG_LINEINFO, hwnd, (DLGPROC)MixAppDlgProcLineInfo, lr);
  852.                     }
  853.                     else
  854.                     {
  855.                         DialogBoxParam(ghinst, DLG_LINECONTROLS, hwnd, (DLGPROC)MixAppDlgProcLineControls, lr);
  856.                     }
  857.                     break;
  858.             }
  859.             break;
  860.     }
  861.  
  862.     return (0L);
  863. } // AppCommand()
  864.  
  865.  
  866. //--------------------------------------------------------------------------;
  867. //
  868. //  LRESULT AppSize
  869. //
  870. //  Description:
  871. //      This function handles the WM_SIZE message for the application's
  872. //      window. This message is sent to the application window after the
  873. //      size has changed (but before it is painted).
  874. //
  875. //  Arguments:
  876. //      HWND hwnd: Handle to window that generated the WM_SIZE message.
  877. //
  878. //      UINT fuSizeType: Specifies the type of resizing requested. This
  879. //      argument is one of the following: SIZE_MAXIMIZED, SIZE_MINIMIZED,
  880. //      SIZE_RESTORED, SIZE_MAXHIDE, or SIZE_MAXSHOW.
  881. //
  882. //      int nWidth: Width of the new client area for the window.
  883. //
  884. //      int nHeight: Height of the new client area for the window.
  885. //
  886. //  Return (LRESULT):
  887. //      Returns zero if the application processes the message.
  888. //
  889. //  History:
  890. //       2/ 5/93
  891. //
  892. //--------------------------------------------------------------------------;
  893.  
  894. LRESULT FNLOCAL AppSize
  895. (
  896.     HWND                    hwnd,
  897.     UINT                    fuSizeType,
  898.     int                     nWidth,
  899.     int                     nHeight
  900. )
  901. {
  902.     RECT                rc;
  903.  
  904.     DPF(1, "AppSize(hwnd=%Xh, fuSizeType=%u, nWidth=%d, nHeight=%d)",
  905.             hwnd, fuSizeType, nWidth, nHeight);
  906.  
  907.     //
  908.     //  unless this application is the one being resized then don't waste
  909.     //  time computing stuff that doesn't matter. this applies to being
  910.     //  minimized also because this application does not have a custom
  911.     //  minimized state.
  912.     //
  913.     if ((SIZE_RESTORED != fuSizeType) && (SIZE_MAXIMIZED != fuSizeType))
  914.         return (0L);
  915.  
  916.  
  917.     //
  918.     //  size the devices listbox to be the total size of the client area--
  919.     //  inflate the rect by one so borders are not visible. note that
  920.     //  we need to leave room at the top for the title text which is one
  921.     //  line of text in height...
  922.     //
  923.     GetClientRect(hwnd, &rc);
  924.     InflateRect(&rc, 1, 1);
  925.  
  926.  
  927.     TlbMove(gptlbLines, &rc, FALSE);
  928.  
  929.  
  930.     //
  931.     //  we processed the message..
  932.     //
  933.     return (0L);
  934. } // AppSize()
  935.  
  936.  
  937. //--------------------------------------------------------------------------;
  938. //
  939. //  LRESULT AppPaint
  940. //
  941. //  Description:
  942. //
  943. //
  944. //  Arguments:
  945. //      HWND hwnd:
  946. //
  947. //  Return (LRESULT):
  948. //
  949. //  History:
  950. //      05/11/93
  951. //
  952. //--------------------------------------------------------------------------;
  953.  
  954. LRESULT FNLOCAL AppPaint
  955. (
  956.     HWND                    hwnd
  957. )
  958. {
  959.     PAINTSTRUCT         ps;
  960.  
  961.     //
  962.     //
  963.     //
  964.     BeginPaint(hwnd, &ps);
  965.  
  966.     TlbPaint(gptlbLines, hwnd, ps.hdc);
  967.  
  968.     EndPaint(hwnd, &ps);
  969.  
  970.     //
  971.     //  we processed the message
  972.     //
  973.     return (0L);
  974. } // AppPaint()
  975.  
  976.  
  977. //--------------------------------------------------------------------------;
  978. //
  979. //  LRESULT AppWndProc
  980. //
  981. //  Description:
  982. //      This is the main application window procedure.
  983. //
  984. //  Arguments:
  985. //      HWND hwnd: Handle to window.
  986. //
  987. //      UINT uMsg: Message being sent to the window.
  988. //
  989. //      WPARAM wParam: Specific argument to message.
  990. //
  991. //      LPARAM lParam: Specific argument to message.
  992. //
  993. //  Return (LRESULT):
  994. //      The return value depends on the message that is being processed.
  995. //
  996. //  History:
  997. //      11/ 8/92
  998. //
  999. //--------------------------------------------------------------------------;
  1000.  
  1001. LRESULT CALLBACK AppWndProc
  1002. (
  1003.     HWND                    hwnd,
  1004.     UINT                    uMsg,
  1005.     WPARAM                  wParam,
  1006.     LPARAM                  lParam
  1007. )
  1008. {
  1009.     LRESULT             lr;
  1010.  
  1011.     switch (uMsg)
  1012.     {
  1013.         case WM_CREATE:
  1014.             lr = HANDLE_WM_CREATE(hwnd, wParam, lParam, AppCreate);
  1015.             return (lr);
  1016.  
  1017.         case WM_INITMENUPOPUP:
  1018.             HANDLE_WM_INITMENUPOPUP(hwnd, wParam, lParam, AppInitMenuPopup);
  1019.             return (0L);
  1020.  
  1021.         case WM_COMMAND:
  1022.             lr = HANDLE_WM_COMMAND(hwnd, wParam, lParam, AppCommand);
  1023.             return (lr);
  1024.  
  1025.         case WM_SIZE:
  1026.             //
  1027.             //  handle what we want for sizing, and then always call the
  1028.             //  default handler...
  1029.             //
  1030.             HANDLE_WM_SIZE(hwnd, wParam, lParam, AppSize);
  1031.             break;
  1032.  
  1033.         case WM_PAINT:
  1034.             HANDLE_WM_PAINT(hwnd, wParam, lParam, AppPaint);
  1035.             break;
  1036.  
  1037.         case WM_QUERYENDSESSION:
  1038.             lr = HANDLE_WM_QUERYENDSESSION(hwnd, wParam, lParam, AppQueryEndSession);
  1039.             return (lr);
  1040.  
  1041.         case WM_ENDSESSION:
  1042.             HANDLE_WM_ENDSESSION(hwnd, wParam, lParam, AppEndSession);
  1043.             return (0L);
  1044.  
  1045.         case WM_CLOSE:
  1046.             HANDLE_WM_CLOSE(hwnd, wParam, lParam, AppClose);
  1047.             return (0L);
  1048.  
  1049.         case WM_DESTROY:
  1050.             PostQuitMessage(0);
  1051.             return (0L);
  1052.  
  1053.  
  1054.         case MM_MIXM_LINE_CHANGE:
  1055.             lr = MixAppLineChange(hwnd, (HMIXER)wParam, lParam);
  1056.             return (lr);
  1057.  
  1058.         case MM_MIXM_CONTROL_CHANGE:
  1059.             lr = MixAppControlChange(hwnd, (HMIXER)wParam, lParam);
  1060.             return (lr);
  1061.     }
  1062.  
  1063.     return (DefWindowProc(hwnd, uMsg, wParam, lParam));
  1064. } // AppWndProc()
  1065.  
  1066.  
  1067. //==========================================================================;
  1068. //
  1069. //  Main entry and message dispatching code
  1070. //
  1071. //
  1072. //==========================================================================;
  1073.  
  1074. //--------------------------------------------------------------------------;
  1075. //
  1076. //  int WinMain
  1077. //
  1078. //  Description:
  1079. //      This function is called by the system as the initial entry point
  1080. //      for a Windows application.
  1081. //
  1082. //  Arguments:
  1083. //      HINSTANCE hinst: Identifies the current instance of the
  1084. //      application.
  1085. //
  1086. //      HINSTANCE hinstPrev: Identifies the previous instance of the
  1087. //      application (NULL if first instance). For Win 32, this argument
  1088. //      is _always_ NULL.
  1089. //
  1090. //      LPSTR pszCmdLine: Points to null-terminated unparsed command line.
  1091. //      This string is strictly ANSI regardless of whether the application
  1092. //      is built for Unicode. To get the Unicode equivalent call the
  1093. //      GetCommandLine() function (Win 32 only).
  1094. //
  1095. //      int nCmdShow: How the main window for the application is to be
  1096. //      shown by default.
  1097. //
  1098. //  Return (int):
  1099. //      Returns result from WM_QUIT message (in wParam of MSG structure) if
  1100. //      the application is able to enter its message loop. Returns 0 if
  1101. //      the application is not able to enter its message loop.
  1102. //
  1103. //  History:
  1104. //      11/ 8/92
  1105. //
  1106. //--------------------------------------------------------------------------;
  1107.  
  1108. int PASCAL WinMain
  1109. (
  1110.     HINSTANCE               hinst,
  1111.     HINSTANCE               hinstPrev,
  1112.     LPSTR                   pszCmdLine,
  1113.     int                     nCmdShow
  1114. )
  1115. {
  1116.     int                 nResult;
  1117.     HWND                hwnd;
  1118.     MSG                 msg;
  1119.     HACCEL              haccl;
  1120.  
  1121.     // * * * temp  bodge * * *
  1122.     {
  1123.       HKEY htemp;
  1124.       RegOpenKey(HKEY_LOCAL_MACHINE, "A Value That Does Not Exist", &htemp);
  1125.     }
  1126.     // * * * * * * * * * * * *
  1127.  
  1128.     //
  1129.     //  our documentation states that WinMain is supposed to return 0 if
  1130.     //  we do not enter our message loop--so assume the worst...
  1131.     //
  1132.     nResult = 0;
  1133.  
  1134.     //
  1135.     //  make our instance handle global for convenience..
  1136.     //
  1137.     ghinst = hinst;
  1138.  
  1139.     //
  1140.     //  init some stuff, create window, etc.. note the explicit cast of
  1141.     //  pszCmdLine--this is to mute a warning (and an ugly ifdef) when
  1142.     //  compiling for Unicode. see AppInit() for more details.
  1143.     //
  1144.     hwnd = AppInit(hinst, hinstPrev, (LPTSTR)pszCmdLine, nCmdShow);
  1145.     if (hwnd)
  1146.     {
  1147.         haccl = LoadAccelerators(hinst, ACCEL_APP);
  1148.  
  1149.         //
  1150.         //  dispatch messages
  1151.         //
  1152.         while (GetMessage(&msg, NULL, 0, 0))
  1153.         {
  1154.             //
  1155.             //  do all the special stuff required for this application
  1156.             //  when dispatching messages..
  1157.             //
  1158.             if (!TranslateAccelerator(hwnd, haccl, &msg))
  1159.             {
  1160.                 TranslateMessage(&msg);
  1161.                 DispatchMessage(&msg);
  1162.             }
  1163.         }
  1164.  
  1165.         //
  1166.         //  return result of WM_QUIT message.
  1167.         //
  1168.         nResult = (int)msg.wParam;
  1169.     }
  1170.  
  1171.     //
  1172.     //  shut things down, clean up, etc.
  1173.     //
  1174.     nResult = AppExit(hinst, nResult);
  1175.  
  1176.     return (nResult);
  1177. } // WinMain()
  1178.