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 / mafader.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  23KB  |  834 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. //  mafader.c
  13. //
  14. //  Description:
  15. //
  16. //
  17. //  History:
  18. //       9/21/93
  19. //
  20. //==========================================================================;
  21.  
  22. #include <windows.h>
  23. #include <windowsx.h>
  24. #include <mmsystem.h>
  25. #include "muldiv32.h"
  26.  
  27. #include "mixapp.h"
  28.  
  29. #include "debug.h"
  30.  
  31.  
  32. //
  33. //
  34. //
  35. typedef struct tMACONTROLINSTANCE_FADER
  36. {
  37.     LPMACONTROLINSTANCE             pmaci;
  38.     int                             nRange;
  39.     int                             nPageInc;
  40.     MIXERCONTROLDETAILS_UNSIGNED    pmxcd_u[];
  41.  
  42. } MACONTROLINSTANCE_FADER, *PMACONTROLINSTANCE_FADER;
  43.  
  44.  
  45. //==========================================================================;
  46. //
  47. //
  48. //
  49. //
  50. //==========================================================================;
  51.  
  52. //--------------------------------------------------------------------------;
  53. //
  54. //  BOOL MixAppControlChangeFader
  55. //
  56. //  Description:
  57. //
  58. //
  59. //  Arguments:
  60. //      HWND hwnd:
  61. //
  62. //      HMIXER hmx:
  63. //
  64. //      DWORD dwControlID:
  65. //
  66. //  Return (BOOL):
  67. //
  68. //  History:
  69. //      09/22/93
  70. //
  71. //--------------------------------------------------------------------------;
  72.  
  73. BOOL FNLOCAL MixAppControlChangeFader
  74. (
  75.     HWND                    hwnd,
  76.     HMIXER                  hmx,
  77.     DWORD                   dwControlID
  78. )
  79. {
  80.     MMRESULT                        mmr;
  81.     HWND                            htxt;
  82.     PMACONTROLINSTANCE_FADER        pmaci_fader;
  83.     LPMACONTROLINSTANCE             pmaci;
  84.     LPMIXERLINE                     pmxl;
  85.     LPMIXERCONTROL                  pmxctrl;
  86.     PMIXERCONTROLDETAILS_UNSIGNED   pmxcd_u;
  87.     int                             nRange;
  88.     int                             nValue;
  89.     UINT                            cChannels;
  90.     UINT                            cMultipleItems;
  91.     UINT                            u;
  92.     UINT                            uIndex;
  93.     UINT                            v;
  94.     MIXERCONTROLDETAILS             mxcd;
  95.     HWND                            hsbFocus;
  96.     HWND                            hsb;
  97.  
  98.  
  99.     hsbFocus = GetFocus();
  100.     if (NULL == hsbFocus)
  101.     {
  102.         hsbFocus = GetDlgItem(hwnd, IDD_MACONTROL_MULTICHANNEL_BASE);
  103.     }
  104.     else
  105.     {
  106.         uIndex = GetDlgCtrlID(hsbFocus);
  107.         if (uIndex < IDD_MACONTROL_MULTICHANNEL_BASE)
  108.         {
  109.             hsbFocus = GetDlgItem(hwnd, IDD_MACONTROL_MULTICHANNEL_BASE);
  110.         }
  111.     }
  112.  
  113.  
  114.     //
  115.     //
  116.     //
  117.     pmaci_fader = (PMACONTROLINSTANCE_FADER)(UINT)GetWindowLong(hwnd, DWL_USER);
  118.     pmaci       = pmaci_fader->pmaci;
  119.     pmxl        = pmaci->pmxl;
  120.     pmxctrl     = pmaci->pmxctrl;
  121.     pmxcd_u     = &pmaci_fader->pmxcd_u[0];
  122.     nRange      = pmaci_fader->nRange;
  123.  
  124.     cChannels = (UINT)pmxl->cChannels;
  125.     if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl->fdwControl)
  126.         cChannels = 1;
  127.  
  128.  
  129.  
  130.     //
  131.     //
  132.     //
  133.     mxcd.cbStruct       = sizeof(mxcd);
  134.     mxcd.dwControlID    = pmxctrl->dwControlID;
  135.     mxcd.cChannels      = cChannels;
  136.     mxcd.cMultipleItems = pmxctrl->cMultipleItems;
  137.     mxcd.cbDetails      = sizeof(*pmxcd_u);
  138.     mxcd.paDetails      = pmxcd_u;
  139.  
  140.     mmr = mixerGetControlDetails((HMIXEROBJ)pmaci->hmx, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE);
  141.     if (MMSYSERR_NOERROR != mmr)
  142.     {
  143.         AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  144.                   "mixerGetControlDetails(ctrlid=%.08lXh) failed on hmx=%.04Xh, mmr=%u!",
  145.                   pmxctrl->dwControlID, pmaci->hmx, mmr);
  146.         return (FALSE);
  147.     }
  148.  
  149.  
  150.     cMultipleItems = 1;
  151.     if (MIXERCONTROL_CONTROLF_MULTIPLE & pmxctrl->fdwControl)
  152.         cMultipleItems = (UINT)pmxctrl->cMultipleItems;
  153.  
  154.  
  155.     for (u = 0; u < cChannels; u++)
  156.     {
  157.         for (v = 0; v < cMultipleItems; v++)
  158.         {
  159.             uIndex = (u * cMultipleItems) + v;
  160.  
  161.             nValue = (int)MulDivRN(pmxcd_u[uIndex].dwValue, nRange, 0xFFFF);
  162.  
  163.  
  164.             //
  165.             //  Windows is stupid and forces an update to scrollbars
  166.             //  (a flickering paint) even when the position does not
  167.             //  change... so don't update if it is already in the
  168.             //  right position.
  169.             //
  170.             hsb = GetDlgItem(hwnd, IDD_MACONTROL_MULTICHANNEL_BASE + uIndex);
  171.  
  172.             if (hsbFocus == hsb)
  173.             {
  174.                 htxt = GetDlgItem(hwnd, IDD_MACONTROL_TXT_VALUE);
  175.                 AppSetWindowText(htxt, "mapped=%d, dwValue=%lu",
  176.                                  nValue,
  177.                                  pmxcd_u[uIndex].dwValue);
  178.             }
  179.  
  180.             if (nRange - nValue == GetScrollPos(hsb, SB_CTL))
  181.                 continue;
  182.  
  183.             //
  184.             //  note that we _invert_ the position since a fader will
  185.             //  increase approaching the top (opposite of scrollbar
  186.             //  logic)
  187.             //
  188.             SetScrollPos(hsb, SB_CTL, nRange - nValue, TRUE);
  189.         }
  190.     }
  191.  
  192.     //
  193.     //
  194.     //
  195.     mxcd.cbStruct       = sizeof(mxcd);
  196.     mxcd.dwControlID    = pmxctrl->dwControlID;
  197.     mxcd.cChannels      = 1;
  198.     mxcd.cMultipleItems = pmxctrl->cMultipleItems;
  199.     mxcd.cbDetails      = sizeof(*pmxcd_u);
  200.     mxcd.paDetails      = pmxcd_u;
  201.  
  202.     mmr = mixerGetControlDetails((HMIXEROBJ)pmaci->hmx, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE);
  203.     if (MMSYSERR_NOERROR != mmr)
  204.     {
  205.         AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  206.                   "mixerGetControlDetails(ctrlid=%.08lXh) failed on hmx=%.04Xh, mmr=%u!",
  207.                   pmxctrl->dwControlID, pmaci->hmx, mmr);
  208.         return (FALSE);
  209.     }
  210.  
  211.  
  212.     for (v = 0; v < cMultipleItems; v++)
  213.     {
  214.         uIndex = v;
  215.  
  216.         nValue = (int)MulDivRN(pmxcd_u[uIndex].dwValue, nRange, 0xFFFF);
  217.  
  218.         hsb = GetDlgItem(hwnd, IDD_MACONTROL_UNIFORM_BASE + uIndex);
  219.         if (hsbFocus == hsb)
  220.         {
  221.             htxt = GetDlgItem(hwnd, IDD_MACONTROL_TXT_VALUE);
  222.             AppSetWindowText(htxt, "mapped=%d, dwValue=%lu",
  223.                              nValue,
  224.                              pmxcd_u[0].dwValue);
  225.         }
  226.  
  227.         if (nRange - nValue == GetScrollPos(hsb, SB_CTL))
  228.             continue;
  229.  
  230.         //
  231.         //  note that we _invert_ the position since a fader will
  232.         //  increase approaching the top (opposite of scrollbar
  233.         //  logic)
  234.         //
  235.         SetScrollPos(hsb, SB_CTL, nRange - nValue, TRUE);
  236.     }
  237.  
  238.  
  239.     return (TRUE);
  240. } // MixAppControlChangeFader()
  241.  
  242.  
  243. //--------------------------------------------------------------------------;
  244. //
  245. //  BOOL MixAppControlSetFader
  246. //
  247. //  Description:
  248. //
  249. //
  250. //  Arguments:
  251. //      HWND hwnd:
  252. //
  253. //      HWND hsb:
  254. //
  255. //      UINT uCode:
  256. //
  257. //      int nPos:
  258. //
  259. //  Return (BOOL):
  260. //
  261. //  History:
  262. //      09/22/93
  263. //
  264. //--------------------------------------------------------------------------;
  265.  
  266. BOOL FNLOCAL MixAppControlSetFader
  267. (
  268.     HWND                    hwnd,
  269.     HWND                    hsb,
  270.     UINT                    uCode,
  271.     int                     nPos
  272. )
  273. {
  274.     PMACONTROLINSTANCE_FADER        pmaci_fader;
  275.     LPMACONTROLINSTANCE             pmaci;
  276.     LPMIXERLINE                     pmxl;
  277.     LPMIXERCONTROL                  pmxctrl;
  278.     PMIXERCONTROLDETAILS_UNSIGNED   pmxcd_u;
  279.     MMRESULT                        mmr;
  280.     int                             nRange;
  281.     int                             nPageInc;
  282.     int                             nValue;
  283.     UINT                            cChannels;
  284.     UINT                            uIndex;
  285.     MIXERCONTROLDETAILS             mxcd;
  286.  
  287.     //
  288.     //
  289.     //
  290.     pmaci_fader = (PMACONTROLINSTANCE_FADER)(UINT)GetWindowLong(hwnd, DWL_USER);
  291.     pmaci       = pmaci_fader->pmaci;
  292.     pmxl        = pmaci->pmxl;
  293.     pmxctrl     = pmaci->pmxctrl;
  294.     pmxcd_u     = &pmaci_fader->pmxcd_u[0];
  295.     nRange      = pmaci_fader->nRange;
  296.     nPageInc    = pmaci_fader->nPageInc;
  297.  
  298.  
  299.     uIndex = GetDlgCtrlID(hsb);
  300.  
  301.     if (uIndex < IDD_MACONTROL_UNIFORM_BASE)
  302.     {
  303.         cChannels = (UINT)pmxl->cChannels;
  304.         if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl->fdwControl)
  305.             cChannels = 1;
  306.  
  307.         uIndex -= IDD_MACONTROL_MULTICHANNEL_BASE;
  308.     }
  309.     else
  310.     {
  311.         cChannels = 1;
  312.  
  313.         uIndex -= IDD_MACONTROL_UNIFORM_BASE;
  314.     }
  315.  
  316.  
  317.     nValue = GetScrollPos(hsb, SB_CTL);
  318.  
  319.     switch (uCode)
  320.     {
  321.         case SB_PAGEDOWN:
  322.             nValue = (int)min(nRange, (LONG)nValue + nPageInc);
  323.             break;
  324.  
  325.         case SB_LINEDOWN:
  326.             nValue = (int)min(nRange, (LONG)nValue + 1);
  327.             break;
  328.  
  329.         case SB_PAGEUP:
  330.             nValue -= nPageInc;
  331.  
  332.             //-- fall through --//
  333.  
  334.         case SB_LINEUP:
  335.             nValue = (nValue < 1) ? 0 : (nValue - 1);
  336.             break;
  337.  
  338.  
  339.         case SB_TOP:
  340.             //
  341.             //  !!! would be a VERY BAD IDEA to go full volume !!!
  342.             //
  343.             nValue = nRange / 2;
  344.             break;
  345.  
  346.         case SB_BOTTOM:
  347.             nValue = nRange;
  348.             break;
  349.  
  350.         case SB_THUMBPOSITION:
  351.         case SB_THUMBTRACK:
  352.             nValue = nPos;
  353.             break;
  354.  
  355.         default:
  356.             return (FALSE);
  357.     }
  358.  
  359.  
  360.     //
  361.     //
  362.     //
  363.     //
  364.     mxcd.cbStruct       = sizeof(mxcd);
  365.     mxcd.dwControlID    = pmxctrl->dwControlID;
  366.     mxcd.cChannels      = cChannels;
  367.     mxcd.cMultipleItems = pmxctrl->cMultipleItems;
  368.     mxcd.cbDetails      = sizeof(*pmxcd_u);
  369.     mxcd.paDetails      = pmxcd_u;
  370.  
  371.     mmr = mixerGetControlDetails((HMIXEROBJ)pmaci->hmx, &mxcd, 0L);
  372.     if (MMSYSERR_NOERROR != mmr)
  373.     {
  374.         AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  375.                   "mixerGetControlDetails(ctrlid=%.08lXh) failed on hmx=%.04Xh, mmr=%u!",
  376.                   pmxctrl->dwControlID, pmaci->hmx, mmr);
  377.         return (FALSE);
  378.     }
  379.  
  380.     pmxcd_u[uIndex].dwValue  = (DWORD)MulDivRN((nRange - nValue), 0xFFFF, nRange);
  381.  
  382.     mmr = mixerSetControlDetails((HMIXEROBJ)pmaci->hmx, &mxcd, 0L);
  383.     if (MMSYSERR_NOERROR != mmr)
  384.     {
  385.         AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  386.                   "mixerSetControlDetails(ctrlid=%.08lXh) failed on hmx=%.04Xh, mmr=%u!",
  387.                   pmxctrl->dwControlID, pmaci->hmx, mmr);
  388.         return (FALSE);
  389.     }
  390.  
  391. // * commented out to stop sliders getting out of synch    *
  392. // * between different instances of the app. AGuy 22.12.93 *
  393. //  SetScrollPos(hsb, SB_CTL, nValue, TRUE);
  394.  
  395. #if 0
  396.     if (0 == uIndex)
  397.     {
  398.         htxt = GetDlgItem(hwnd, IDD_MACONTROL_TXT_VALUE);
  399.         AppSetWindowText(htxt, "mapped=%d, dwValue=%lu",
  400.                          nValue,
  401.                          pmxcd_u[0].dwValue);
  402.     }
  403. #endif
  404.  
  405.     return (TRUE);
  406. } // MixAppControlSetFader()
  407.  
  408.  
  409. //--------------------------------------------------------------------------;
  410. //
  411. //  BOOL MixAppLineChangeFader
  412. //
  413. //  Description:
  414. //
  415. //
  416. //  Arguments:
  417. //      HWND hwnd:
  418. //
  419. //      HMIXER hmx:
  420. //
  421. //      DWORD dwLineID:
  422. //
  423. //  Return (BOOL):
  424. //
  425. //  History:
  426. //      09/24/93
  427. //
  428. //--------------------------------------------------------------------------;
  429.  
  430. BOOL FNLOCAL MixAppLineChangeFader
  431. (
  432.     HWND                    hwnd,
  433.     HMIXER                  hmx,
  434.     DWORD                   dwLineID
  435. )
  436. {
  437.     MMRESULT                    mmr;
  438.     PMACONTROLINSTANCE_FADER    pmaci_fader;
  439.     LPMACONTROLINSTANCE         pmaci;
  440.     LPMIXERLINE                 pmxl;
  441.     MIXERLINE                   mxl;
  442.     BOOL                        fSource;
  443.     BOOL                        fActive;
  444.     BOOL                        fDisconnected;
  445.     HWND                        htxt;
  446.  
  447.  
  448.     //
  449.     //
  450.     //
  451.     pmaci_fader = (PMACONTROLINSTANCE_FADER)(UINT)GetWindowLong(hwnd, DWL_USER);
  452.     pmaci       = pmaci_fader->pmaci;
  453.     pmxl        = pmaci->pmxl;
  454.  
  455.     if (pmxl->dwLineID != dwLineID)
  456.     {
  457.         DPF(0, "!MixAppLineChangeFader: why am i getting notifications for some other line??");
  458.  
  459.         //
  460.         //  this would be a bug in this app... keep from bombing though
  461.         //  until i fix it.
  462.         //
  463.         dwLineID = pmxl->dwLineID;
  464.     }
  465.  
  466.     //
  467.     //  get the current state of the line that changed.. this is actually
  468.     //  silly that you have to do this just to determine if the line went
  469.     //  [in]active. sigh..
  470.     //
  471.     mxl.cbStruct      = sizeof(mxl);
  472.     mxl.dwLineID      = dwLineID;
  473.  
  474.     mmr = mixerGetLineInfo((HMIXEROBJ)ghmx, &mxl, MIXER_GETLINEINFOF_LINEID);
  475.     if (MMSYSERR_NOERROR != mmr)
  476.     {
  477.         AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  478.                   "mixerGetLineInfo(lineid=%.08lXh) failed on hmx=%.04Xh, mmr=%u!",
  479.                   dwLineID, ghmx, mmr);
  480.  
  481.         return (FALSE);
  482.     }
  483.  
  484.     fSource       = (0 != (MIXERLINE_LINEF_SOURCE & mxl.fdwLine));
  485.     fActive       = (0 != (MIXERLINE_LINEF_ACTIVE & mxl.fdwLine));
  486.     fDisconnected = (0 != (MIXERLINE_LINEF_DISCONNECTED & mxl.fdwLine));
  487.  
  488.  
  489.     htxt = GetDlgItem(hwnd, IDD_MACONTROL_TXT_LINEINFO);
  490.     AppSetWindowText(htxt, "(%s), '%s', %s, %s",
  491.                      fSource ? (LPSTR)"src" : (LPSTR)"DST",
  492.                      (LPSTR)mxl.szShortName,
  493.                      fActive ? (LPSTR)"ACTIVE" : (LPSTR)"inactive",
  494.                      fDisconnected ? (LPSTR)"DISCONNECTED" : (LPSTR)"connected");
  495.  
  496.     return (fActive);
  497. } // MixAppLineChangeFader()
  498.  
  499.  
  500. //--------------------------------------------------------------------------;
  501. //
  502. //  BOOL MixAppInitDialogFader
  503. //
  504. //  Description:
  505. //
  506. //
  507. //  Arguments:
  508. //      HWND hwnd:
  509. //
  510. //      HWND hwndFocus:
  511. //
  512. //      LPARAM lParam:
  513. //
  514. //  Return (BOOL):
  515. //
  516. //  History:
  517. //      09/22/93
  518. //
  519. //--------------------------------------------------------------------------;
  520.  
  521. BOOL FNLOCAL MixAppInitDialogFader
  522. (
  523.     HWND                    hwnd,
  524.     HWND                    hwndFocus,
  525.     LPARAM                  lParam
  526. )
  527. {
  528.     #define FSB_DEF_STYLE   (WS_VISIBLE | WS_CHILD | SBS_VERT | WS_TABSTOP)
  529.  
  530.     static TCHAR        szScrollBar[] = TEXT("scrollbar");
  531.     static TCHAR        szTitle[]     = TEXT("Fader Class: '%s'");
  532.  
  533.     TCHAR                       szControlType[64];
  534.     LPMACONTROLINSTANCE         pmaci;
  535.     PMACONTROLINSTANCE_FADER    pmaci_fader;
  536.  
  537.     LPMIXERLINE                 pmxl;
  538.     LPMIXERCONTROL              pmxctrl;
  539.  
  540.     HWND                        htxt;
  541.     UINT                        u;
  542.     UINT                        v;
  543.     HWND                        hsb;
  544.     RECT                        rcM;
  545.     RECT                        rcU;
  546.     int                         cxvsb;
  547.     UINT                        cb;
  548.     UINT                        cChannels;
  549.     UINT                        cMultipleItems;
  550.     UINT                        uIndex;
  551.     int                         nRange;
  552.     int                         nPageInc;
  553.  
  554.  
  555.     //
  556.     //
  557.     //
  558.     pmaci = (LPMACONTROLINSTANCE)lParam;
  559.     if (NULL == pmaci)
  560.     {
  561.         DPF(0, "!MixAppInitDialogFader: pmaci passed in lParam is NULL!?!");
  562.         return (FALSE);
  563.     }
  564.  
  565.     pmxl    = pmaci->pmxl;
  566.     pmxctrl = pmaci->pmxctrl;
  567.  
  568.     if (!MixAppGetControlTypeName(pmxctrl, szControlType))
  569.     {
  570.         return (FALSE);
  571.     }
  572.  
  573.     //
  574.     //
  575.     //
  576.     switch (pmxctrl->dwControlType)
  577.     {
  578.         case MIXERCONTROL_CONTROLTYPE_FADER:
  579.         case MIXERCONTROL_CONTROLTYPE_VOLUME:
  580.         case MIXERCONTROL_CONTROLTYPE_BASS:
  581.         case MIXERCONTROL_CONTROLTYPE_TREBLE:
  582.         case MIXERCONTROL_CONTROLTYPE_EQUALIZER:
  583.             break;
  584.  
  585.         default:
  586.             DPF(0, "!MixAppInitDialogFader: pmxctrl->dwControlType=%.08lXh not valid fader!", pmxctrl->dwControlType);
  587.             return (FALSE);
  588.     }
  589.  
  590.  
  591.  
  592.  
  593.     //
  594.     //
  595.     //
  596.     AppSetWindowText(hwnd, szTitle, (LPTSTR)szControlType);
  597.     SetDlgItemText(hwnd, IDD_MACONTROL_TXT_SHORT_NAME, pmxctrl->szShortName);
  598.     SetDlgItemText(hwnd, IDD_MACONTROL_TXT_LONG_NAME,  pmxctrl->szName);
  599.  
  600.     htxt = GetDlgItem(hwnd, IDD_MACONTROL_TXT_BOUNDS);
  601.     AppSetWindowText(htxt, "dwMinimum=%lu, dwMaximum=%lu",
  602.                      pmxctrl->Bounds.dwMinimum,
  603.                      pmxctrl->Bounds.dwMaximum);
  604.  
  605.     htxt = GetDlgItem(hwnd, IDD_MACONTROL_TXT_METRICS);
  606.     AppSetWindowText(htxt, "cSteps=%lu",
  607.                      pmxctrl->Metrics.cSteps);
  608.  
  609.  
  610.  
  611.     //
  612.     //
  613.     //
  614.     cChannels = (UINT)pmxl->cChannels;
  615.     if (MIXERCONTROL_CONTROLF_UNIFORM & pmxctrl->fdwControl)
  616.         cChannels = 1;
  617.  
  618.     cMultipleItems = 1;
  619.     if (MIXERCONTROL_CONTROLF_MULTIPLE & pmxctrl->fdwControl)
  620.         cMultipleItems = (UINT)pmxctrl->cMultipleItems;
  621.  
  622.     cb  = sizeof(*pmaci_fader);
  623.     cb += cChannels * cMultipleItems * sizeof(pmaci_fader->pmxcd_u[0]);
  624.     pmaci_fader = (PMACONTROLINSTANCE_FADER)LocalAlloc(LPTR, cb);
  625.     if (NULL == pmaci_fader)
  626.     {
  627.         DPF(0, "!MixAppInitDialogFader: failed trying to alloc %u bytes for control instance!", cb);
  628.         return (FALSE);
  629.     }
  630.  
  631.  
  632.     //
  633.     //
  634.     //
  635.     SetWindowLong(hwnd, DWL_USER, (LPARAM)(UINT)pmaci_fader);
  636.  
  637.     nRange   = (int)min(32767, pmxctrl->Metrics.cSteps - 1);
  638.     nPageInc = nRange / 10;
  639.     if (0 == nPageInc)
  640.         nPageInc = 1;
  641.  
  642.     pmaci_fader->pmaci    = pmaci;
  643.     pmaci_fader->nRange   = nRange;
  644.     pmaci_fader->nPageInc = nPageInc;
  645.  
  646.  
  647.     //
  648.     //
  649.     //
  650.     //
  651.     cxvsb = GetSystemMetrics(SM_CXVSCROLL);
  652.  
  653.     hsb = GetDlgItem(hwnd, IDD_MACONTROL_GRP_MULTICHANNEL);
  654.     GetWindowRect(hsb, &rcM);
  655.  
  656.     InflateRect(&rcM, -10, -20);
  657.     ScreenToClient(hwnd, (LPPOINT)&rcM.left);
  658.     ScreenToClient(hwnd, (LPPOINT)&rcM.right);
  659.  
  660.     rcM.right = rcM.left + cxvsb;
  661.  
  662.     for (u = 0; u < cChannels; u++)
  663.     {
  664.         for (v = 0; v < cMultipleItems; v++)
  665.         {
  666.             uIndex = (u * cMultipleItems) + v;
  667.  
  668.             hsb = CreateWindow(szScrollBar, gszNull, FSB_DEF_STYLE,
  669.                                rcM.left, rcM.top,
  670.                                rcM.right - rcM.left,
  671.                                rcM.bottom - rcM.top,
  672.                                hwnd, (HMENU)(IDD_MACONTROL_MULTICHANNEL_BASE + uIndex),
  673.                                ghinst, NULL);
  674.  
  675.             SetScrollRange(hsb, SB_CTL, 0, nRange, FALSE);
  676.  
  677.             rcM.left  += cxvsb + 4;
  678.             rcM.right += cxvsb + 4;
  679.         }
  680.  
  681.         //
  682.         //  add more separation between channels
  683.         //
  684.         rcM.left  += cxvsb;
  685.         rcM.right += cxvsb;
  686.     }
  687.  
  688.  
  689.     //
  690.     //
  691.     //
  692.     //
  693.     hsb = GetDlgItem(hwnd, IDD_MACONTROL_GRP_UNIFORM);
  694.     GetWindowRect(hsb, &rcU);
  695.  
  696.     InflateRect(&rcU, -10, -20);
  697.     ScreenToClient(hwnd, (LPPOINT)&rcU.left);
  698.     ScreenToClient(hwnd, (LPPOINT)&rcU.right);
  699.  
  700.     rcU.right = rcU.left + cxvsb;
  701.  
  702.     for (v = 0; v < cMultipleItems; v++)
  703.     {
  704.         hsb = CreateWindow(szScrollBar, gszNull, FSB_DEF_STYLE,
  705.                             rcU.left, rcU.top,
  706.                             rcU.right - rcU.left,
  707.                             rcU.bottom - rcU.top,
  708.                             hwnd, (HMENU)(IDD_MACONTROL_UNIFORM_BASE + v),
  709.                             ghinst, NULL);
  710.  
  711.         SetScrollRange(hsb, SB_CTL, 0, nRange, FALSE);
  712.  
  713.         rcU.left  += cxvsb + 4;
  714.         rcU.right += cxvsb + 4;
  715.     }
  716.  
  717.  
  718.     //
  719.     //
  720.     //
  721.     SendMessage(hwnd,
  722.                 MM_MIXM_LINE_CHANGE,
  723.                 (WPARAM)pmaci->hmx,
  724.                 pmxl->dwLineID);
  725.  
  726.     SendMessage(hwnd,
  727.                 MM_MIXM_CONTROL_CHANGE,
  728.                 (WPARAM)pmaci->hmx,
  729.                 pmxctrl->dwControlID);
  730.  
  731.     return (TRUE);
  732. } // MixAppInitDialogFader()
  733.  
  734.  
  735. //==========================================================================;
  736. //
  737. //
  738. //
  739. //
  740. //==========================================================================;
  741.  
  742. //--------------------------------------------------------------------------;
  743. //
  744. //  BOOL MixAppDlgProcControlFader
  745. //
  746. //  Description:
  747. //
  748. //
  749. //  Arguments:
  750. //      HWND hwnd:
  751. //
  752. //      UINT uMsg:
  753. //
  754. //      WPARAM wParam:
  755. //
  756. //      LPARAM lParam:
  757. //
  758. //  Return (BOOL):
  759. //
  760. //  History:
  761. //      07/22/93
  762. //
  763. //--------------------------------------------------------------------------;
  764.  
  765. BOOL CALLBACK MixAppDlgProcControlFader
  766. (
  767.     HWND                    hwnd,
  768.     UINT                    uMsg,
  769.     WPARAM                  wParam,
  770.     LPARAM                  lParam
  771. )
  772. {
  773.     LRESULT             lr;
  774.     HLOCAL              hl;
  775.     UINT                uId;
  776.  
  777.  
  778.     //
  779.     //
  780.     //
  781.     switch (uMsg)
  782.     {
  783.         case WM_INITDIALOG:
  784.             DPF(0, "WM_INITDIALOG");
  785.             lr = HANDLE_WM_INITDIALOG(hwnd, wParam, lParam, MixAppInitDialogFader);
  786.             if (FALSE == lr)
  787.             {
  788.                 EndDialog(hwnd, FALSE);
  789.             }
  790.             else
  791.             {
  792.                 ghdlgControl = hwnd;
  793.             }
  794.             return (TRUE);
  795.  
  796.  
  797.         case MM_MIXM_LINE_CHANGE:
  798.             DPF(0, "MM_MIXM_LINE_CHANGE");
  799.             MixAppLineChangeFader(hwnd, (HMIXER)wParam, lParam);
  800.             return (TRUE);
  801.  
  802.         case MM_MIXM_CONTROL_CHANGE:
  803.             DPF(0, "MM_MIXM_CONTROL_CHANGE");
  804.             MixAppControlChangeFader(hwnd, (HMIXER)wParam, lParam);
  805.             DPF(0, "done...");
  806.             return (TRUE);
  807.  
  808.  
  809.         case WM_VSCROLL:
  810.             DPF(0,"WM_SCROLL");
  811.             HANDLE_WM_VSCROLL(hwnd, wParam, lParam, MixAppControlSetFader);
  812.             return (TRUE);
  813.  
  814.  
  815.         case WM_COMMAND:
  816.             DPF(0, "WM_COMMAND");
  817.             uId = GET_WM_COMMAND_ID(wParam, lParam);
  818.             switch (uId)
  819.             {
  820.                 case IDCANCEL:
  821.                 case IDOK:
  822.                     hl = (HLOCAL)(UINT)GetWindowLong(hwnd, DWL_USER);
  823.                     LocalFree(hl);
  824.  
  825.                     EndDialog(hwnd, TRUE);
  826.                     ghdlgControl = NULL;
  827.                     break;
  828.             }
  829.             break;
  830.     }
  831.  
  832.     return (FALSE);
  833. } // MixAppDlgProcControlFader()
  834.