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 } 859