Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

759 lines
21 KiB

  1. /*****************************************************************************
  2. *
  3. * Component: sndvol32.exe
  4. * File: choice.c
  5. * Purpose: properties dialog box code
  6. *
  7. * Copyright (c) 1985-1999 Microsoft Corporation
  8. *
  9. *****************************************************************************/
  10. #include <windows.h>
  11. #include <windowsx.h>
  12. #include <mmsystem.h>
  13. #include <commctrl.h>
  14. #include "volids.h"
  15. #include "volumei.h"
  16. #include "utils.h"
  17. typedef struct t_DEVICEPROP {
  18. BOOL fMixer; // is mixer
  19. UINT uDeviceID; // device ID
  20. DWORD dwPlayback; // mixerline representing playback
  21. DWORD dwRecording; // mixerline representing recording
  22. MIXERCAPS mxcaps;
  23. } DEVICEPROP, *PDEVICEPROP;
  24. typedef struct t_PRIVPROP {
  25. PMIXUIDIALOG pmxud; // app instance data
  26. PDEVICEPROP adp; // array of allocated device props
  27. PDEVICEPROP pdpCurSel; // current device selection
  28. DWORD dwDestSel; // last destination selection
  29. PVOLCTRLDESC avcd;
  30. DWORD cvcd;
  31. // in/out params
  32. UINT uDeviceID;
  33. BOOL fMixer;
  34. DWORD dwDestination;
  35. DWORD dwStyle;
  36. } PRIVPROP, *PPRIVPROP;
  37. #define PROPATOM TEXT("privprop")
  38. const TCHAR gszPropAtom[] = PROPATOM;
  39. #define SETPROP(x,y) SetProp((x), gszPropAtom, (HANDLE)(y))
  40. #define GETPROP(x) (PPRIVPROP)GetProp((x), gszPropAtom)
  41. #define REMOVEPROP(x) RemoveProp(x,gszPropAtom)
  42. void SetCheckState (HWND hwndLV, int nItem, BOOL bCheck)
  43. {
  44. LVITEM item;
  45. int nCheck = bCheck ? 2 : 1; // one based index
  46. ZeroMemory (&item, sizeof (item));
  47. item.mask = LVIF_STATE;
  48. item.iItem = nItem;
  49. item.stateMask = LVIS_STATEIMAGEMASK;
  50. item.state = INDEXTOSTATEIMAGEMASK (nCheck);
  51. ListView_SetItem (hwndLV, &item);
  52. }
  53. void EnableOk(
  54. HWND hwnd,
  55. BOOL fEnable)
  56. {
  57. HWND hOk, hCancel;
  58. BOOL fWasEnabled;
  59. hOk = GetDlgItem(hwnd,IDOK);
  60. hCancel = GetDlgItem(hwnd,IDCANCEL);
  61. fWasEnabled = IsWindowEnabled(hOk);
  62. if (!fEnable && fWasEnabled)
  63. {
  64. Button_SetStyle(hOk, BS_PUSHBUTTON, TRUE);
  65. SendMessage(hwnd, DM_SETDEFID, IDCANCEL, 0L);
  66. EnableWindow(hOk, FALSE);
  67. }
  68. else if (fEnable && !fWasEnabled)
  69. {
  70. EnableWindow(hOk, TRUE);
  71. Button_SetStyle(hCancel, BS_PUSHBUTTON, TRUE);
  72. SendMessage(hwnd, DM_SETDEFID, IDOK, 0L);
  73. }
  74. }
  75. void Properties_GroupEnable(
  76. HWND hwnd,
  77. const int ids[],
  78. int cids,
  79. BOOL fEnable)
  80. {
  81. int i;
  82. for (i = 0; i < cids; i++)
  83. EnableWindow(GetDlgItem(hwnd, ids[i]), fEnable);
  84. }
  85. void Properties_Enable_Prop_Volumes(
  86. HWND hwnd,
  87. BOOL fEnable)
  88. {
  89. const int ids[] = {
  90. IDC_PROP_VOLUMES,
  91. IDC_PROP_PLAYBACK,
  92. IDC_PROP_RECORDING,
  93. IDC_PROP_OTHER,
  94. IDC_PROP_OTHERLIST
  95. };
  96. if (!fEnable)
  97. ComboBox_SetCurSel(GetDlgItem(hwnd, IDC_PROP_OTHERLIST), -1);
  98. Properties_GroupEnable(hwnd, ids, SIZEOF(ids), fEnable);
  99. }
  100. void Properties_Enable_PROP_DEVICELIST(
  101. HWND hwnd,
  102. BOOL fEnable)
  103. {
  104. const int ids[] = {
  105. IDC_PROP_TXT1,
  106. IDC_PROP_DEVICELIST,
  107. };
  108. if (!fEnable)
  109. ComboBox_SetCurSel(GetDlgItem(hwnd, IDC_PROP_OTHERLIST), -1);
  110. Properties_GroupEnable(hwnd, ids, SIZEOF(ids), fEnable);
  111. }
  112. void Properties_Enable_PROP_VOLUMELIST(
  113. HWND hwnd,
  114. BOOL fEnable)
  115. {
  116. const int ids[] = {
  117. IDC_PROP_TXT2,
  118. IDC_PROP_VOLUMELIST,
  119. };
  120. Properties_GroupEnable(hwnd, ids, SIZEOF(ids), fEnable);
  121. }
  122. void Properties_CommitState(
  123. PPRIVPROP ppr,
  124. HWND hlb)
  125. {
  126. DWORD i;
  127. DWORD cItems = ListView_GetItemCount(hlb);
  128. if (!ppr->avcd)
  129. return;
  130. for (i=0;i<cItems;i++)
  131. {
  132. LV_ITEM lvi;
  133. lvi.iItem = i;
  134. lvi.iSubItem = 0;
  135. lvi.mask = LVIF_PARAM;
  136. if (ListView_GetItem(hlb, &lvi))
  137. {
  138. ppr->avcd[lvi.lParam].dwSupport = (ListView_GetCheckState (hlb, i))?0:VCD_SUPPORTF_HIDDEN;
  139. }
  140. }
  141. Volume_GetSetRegistryLineStates(ppr->pdpCurSel->mxcaps.szPname
  142. , ppr->avcd[0].szShortName
  143. , ppr->avcd
  144. , ppr->cvcd
  145. , SET );
  146. Mixer_CleanupVolumeDescription(ppr->avcd, ppr->cvcd);
  147. GlobalFreePtr(ppr->avcd);
  148. ppr->avcd = NULL;
  149. ppr->cvcd = 0L;
  150. }
  151. /*
  152. * Init the destination type groupbox
  153. *
  154. * */
  155. BOOL Properties_Init_Prop_Volumes(
  156. PPRIVPROP ppr,
  157. HWND hwnd)
  158. {
  159. HWND hPlay = GetDlgItem(hwnd, IDC_PROP_PLAYBACK);
  160. HWND hRec = GetDlgItem(hwnd, IDC_PROP_RECORDING);
  161. HWND hOther = GetDlgItem(hwnd, IDC_PROP_OTHER);
  162. HWND hOtherList = GetDlgItem(hwnd, IDC_PROP_OTHERLIST);
  163. DWORD iDest, cDest;
  164. BOOL fPlay = FALSE, fRec = FALSE;
  165. if (!ppr->pdpCurSel->fMixer)
  166. return FALSE;
  167. ComboBox_ResetContent(hOtherList);
  168. cDest = ppr->pdpCurSel->mxcaps.cDestinations;
  169. EnableWindow(hPlay, FALSE);
  170. EnableWindow(hRec, FALSE);
  171. EnableWindow(hOther, FALSE);
  172. for (iDest = 0; iDest < cDest; iDest++)
  173. {
  174. MIXERLINE mlDst;
  175. int imx;
  176. mlDst.cbStruct = sizeof ( mlDst );
  177. mlDst.dwDestination = iDest;
  178. if (mixerGetLineInfo((HMIXEROBJ)UIntToPtr(ppr->pdpCurSel->uDeviceID)
  179. , &mlDst
  180. , MIXER_GETLINEINFOF_DESTINATION)
  181. != MMSYSERR_NOERROR)
  182. continue;
  183. //
  184. // Conditionally enable selections. The first type for Play and
  185. // Record are the default Playback and Recording radiobuttons.
  186. // The next occurence of the same type is heaped into the Other
  187. // category.
  188. //
  189. if (mlDst.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
  190. && !fPlay)
  191. {
  192. EnableWindow(hPlay, TRUE);
  193. if (iDest == ppr->dwDestSel)
  194. CheckRadioButton(hwnd, IDC_PROP_PLAYBACK, IDC_PROP_OTHER
  195. , IDC_PROP_PLAYBACK);
  196. ppr->pdpCurSel->dwPlayback = iDest;
  197. fPlay = TRUE;
  198. }
  199. else if (mlDst.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_WAVEIN
  200. && !fRec)
  201. {
  202. EnableWindow(hRec, TRUE);
  203. if (iDest == ppr->dwDestSel)
  204. CheckRadioButton(hwnd, IDC_PROP_PLAYBACK, IDC_PROP_OTHER
  205. , IDC_PROP_RECORDING);
  206. ppr->pdpCurSel->dwRecording = iDest;
  207. fRec = TRUE;
  208. }
  209. else
  210. {
  211. EnableWindow(hOther, TRUE);
  212. imx = ComboBox_AddString(hOtherList, mlDst.szName);
  213. ComboBox_SetItemData(hOtherList, imx, iDest);
  214. if (iDest == ppr->dwDestSel)
  215. {
  216. CheckRadioButton(hwnd, IDC_PROP_PLAYBACK, IDC_PROP_OTHER
  217. , IDC_PROP_OTHER);
  218. ComboBox_SetCurSel(hOtherList, imx);
  219. }
  220. }
  221. }
  222. //
  223. // Disable the "other" drop down if its not selected
  224. //
  225. if (!IsDlgButtonChecked(hwnd, IDC_PROP_OTHER))
  226. {
  227. ComboBox_SetCurSel(hOtherList, 0);
  228. EnableWindow(hOtherList, FALSE);
  229. }
  230. return TRUE;
  231. }
  232. BOOL Properties_Init_PROP_VOLUMELIST(
  233. PPRIVPROP ppr,
  234. HWND hwnd)
  235. {
  236. HWND hlb = GetDlgItem(hwnd, IDC_PROP_VOLUMELIST);
  237. LV_COLUMN col = {LVCF_FMT | LVCF_WIDTH, LVCFMT_LEFT};
  238. RECT rc;
  239. BOOL fSet = FALSE;
  240. PVOLCTRLDESC avcd = NULL;
  241. DWORD cvcd = 0L;
  242. DWORD ivcd;
  243. int ilvi;
  244. LV_ITEM lvi;
  245. ListView_DeleteAllItems(hlb);
  246. ListView_SetExtendedListViewStyleEx (hlb, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
  247. ZeroMemory (&lvi, sizeof (lvi));
  248. GetClientRect(hlb, &rc);
  249. col.cx = rc.right - 2 * GetSystemMetrics(SM_CXEDGE);
  250. ListView_InsertColumn(hlb, 0, &col);
  251. if (ppr->avcd)
  252. {
  253. if (ppr->pdpCurSel->fMixer)
  254. Mixer_CleanupVolumeDescription(ppr->avcd, ppr->cvcd);
  255. // else
  256. // Nonmixer_CleanupVolumeDescription(ppr->avcd, ppr->cvcd);
  257. GlobalFreePtr(ppr->avcd);
  258. ppr->avcd = NULL;
  259. ppr->cvcd = 0L;
  260. }
  261. if (ppr->pdpCurSel->fMixer)
  262. {
  263. HMIXER hmx;
  264. MMRESULT mmr;
  265. //
  266. // Mixer API's are much more efficient with mixer handle...
  267. //
  268. mmr = mixerOpen(&hmx
  269. , ppr->pdpCurSel->uDeviceID
  270. , 0L
  271. , 0L
  272. , MIXER_OBJECTF_MIXER);
  273. if(MMSYSERR_NOERROR == mmr)
  274. {
  275. avcd = Mixer_CreateVolumeDescription((HMIXEROBJ)hmx
  276. , ppr->dwDestSel
  277. , &cvcd);
  278. mixerClose(hmx);
  279. }
  280. else
  281. {
  282. avcd = Mixer_CreateVolumeDescription((HMIXEROBJ)UIntToPtr(ppr->pdpCurSel->uDeviceID)
  283. , ppr->dwDestSel
  284. , &cvcd);
  285. }
  286. }
  287. else
  288. {
  289. avcd = Nonmixer_CreateVolumeDescription(ppr->dwDestSel
  290. , &cvcd);
  291. }
  292. if (avcd)
  293. {
  294. BOOL fFirstRun;
  295. //
  296. // Restore hidden state
  297. //
  298. fFirstRun = !Volume_GetSetRegistryLineStates(ppr->pdpCurSel->mxcaps.szPname
  299. , avcd[0].szShortName
  300. , avcd
  301. , cvcd
  302. , GET );
  303. if (fFirstRun)
  304. {
  305. for (ivcd = 0; ivcd < cvcd; ivcd++)
  306. {
  307. if (!(avcd[ivcd].dwSupport & VCD_SUPPORTF_DEFAULT))
  308. avcd[ivcd].dwSupport |= VCD_SUPPORTF_HIDDEN;
  309. }
  310. Volume_GetSetRegistryLineStates(ppr->pdpCurSel->mxcaps.szPname
  311. , avcd[0].szShortName
  312. , avcd
  313. , cvcd
  314. , SET);
  315. }
  316. for (ivcd = 0, ilvi = 0; ivcd < cvcd; ivcd++)
  317. {
  318. if (!(avcd[ivcd].dwSupport & VCD_SUPPORTF_VISIBLE))
  319. continue;
  320. lvi.iItem = ilvi;
  321. lvi.iSubItem = 0;
  322. lvi.mask = LVIF_TEXT|LVIF_PARAM;
  323. lvi.lParam = ivcd;
  324. lvi.pszText = avcd[ivcd].szName;
  325. ListView_InsertItem(hlb, &lvi);
  326. if (!(avcd[ivcd].dwSupport & VCD_SUPPORTF_HIDDEN))
  327. {
  328. fSet = TRUE;
  329. SetCheckState (hlb, ilvi, TRUE);
  330. }
  331. ilvi++;
  332. }
  333. ppr->avcd = avcd;
  334. ppr->cvcd = cvcd;
  335. }
  336. ListView_SetItemState(hlb, 0, TRUE, LVIS_FOCUSED);
  337. EnableOk(hwnd, fSet);
  338. return TRUE;
  339. }
  340. /*
  341. * Init the list of devices.
  342. *
  343. * */
  344. BOOL Properties_Init_PROP_DEVICELIST(
  345. PPRIVPROP ppr,
  346. HWND hwnd)
  347. {
  348. HWND hlb = GetDlgItem(hwnd, IDC_PROP_DEVICELIST);
  349. int iMixer;
  350. int cValidMixers = 0;
  351. int cMixers;
  352. cMixers = mixerGetNumDevs();
  353. if (!cMixers)
  354. return FALSE;
  355. ppr->adp = (PDEVICEPROP)GlobalAllocPtr(GHND,cMixers * sizeof(DEVICEPROP));
  356. if (ppr->adp == NULL)
  357. return FALSE;
  358. for (iMixer = 0; iMixer < cMixers; iMixer++)
  359. {
  360. int imx;
  361. MIXERCAPS* pmxcaps = &ppr->adp[iMixer].mxcaps;
  362. MMRESULT mmr;
  363. mmr = mixerGetDevCaps(iMixer, pmxcaps, sizeof(MIXERCAPS));
  364. if (mmr != MMSYSERR_NOERROR)
  365. continue;
  366. cValidMixers++;
  367. imx = ComboBox_AddString(hlb, pmxcaps->szPname);
  368. ppr->adp[iMixer].uDeviceID = iMixer;
  369. ppr->adp[iMixer].fMixer = TRUE;
  370. ComboBox_SetItemData(hlb, imx, &ppr->adp[iMixer]);
  371. }
  372. if (cValidMixers == 0)
  373. return FALSE;
  374. return TRUE;
  375. }
  376. BOOL Properties_OnCommand(
  377. HWND hwnd,
  378. int id,
  379. HWND hctl,
  380. UINT unotify)
  381. {
  382. PPRIVPROP ppr = GETPROP(hwnd);
  383. if (!ppr)
  384. return FALSE;
  385. switch (id)
  386. {
  387. case IDC_PROP_DEVICELIST:
  388. if (unotify == CBN_SELCHANGE)
  389. {
  390. int imx;
  391. PDEVICEPROP pdp;
  392. imx = ComboBox_GetCurSel(hctl);
  393. pdp = (PDEVICEPROP)ComboBox_GetItemData(hctl, imx);
  394. if (pdp == ppr->pdpCurSel)
  395. break;
  396. ppr->pdpCurSel = pdp;
  397. if (ppr->pdpCurSel->fMixer)
  398. Properties_Init_Prop_Volumes(ppr, hwnd);
  399. else
  400. Properties_Enable_Prop_Volumes(hwnd, FALSE);
  401. Properties_Init_PROP_VOLUMELIST(ppr, hwnd);
  402. }
  403. break;
  404. case IDC_PROP_PLAYBACK:
  405. EnableWindow(GetDlgItem(hwnd, IDC_PROP_OTHERLIST), FALSE);
  406. if (ppr->dwDestSel == ppr->pdpCurSel->dwPlayback)
  407. break;
  408. ppr->dwDestSel = ppr->pdpCurSel->dwPlayback;
  409. Properties_Init_PROP_VOLUMELIST(ppr, hwnd);
  410. break;
  411. case IDC_PROP_RECORDING:
  412. EnableWindow(GetDlgItem(hwnd, IDC_PROP_OTHERLIST), FALSE);
  413. if (ppr->dwDestSel == ppr->pdpCurSel->dwRecording)
  414. break;
  415. ppr->dwDestSel = ppr->pdpCurSel->dwRecording;
  416. Properties_Init_PROP_VOLUMELIST(ppr, hwnd);
  417. break;
  418. case IDC_PROP_OTHER:
  419. {
  420. HWND hol;
  421. DWORD dwSel;
  422. hol = GetDlgItem(hwnd, IDC_PROP_OTHERLIST);
  423. EnableWindow(hol, TRUE);
  424. ComboBox_SetCurSel(hol, 0);
  425. dwSel = (DWORD)ComboBox_GetItemData(hol, 0);
  426. if (ppr->dwDestSel == dwSel)
  427. break;
  428. ppr->dwDestSel = dwSel;
  429. Properties_Init_PROP_VOLUMELIST(ppr, hwnd);
  430. break;
  431. }
  432. case IDC_PROP_OTHERLIST:
  433. if (unotify == CBN_SELCHANGE)
  434. {
  435. int idst;
  436. DWORD dwSel;
  437. idst = ComboBox_GetCurSel(hctl);
  438. dwSel = (DWORD)ComboBox_GetItemData(hctl, idst);
  439. if (ppr->dwDestSel == dwSel)
  440. break;
  441. ppr->dwDestSel = dwSel;
  442. Properties_Init_PROP_VOLUMELIST(ppr, hwnd);
  443. }
  444. break;
  445. case IDOK:
  446. //
  447. // Save out to registry for restaring.
  448. //
  449. Properties_CommitState(ppr, GetDlgItem(hwnd, IDC_PROP_VOLUMELIST));
  450. ppr->uDeviceID = ppr->pdpCurSel->uDeviceID;
  451. ppr->fMixer = TRUE;
  452. ppr->dwDestination = ppr->dwDestSel;
  453. EndDialog(hwnd, TRUE);
  454. break;
  455. case IDCANCEL:
  456. Mixer_CleanupVolumeDescription(ppr->avcd, ppr->cvcd);
  457. if (ppr->avcd)
  458. {
  459. GlobalFreePtr(ppr->avcd);
  460. ppr->avcd = NULL;
  461. ppr->cvcd = 0L;
  462. }
  463. EndDialog(hwnd, FALSE);
  464. break;
  465. }
  466. return FALSE;
  467. }
  468. /*
  469. * Initialize the dialog
  470. *
  471. * */
  472. BOOL Properties_OnInitDialog(
  473. HWND hwnd,
  474. HWND hwndFocus,
  475. LPARAM lParam)
  476. {
  477. PPRIVPROP ppr;
  478. BOOL fEnable = TRUE;
  479. HWND hlv;
  480. SETPROP(hwnd, (PPRIVPROP)lParam);
  481. ppr = GETPROP(hwnd);
  482. if (!ppr)
  483. fEnable = FALSE;
  484. if (fEnable)
  485. fEnable = Properties_Init_PROP_DEVICELIST(ppr, hwnd);
  486. hlv = GetDlgItem(hwnd, IDC_PROP_VOLUMELIST);
  487. if (!fEnable)
  488. {
  489. //
  490. // Bad state, disable everything except cancel
  491. //
  492. Properties_Enable_PROP_DEVICELIST(hwnd, FALSE);
  493. Properties_Enable_Prop_Volumes(hwnd, FALSE);
  494. Properties_Enable_PROP_VOLUMELIST(hwnd, FALSE);
  495. EnableOk(hwnd, FALSE);
  496. return FALSE;
  497. }
  498. else
  499. {
  500. int i;
  501. PDEVICEPROP pdp;
  502. HWND hdl;
  503. //
  504. // make intial device selection
  505. //
  506. hdl = GetDlgItem(hwnd, IDC_PROP_DEVICELIST);
  507. ppr->dwDestSel = 0;
  508. ComboBox_SetCurSel(hdl, 0);
  509. ppr->pdpCurSel = (PDEVICEPROP)ComboBox_GetItemData(hdl, 0);
  510. i = ComboBox_GetCount(hdl);
  511. for (; i > 0 ; i-- )
  512. {
  513. pdp = (PDEVICEPROP)ComboBox_GetItemData(hdl,i-1);
  514. //
  515. // if things match up, then set the init data
  516. //
  517. if (pdp->uDeviceID == ppr->uDeviceID
  518. && pdp->fMixer == ppr->fMixer)
  519. {
  520. ppr->pdpCurSel = pdp;
  521. ComboBox_SetCurSel(hdl, i-1);
  522. ppr->dwDestSel = ppr->dwDestination;
  523. break;
  524. }
  525. }
  526. }
  527. Properties_Init_Prop_Volumes(ppr, hwnd);
  528. Properties_Init_PROP_VOLUMELIST(ppr, hwnd);
  529. return FALSE;
  530. }
  531. INT_PTR CALLBACK Properties_Proc(
  532. HWND hwnd,
  533. UINT msg,
  534. WPARAM wparam,
  535. LPARAM lparam)
  536. {
  537. extern TCHAR gszHelpFileName[];
  538. #include "helpids.h"
  539. static const DWORD aHelpIds[] = {
  540. IDC_PROP_TXT1, IDH_SNDVOL32_SELECT_DEVICE,
  541. IDC_PROP_DEVICELIST, IDH_SNDVOL32_SELECT_DEVICE,
  542. IDC_PROP_VOLUMES, IDH_SNDVOL32_SELECT_SOUND,
  543. IDC_PROP_PLAYBACK, IDH_SNDVOL32_SELECT_SOUND,
  544. IDC_PROP_RECORDING, IDH_SNDVOL32_SELECT_SOUND,
  545. IDC_PROP_OTHER, IDH_SNDVOL32_SELECT_SOUND,
  546. IDC_PROP_OTHERLIST, IDH_SNDVOL32_SELECT_SOUND,
  547. IDC_PROP_TXT2, IDH_SNDVOL32_VOLCONTROL,
  548. IDC_PROP_VOLUMELIST, IDH_SNDVOL32_VOLCONTROL,
  549. 0, 0
  550. };
  551. switch (msg)
  552. {
  553. case WM_CONTEXTMENU:
  554. WinHelp((HWND)wparam, gszHelpFileName, HELP_CONTEXTMENU,
  555. (UINT_PTR)(LPSTR)aHelpIds);
  556. break;
  557. case WM_HELP:
  558. {
  559. LPHELPINFO lphi = (LPVOID) lparam;
  560. WinHelp (lphi->hItemHandle, gszHelpFileName, HELP_WM_HELP,
  561. (UINT_PTR) (LPSTR) aHelpIds);
  562. return TRUE;
  563. }
  564. case WM_INITDIALOG:
  565. HANDLE_WM_INITDIALOG(hwnd, wparam, lparam, Properties_OnInitDialog);
  566. return TRUE;
  567. case WM_COMMAND:
  568. HANDLE_WM_COMMAND(hwnd, wparam, lparam, Properties_OnCommand);
  569. break;
  570. case WM_CLOSE:
  571. EndDialog(hwnd, FALSE);
  572. break;
  573. case WM_DESTROY:
  574. {
  575. PPRIVPROP ppr = GETPROP(hwnd);
  576. if (ppr)
  577. {
  578. if (ppr->adp)
  579. {
  580. GlobalFreePtr(ppr->adp);
  581. ppr->adp = NULL;
  582. }
  583. REMOVEPROP(hwnd);
  584. }
  585. break;
  586. }
  587. case WM_NOTIFY:
  588. {
  589. NMHDR FAR* lpnm = (NMHDR FAR *)lparam;
  590. if ((LVN_ITEMCHANGED == lpnm->code) && hwnd)
  591. {
  592. HWND hwndLV = GetDlgItem (hwnd, IDC_PROP_VOLUMELIST);
  593. if (hwndLV)
  594. {
  595. int nItems = ListView_GetItemCount (hwndLV);
  596. int indx;
  597. for (indx = 0; indx < nItems; indx++)
  598. if (ListView_GetCheckState (hwndLV, indx))
  599. break;
  600. EnableOk (hwnd, nItems != indx);
  601. }
  602. }
  603. break;
  604. }
  605. }
  606. return FALSE;
  607. }
  608. BOOL Properties(
  609. PMIXUIDIALOG pmxud,
  610. HWND hwnd)
  611. {
  612. INT_PTR iret;
  613. PRIVPROP pr;
  614. ZeroMemory(&pr, sizeof(pr));
  615. pr.dwDestination = pmxud->iDest;
  616. pr.uDeviceID = pmxud->mxid;
  617. pr.fMixer = pmxud->dwFlags & MXUD_FLAGSF_MIXER;
  618. pr.dwStyle = pmxud->dwStyle;
  619. pr.pmxud = pmxud;
  620. iret = DialogBoxParam(pmxud->hInstance
  621. , MAKEINTRESOURCE(IDD_PROPERTIES)
  622. , hwnd
  623. , Properties_Proc
  624. , (LPARAM)(LPVOID)&pr );
  625. if (iret == TRUE)
  626. {
  627. pmxud->mxid = pr.uDeviceID;
  628. pmxud->iDest = pr.dwDestination;
  629. pmxud->dwFlags &= ~MXUD_FLAGSF_MIXER;
  630. pmxud->dwFlags |= (pr.fMixer)?MXUD_FLAGSF_MIXER:0L;
  631. pmxud->dwStyle = pr.dwStyle;
  632. }
  633. return (iret == -1) ? FALSE : TRUE;
  634. }