[SNDVOL32] In record mode, rename the 'Mute' autocheckbox to 'Select', turn it into...
[reactos.git] / base / applications / sndvol32 / dialog.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Sound Volume Control
4 * FILE: base/applications/sndvol32/dialog.c
5 * PROGRAMMERS: Johannes Anderwald
6 */
7
8 #include "sndvol32.h"
9
10
11 VOID
12 ConvertRect(LPRECT lpRect, UINT xBaseUnit, UINT yBaseUnit)
13 {
14 lpRect->left = MulDiv(lpRect->left, xBaseUnit, 4);
15 lpRect->right = MulDiv(lpRect->right, xBaseUnit, 4);
16 lpRect->top = MulDiv(lpRect->top, yBaseUnit, 8);
17 lpRect->bottom = MulDiv(lpRect->bottom, yBaseUnit, 8);
18 }
19
20 LPVOID
21 LoadDialogResource(
22 IN HMODULE hModule,
23 IN LPCWSTR ResourceName,
24 OUT LPDWORD ResourceLength)
25 {
26 HRSRC hSrc;
27 HGLOBAL hRes;
28 PVOID Result;
29
30 /* find resource */
31 hSrc = FindResourceW(hModule, ResourceName, (LPCWSTR)RT_DIALOG);
32
33 if (!hSrc)
34 {
35 /* failed to find resource */
36 return NULL;
37 }
38
39 /* now load the resource */
40 hRes = LoadResource(hAppInstance, hSrc);
41 if (!hRes)
42 {
43 /* failed to load resource */
44 return NULL;
45 }
46
47 /* now lock the resource */
48 Result = LockResource(hRes);
49
50 if (!Result)
51 {
52 /* failed to lock resource */
53 return NULL;
54 }
55
56 if (ResourceLength)
57 {
58 /* store output length */
59 *ResourceLength = SizeofResource(hAppInstance, hSrc);
60 }
61
62 /* done */
63 return Result;
64 }
65
66 LPWORD
67 AddDialogControl(
68 IN HWND hwndDialog,
69 OUT HWND *OutWnd,
70 IN LPRECT DialogOffset,
71 IN PDLGITEMTEMPLATE DialogItem,
72 IN DWORD DialogIdMultiplier,
73 IN HFONT hFont,
74 IN UINT xBaseUnit,
75 IN UINT yBaseUnit,
76 IN UINT MixerId)
77 {
78 RECT rect;
79 LPWORD Offset;
80 LPWSTR ClassName, WindowName;
81 WCHAR WindowIdBuf[sizeof("#65535")];
82 HWND hwnd;
83 DWORD wID;
84 INT nSteps, i;
85
86 /* initialize client rectangle */
87 rect.left = DialogItem->x;
88 rect.top = DialogItem->y;
89 rect.right = DialogItem->x + DialogItem->cx;
90 rect.bottom = DialogItem->y + DialogItem->cy;
91
92 /* Convert Dialog units to pixes */
93 ConvertRect(&rect, xBaseUnit, yBaseUnit);
94
95 rect.left += DialogOffset->left;
96 rect.right += DialogOffset->left;
97 rect.top += DialogOffset->top;
98 rect.bottom += DialogOffset->top;
99
100 /* move offset after dialog item */
101 Offset = (LPWORD)(DialogItem + 1);
102
103 if (*Offset == 0xFFFF)
104 {
105 /* class is encoded as type */
106 Offset++;
107
108 /* get control type */
109 switch(*Offset)
110 {
111 case 0x80:
112 ClassName = L"button";
113 break ;
114 case 0x82:
115 ClassName = L"static";
116 break;
117 default:
118 /* FIXME */
119 assert(0);
120 ClassName = NULL;
121 }
122 Offset++;
123 }
124 else
125 {
126 /* class name is encoded as string */
127 ClassName = (LPWSTR)(Offset);
128
129 /* move offset to the end of class string */
130 Offset += wcslen(ClassName) + 1;
131 }
132
133 if (*Offset == 0xFFFF)
134 {
135 /* Window name is encoded as ordinal */
136 Offset++;
137 wsprintf(WindowIdBuf, L"#%u", (DWORD)*Offset);
138 WindowName = WindowIdBuf;
139 Offset++;
140 }
141 else
142 {
143 /* window name is encoded as string */
144 WindowName = (LPWSTR)(Offset);
145
146 /* move offset to the end of class string */
147 Offset += wcslen(WindowName) + 1;
148 }
149
150 if (DialogItem->id == MAXWORD)
151 {
152 /* id is not important */
153 wID = DialogItem->id;
154 }
155 else
156 {
157 /* calculate id */
158 wID = DialogItem->id * (DialogIdMultiplier + 1);
159
160 }
161
162 /* now create the window */
163 hwnd = CreateWindowExW(DialogItem->dwExtendedStyle,
164 ClassName,
165 WindowName,
166 DialogItem->style,
167 rect.left,
168 rect.top,
169 rect.right - rect.left,
170 rect.bottom - rect.top,
171 hwndDialog,
172 UlongToPtr(wID),
173 hAppInstance,
174 NULL);
175
176 /* sanity check */
177 assert(hwnd);
178
179 /* store window */
180 *OutWnd = hwnd;
181
182 /* check if this the track bar */
183 if (!wcsicmp(ClassName, L"msctls_trackbar32"))
184 {
185 if (DialogItem->style & TBS_VERT)
186 {
187 /* Vertical trackbar: Volume */
188
189 /* Disable the volume trackbar by default */
190 EnableWindow(hwnd, FALSE);
191
192 /* set up range */
193 SendMessage(hwnd, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(VOLUME_MIN, VOLUME_MAX));
194
195 /* set up page size */
196 SendMessage(hwnd, TBM_SETPAGESIZE, 0, (LPARAM)VOLUME_PAGE_SIZE);
197
198 /* set position */
199 SendMessage(hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)0);
200
201 /* Calculate and set ticks */
202 nSteps = (VOLUME_MAX / (VOLUME_TICKS + 1));
203 if (VOLUME_MAX % (VOLUME_TICKS + 1) != 0)
204 nSteps++;
205 for (i = nSteps; i < VOLUME_MAX; i += nSteps)
206 SendMessage(hwnd, TBM_SETTIC, 0, (LPARAM)i);
207 }
208 else
209 {
210 /* Horizontal trackbar: Balance */
211
212 /* Disable the balance trackbar by default */
213 EnableWindow(hwnd, FALSE);
214
215 /* set up range */
216 SendMessage(hwnd, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, BALANCE_STEPS));
217
218 /* set up page size */
219 SendMessage(hwnd, TBM_SETPAGESIZE, 0, (LPARAM)BALANCE_PAGE_SIZE);
220
221 /* set position */
222 SendMessage(hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)BALANCE_STEPS / 2);
223
224 /* Calculate and set ticks */
225 nSteps = (BALANCE_STEPS / (BALANCE_TICKS + 1));
226 if (BALANCE_STEPS % (BALANCE_TICKS + 1) != 0)
227 nSteps++;
228 for (i = nSteps; i < BALANCE_STEPS; i += nSteps)
229 SendMessage(hwnd, TBM_SETTIC, 0, (LPARAM)i);
230 }
231 }
232 else if (!wcsicmp(ClassName, L"static"))
233 {
234 /* Set font */
235 SendMessageW(hwnd, WM_SETFONT, (WPARAM)hFont, TRUE);
236 }
237 else if (!wcsicmp(ClassName, L"button"))
238 {
239 if (DialogItem->id == IDC_LINE_SWITCH)
240 {
241 if (MixerId == PLAY_MIXER)
242 {
243 /* Disable checkboxes by default, if we are in play mode */
244 EnableWindow(hwnd, FALSE);
245 }
246 }
247 else if (DialogItem->id == IDC_LINE_ADVANCED)
248 {
249 ShowWindow(hwnd, SW_HIDE);
250 }
251
252 /* Set font */
253 SendMessageW(hwnd, WM_SETFONT, (WPARAM)hFont, TRUE);
254 }
255
256
257 /* check if there is additional data */
258 if (*Offset == 0)
259 {
260 /* no additional data */
261 Offset++;
262 }
263 else
264 {
265 /* FIXME: Determine whether this should be "Offset += 1 + *Offset" to explicitly skip the data count too. */
266 /* skip past additional data */
267 Offset += *Offset;
268 }
269
270 /* make sure next template is word-aligned */
271 Offset = (LPWORD)(((ULONG_PTR)Offset + 3) & ~3);
272
273 /* done */
274 return Offset;
275 }
276
277 VOID
278 LoadDialogControls(
279 IN PMIXER_WINDOW MixerWindow,
280 LPRECT DialogOffset,
281 WORD ItemCount,
282 PDLGITEMTEMPLATE DialogItem,
283 DWORD DialogIdMultiplier,
284 UINT xBaseUnit,
285 UINT yBaseUnit)
286 {
287 LPWORD Offset;
288 WORD Index;
289
290 /* sanity check */
291 assert(ItemCount);
292
293 if (MixerWindow->Window)
294 MixerWindow->Window = (HWND*)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MixerWindow->Window, (MixerWindow->WindowCount + ItemCount) * sizeof(HWND));
295 else
296 MixerWindow->Window = (HWND*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ItemCount * sizeof(HWND));
297 if (!MixerWindow->Window)
298 {
299 /* no memory */
300 return;
301 }
302
303 /* enumerate now all controls */
304 for (Index = 0; Index < ItemCount; Index++)
305 {
306 /* add controls */
307 Offset = AddDialogControl(MixerWindow->hWnd,
308 &MixerWindow->Window[MixerWindow->WindowCount],
309 DialogOffset,
310 DialogItem,
311 DialogIdMultiplier,
312 MixerWindow->hFont,
313 xBaseUnit,
314 yBaseUnit,
315 MixerWindow->MixerId);
316
317 /* sanity check */
318 assert(Offset);
319
320 /* move dialog item to new offset */
321 DialogItem =(PDLGITEMTEMPLATE)Offset;
322
323 /* increment window count */
324 MixerWindow->WindowCount++;
325 }
326 }
327
328 VOID
329 LoadDialog(
330 IN HMODULE hModule,
331 IN PMIXER_WINDOW MixerWindow,
332 IN LPCWSTR DialogResId,
333 IN DWORD Index)
334 {
335 LPDLGTEMPLATE DlgTemplate;
336 PDLGITEMTEMPLATE DlgItem;
337 RECT dialogRect;
338 LPWORD Offset;
339 WORD FontSize;
340 WCHAR FontName[100];
341 WORD Length;
342 int width;
343
344 DWORD units = GetDialogBaseUnits();
345 UINT xBaseUnit = LOWORD(units);
346 UINT yBaseUnit = HIWORD(units);
347
348 /* first load the dialog resource */
349 DlgTemplate = (LPDLGTEMPLATE)LoadDialogResource(hModule, DialogResId, NULL);
350 if (!DlgTemplate)
351 {
352 /* failed to load resource */
353 return;
354 }
355
356 /* Now walk past the dialog header */
357 Offset = (LPWORD)(DlgTemplate + 1);
358
359 /* FIXME: support menu */
360 assert(*Offset == 0);
361 Offset++;
362
363 /* FIXME: support classes */
364 assert(*Offset == 0);
365 Offset++;
366
367 /* FIXME: support titles */
368 assert(*Offset == 0);
369 Offset++;
370
371 /* get font size */
372 FontSize = *Offset;
373 Offset++;
374
375 /* calculate font length */
376 Length = wcslen((LPWSTR)Offset) + 1;
377 assert(Length < (sizeof(FontName) / sizeof(WCHAR)));
378
379 /* copy font */
380 wcscpy(FontName, (LPWSTR)Offset);
381
382 if (DlgTemplate->style & DS_SETFONT)
383 {
384 HDC hDC;
385
386 hDC = GetDC(0);
387
388 if (!MixerWindow->hFont)
389 {
390 int pixels = MulDiv(FontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
391 MixerWindow->hFont = CreateFontW(-pixels, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, FontName);
392 }
393
394 if (MixerWindow->hFont)
395 {
396 SIZE charSize;
397 HFONT hOldFont;
398
399 hOldFont = SelectObject(hDC, MixerWindow->hFont);
400 charSize.cx = GdiGetCharDimensions(hDC, NULL, &charSize.cy);
401 if (charSize.cx)
402 {
403 xBaseUnit = charSize.cx;
404 yBaseUnit = charSize.cy;
405 }
406 SelectObject(hDC, hOldFont);
407
408 MixerWindow->baseUnit.cx = charSize.cx;
409 MixerWindow->baseUnit.cy = charSize.cy;
410 }
411 }
412
413 // assert(MixerWindow->hFont);
414
415 /* move offset after font name */
416 Offset += Length;
417
418 /* offset is now at first dialog item control */
419 DlgItem = (PDLGITEMTEMPLATE)Offset;
420
421 dialogRect.left = 0;
422 dialogRect.right = DlgTemplate->cx;
423 dialogRect.top = 0;
424 dialogRect.bottom = DlgTemplate->cy;
425
426 ConvertRect(&dialogRect, xBaseUnit, yBaseUnit);
427
428 width = dialogRect.right - dialogRect.left;
429
430 dialogRect.left += MixerWindow->rect.right;
431 dialogRect.right += MixerWindow->rect.right;
432 dialogRect.top += MixerWindow->rect.top;
433 dialogRect.bottom += MixerWindow->rect.top;
434
435 MixerWindow->rect.right += width;
436 if ((dialogRect.bottom - dialogRect.top) > (MixerWindow->rect.bottom - MixerWindow->rect.top))
437 MixerWindow->rect.bottom = MixerWindow->rect.top + dialogRect.bottom - dialogRect.top;
438
439 /* now add the controls */
440 LoadDialogControls(MixerWindow, &dialogRect, DlgTemplate->cdit, DlgItem, Index, xBaseUnit, yBaseUnit);
441 }
442
443 BOOL
444 CALLBACK
445 EnumConnectionsCallback(
446 PSND_MIXER Mixer,
447 DWORD LineID,
448 LPMIXERLINE Line,
449 PVOID Context)
450 {
451 WCHAR LineName[MIXER_LONG_NAME_CHARS];
452 DWORD Flags;
453 DWORD wID;
454 UINT ControlCount = 0, Index;
455 LPMIXERCONTROL Control = NULL;
456 HWND hDlgCtrl;
457 PMIXERCONTROLDETAILS_UNSIGNED pVolumeDetails = NULL;
458 PPREFERENCES_CONTEXT PrefContext = (PPREFERENCES_CONTEXT)Context;
459
460 if (Line->cControls == 0)
461 return TRUE;
462
463 /* get line name */
464 if (SndMixerGetLineName(PrefContext->MixerWindow->Mixer, PrefContext->SelectedLine, LineName, MIXER_LONG_NAME_CHARS, TRUE) == -1)
465 {
466 /* failed to get line name */
467 LineName[0] = L'\0';
468 }
469
470 pVolumeDetails = HeapAlloc(GetProcessHeap(),
471 0,
472 Line->cChannels * sizeof(MIXERCONTROLDETAILS_UNSIGNED));
473 if (pVolumeDetails == NULL)
474 goto done;
475
476 /* check if line is found in registry settings */
477 if (ReadLineConfig(PrefContext->DeviceName,
478 LineName,
479 Line->szName,
480 &Flags))
481 {
482 /* is it selected */
483 if (Flags != 0x4)
484 {
485 int dlgId;
486
487 if ((Line->dwComponentType == MIXERLINE_COMPONENTTYPE_DST_SPEAKERS) ||
488 (Line->dwComponentType == MIXERLINE_COMPONENTTYPE_DST_HEADPHONES))
489 dlgId = (PrefContext->MixerWindow->Mode == SMALL_MODE) ? IDD_SMALL_MASTER : IDD_NORMAL_MASTER;
490 else
491 dlgId = (PrefContext->MixerWindow->Mode == SMALL_MODE) ? IDD_SMALL_LINE : IDD_NORMAL_LINE;
492
493 /* load dialog resource */
494 LoadDialog(hAppInstance, PrefContext->MixerWindow, MAKEINTRESOURCE(dlgId), PrefContext->MixerWindow->DialogCount);
495
496 /* get id */
497 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_NAME;
498
499 /* set line name */
500 SetDlgItemTextW(PrefContext->MixerWindow->hWnd, wID, Line->szName);
501
502 /* query controls */
503 if (SndMixerQueryControls(Mixer, &ControlCount, Line, &Control) != FALSE)
504 {
505 /* now go through all controls and update their states */
506 for (Index = 0; Index < Line->cControls; Index++)
507 {
508 if (Control[Index].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
509 {
510 MIXERCONTROLDETAILS_BOOLEAN Details;
511
512 /* get volume control details */
513 if (SndMixerGetVolumeControlDetails(Mixer, Control[Index].dwControlID, 1, sizeof(MIXERCONTROLDETAILS_BOOLEAN), (LPVOID)&Details) != -1)
514 {
515 /* update dialog control */
516 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_SWITCH;
517
518 /* get dialog control */
519 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
520
521 if (hDlgCtrl != NULL)
522 {
523 /* Enable the 'Mute' checkbox, if we are in play mode */
524 if (Mixer->MixerId == PLAY_MIXER)
525 EnableWindow(hDlgCtrl, TRUE);
526
527 /* check state */
528 if (SendMessageW(hDlgCtrl, BM_GETCHECK, 0, 0) != Details.fValue)
529 {
530 /* update control state */
531 SendMessageW(hDlgCtrl, BM_SETCHECK, (WPARAM)Details.fValue, 0);
532 }
533 }
534 }
535 }
536 else if (Control[Index].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
537 {
538 /* get volume control details */
539 if (SndMixerGetVolumeControlDetails(Mixer, Control[Index].dwControlID, Line->cChannels, sizeof(MIXERCONTROLDETAILS_UNSIGNED), (LPVOID)pVolumeDetails) != -1)
540 {
541 /* update dialog control */
542 DWORD volumePosition, volumeStep, maxVolume, i;
543 DWORD balancePosition, balanceStep;
544
545 volumeStep = (Control[Index].Bounds.dwMaximum - Control[Index].Bounds.dwMinimum) / (VOLUME_MAX - VOLUME_MIN);
546
547 maxVolume = 0;
548 for (i = 0; i < Line->cChannels; i++)
549 {
550 if (pVolumeDetails[i].dwValue > maxVolume)
551 maxVolume = pVolumeDetails[i].dwValue;
552 }
553
554 volumePosition = (maxVolume - Control[Index].Bounds.dwMinimum) / volumeStep;
555
556 if (Line->cChannels == 1)
557 {
558 balancePosition = BALANCE_CENTER;
559 }
560 else if (Line->cChannels == 2)
561 {
562 if (pVolumeDetails[0].dwValue == pVolumeDetails[1].dwValue)
563 {
564 balancePosition = BALANCE_CENTER;
565 }
566 else if (pVolumeDetails[0].dwValue == Control[Index].Bounds.dwMinimum)
567 {
568 balancePosition = BALANCE_RIGHT;
569 }
570 else if (pVolumeDetails[1].dwValue == Control[Index].Bounds.dwMinimum)
571 {
572 balancePosition = BALANCE_LEFT;
573 }
574 else
575 {
576 balanceStep = (maxVolume - Control[Index].Bounds.dwMinimum) / (BALANCE_STEPS / 2);
577
578 if (pVolumeDetails[0].dwValue < pVolumeDetails[1].dwValue)
579 {
580 balancePosition = (pVolumeDetails[0].dwValue - Control[Index].Bounds.dwMinimum) / balanceStep;
581 balancePosition = BALANCE_RIGHT - balancePosition;
582 }
583 else if (pVolumeDetails[1].dwValue < pVolumeDetails[0].dwValue)
584 {
585 balancePosition = (pVolumeDetails[1].dwValue - Control[Index].Bounds.dwMinimum) / balanceStep;
586 balancePosition = BALANCE_LEFT + balancePosition;
587 }
588 }
589 }
590
591 /* Set the volume trackbar */
592 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_SLIDER_VERT;
593
594 /* get dialog control */
595 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
596
597 if (hDlgCtrl != NULL)
598 {
599 /* check state */
600 LRESULT OldPosition = SendMessageW(hDlgCtrl, TBM_GETPOS, 0, 0);
601
602 /* Enable the volume trackbar */
603 EnableWindow(hDlgCtrl, TRUE);
604
605 if (OldPosition != (VOLUME_MAX - volumePosition))
606 {
607 /* update control state */
608 SendMessageW(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, VOLUME_MAX - volumePosition);
609 }
610 }
611
612 if (Line->cChannels == 2)
613 {
614 /* Set the balance trackbar */
615 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_SLIDER_HORZ;
616
617 /* get dialog control */
618 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
619
620 if (hDlgCtrl != NULL)
621 {
622 /* check state */
623 LRESULT OldPosition = SendMessageW(hDlgCtrl, TBM_GETPOS, 0, 0);
624
625 /* Enable the balance trackbar */
626 EnableWindow(hDlgCtrl, TRUE);
627
628 if (OldPosition != balancePosition)
629 {
630 /* update control state */
631 SendMessageW(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, balancePosition);
632 }
633 }
634 }
635 }
636 }
637 else
638 {
639 if (PrefContext->MixerWindow->Mode == NORMAL_MODE)
640 {
641 PrefContext->MixerWindow->bHasExtendedControls = TRUE;
642
643 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_ADVANCED;
644
645 /* get dialog control */
646 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
647 if (hDlgCtrl != NULL)
648 {
649 ShowWindow(hDlgCtrl,
650 PrefContext->MixerWindow->bShowExtendedControls ? SW_SHOWNORMAL : SW_HIDE);
651 }
652 }
653 }
654 }
655
656 /* free controls */
657 HeapFree(GetProcessHeap(), 0, Control);
658 }
659
660 /* increment dialog count */
661 PrefContext->MixerWindow->DialogCount++;
662 }
663 }
664
665 done:
666 /* Free the volume details */
667 if (pVolumeDetails)
668 HeapFree(GetProcessHeap(), 0, pVolumeDetails);
669
670 return TRUE;
671 }
672
673 VOID
674 LoadDialogCtrls(
675 PPREFERENCES_CONTEXT PrefContext)
676 {
677 WCHAR szBuffer[64];
678 HWND hDlgCtrl;
679 RECT statusRect;
680 UINT i;
681 LONG dy;
682
683 /* set dialog count to zero */
684 PrefContext->MixerWindow->DialogCount = 0;
685 PrefContext->MixerWindow->bHasExtendedControls = FALSE;
686 SetRectEmpty(&PrefContext->MixerWindow->rect);
687
688 /* enumerate controls */
689 SndMixerEnumConnections(PrefContext->MixerWindow->Mixer, PrefContext->SelectedLine, EnumConnectionsCallback, (PVOID)PrefContext);
690
691 /* Update the 'Advanced Controls' menu item */
692 EnableMenuItem(GetMenu(PrefContext->MixerWindow->hWnd),
693 IDM_ADVANCED_CONTROLS,
694 MF_BYCOMMAND | (PrefContext->MixerWindow->bHasExtendedControls ? MF_ENABLED : MF_GRAYED));
695
696 /* Add some height for the status bar */
697 if (PrefContext->MixerWindow->hStatusBar)
698 {
699 GetWindowRect(PrefContext->MixerWindow->hStatusBar, &statusRect);
700 PrefContext->MixerWindow->rect.bottom += (statusRect.bottom - statusRect.top);
701 }
702
703 /* Add height of the 'Advanced' button */
704 dy = MulDiv(ADVANCED_BUTTON_HEIGHT, PrefContext->MixerWindow->baseUnit.cy, 8);
705 if (PrefContext->MixerWindow->bShowExtendedControls && PrefContext->MixerWindow->bHasExtendedControls)
706 PrefContext->MixerWindow->rect.bottom += dy;
707
708 /* now move the window */
709 AdjustWindowRect(&PrefContext->MixerWindow->rect, WS_DLGFRAME | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, TRUE);
710 SetWindowPos(PrefContext->MixerWindow->hWnd, HWND_TOP, PrefContext->MixerWindow->rect.left, PrefContext->MixerWindow->rect.top, PrefContext->MixerWindow->rect.right - PrefContext->MixerWindow->rect.left, PrefContext->MixerWindow->rect.bottom - PrefContext->MixerWindow->rect.top, SWP_NOMOVE | SWP_NOZORDER);
711
712 /* Move the status bar */
713 if (PrefContext->MixerWindow->hStatusBar)
714 {
715 SetWindowPos(PrefContext->MixerWindow->hStatusBar,
716 HWND_TOP,
717 statusRect.left,
718 PrefContext->MixerWindow->rect.bottom - (statusRect.bottom - statusRect.top),
719 PrefContext->MixerWindow->rect.right - PrefContext->MixerWindow->rect.left,
720 statusRect.bottom - statusRect.top,
721 SWP_NOZORDER);
722 }
723
724 if (PrefContext->MixerWindow->MixerId == RECORD_MIXER)
725 LoadStringW(hAppInstance, IDS_SELECT, szBuffer, ARRAYSIZE(szBuffer));
726
727 for (i = 0; i < PrefContext->MixerWindow->DialogCount; i++)
728 {
729 if (PrefContext->MixerWindow->MixerId == RECORD_MIXER)
730 {
731 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, (i + 1) * IDC_LINE_SWITCH);
732
733 /* Turn the autocheckbox into a checkbox */
734 SetWindowLongPtr(hDlgCtrl, GWL_STYLE, (GetWindowLongPtr(hDlgCtrl, GWL_STYLE) & ~BS_AUTOCHECKBOX) | BS_CHECKBOX);
735
736 /* Change text from 'Mute' to 'Select' */
737 SetWindowTextW(hDlgCtrl, szBuffer);
738 }
739
740 /* Resize the vertical line separator */
741 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, (i + 1) * IDC_LINE_SEP);
742 if (hDlgCtrl != NULL)
743 {
744 GetWindowRect(hDlgCtrl, &statusRect);
745 if (PrefContext->MixerWindow->bShowExtendedControls && PrefContext->MixerWindow->bHasExtendedControls)
746 statusRect.bottom += dy;
747
748 SetWindowPos(hDlgCtrl,
749 HWND_TOP,
750 0,
751 0,
752 statusRect.right - statusRect.left,
753 statusRect.bottom - statusRect.top,
754 SWP_NOMOVE | SWP_NOZORDER);
755 }
756 }
757
758 /* Hide the last line separator */
759 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, IDC_LINE_SEP * PrefContext->MixerWindow->DialogCount);
760 if (hDlgCtrl != NULL)
761 {
762 ShowWindow(hDlgCtrl, SW_HIDE);
763 }
764 }
765
766 VOID
767 UpdateDialogLineSwitchControl(
768 PPREFERENCES_CONTEXT PrefContext,
769 LPMIXERLINE Line,
770 LONG fValue)
771 {
772 DWORD Index;
773 DWORD wID;
774 HWND hDlgCtrl;
775 WCHAR LineName[MIXER_LONG_NAME_CHARS];
776
777 /* find the index of this line */
778 for (Index = 0; Index < PrefContext->MixerWindow->DialogCount; Index++)
779 {
780 /* get id */
781 wID = (Index + 1) * IDC_LINE_NAME;
782
783 if (GetDlgItemText(PrefContext->MixerWindow->hWnd, wID, LineName, MIXER_LONG_NAME_CHARS) == 0)
784 {
785 /* failed to retrieve id */
786 continue;
787 }
788
789 /* check if the line name matches */
790 if (!wcsicmp(LineName, Line->szName))
791 {
792 /* found matching line name */
793 wID = (Index + 1) * IDC_LINE_SWITCH;
794
795 /* get dialog control */
796 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
797
798 if (hDlgCtrl != NULL)
799 {
800 /* check state */
801 if (SendMessageW(hDlgCtrl, BM_GETCHECK, 0, 0) != fValue)
802 {
803 /* update control state */
804 SendMessageW(hDlgCtrl, BM_SETCHECK, (WPARAM)fValue, 0);
805 }
806 }
807 break;
808 }
809 }
810 }
811
812 VOID
813 UpdateDialogLineSliderControl(
814 PPREFERENCES_CONTEXT PrefContext,
815 LPMIXERLINE Line,
816 DWORD dwDialogID,
817 DWORD Position)
818 {
819 DWORD Index;
820 DWORD wID;
821 HWND hDlgCtrl;
822 WCHAR LineName[MIXER_LONG_NAME_CHARS];
823
824 /* find the index of this line */
825 for (Index = 0; Index < PrefContext->MixerWindow->DialogCount; Index++)
826 {
827 /* get id */
828 wID = (Index + 1) * IDC_LINE_NAME;
829
830 if (GetDlgItemText(PrefContext->MixerWindow->hWnd, wID, LineName, MIXER_LONG_NAME_CHARS) == 0)
831 {
832 /* failed to retrieve id */
833 continue;
834 }
835
836 /* check if the line name matches */
837 if (!wcsicmp(LineName, Line->szName))
838 {
839 /* found matching line name */
840 wID = (Index + 1) * dwDialogID;
841
842 /* get dialog control */
843 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID);
844
845 if (hDlgCtrl != NULL)
846 {
847 /* check state */
848 LRESULT OldPosition = SendMessageW(hDlgCtrl, TBM_GETPOS, 0, 0);
849 if (OldPosition != Position)
850 {
851 /* update control state */
852 SendMessageW(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, Position);
853 }
854 }
855 break;
856 }
857 }
858 }