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 ReleaseDC(NULL, hDC); 413 } 414 415 // assert(MixerWindow->hFont); 416 417 /* move offset after font name */ 418 Offset += Length; 419 420 /* offset is now at first dialog item control */ 421 DlgItem = (PDLGITEMTEMPLATE)Offset; 422 423 dialogRect.left = 0; 424 dialogRect.right = DlgTemplate->cx; 425 dialogRect.top = 0; 426 dialogRect.bottom = DlgTemplate->cy; 427 428 ConvertRect(&dialogRect, xBaseUnit, yBaseUnit); 429 430 width = dialogRect.right - dialogRect.left; 431 432 dialogRect.left += MixerWindow->rect.right; 433 dialogRect.right += MixerWindow->rect.right; 434 dialogRect.top += MixerWindow->rect.top; 435 dialogRect.bottom += MixerWindow->rect.top; 436 437 MixerWindow->rect.right += width; 438 if ((dialogRect.bottom - dialogRect.top) > (MixerWindow->rect.bottom - MixerWindow->rect.top)) 439 MixerWindow->rect.bottom = MixerWindow->rect.top + dialogRect.bottom - dialogRect.top; 440 441 /* now add the controls */ 442 LoadDialogControls(MixerWindow, &dialogRect, DlgTemplate->cdit, DlgItem, Index, xBaseUnit, yBaseUnit); 443 } 444 445 BOOL 446 CALLBACK 447 EnumConnectionsCallback( 448 PSND_MIXER Mixer, 449 DWORD LineID, 450 LPMIXERLINE Line, 451 PVOID Context) 452 { 453 WCHAR LineName[MIXER_LONG_NAME_CHARS]; 454 DWORD Flags; 455 DWORD wID; 456 UINT ControlCount = 0, Index; 457 LPMIXERCONTROL Control = NULL; 458 HWND hDlgCtrl; 459 PMIXERCONTROLDETAILS_UNSIGNED pVolumeDetails = NULL; 460 PPREFERENCES_CONTEXT PrefContext = (PPREFERENCES_CONTEXT)Context; 461 462 if (Line->cControls == 0) 463 return TRUE; 464 465 /* get line name */ 466 if (SndMixerGetLineName(PrefContext->MixerWindow->Mixer, PrefContext->SelectedLine, LineName, MIXER_LONG_NAME_CHARS, TRUE) == -1) 467 { 468 /* failed to get line name */ 469 LineName[0] = L'\0'; 470 } 471 472 pVolumeDetails = HeapAlloc(GetProcessHeap(), 473 0, 474 Line->cChannels * sizeof(MIXERCONTROLDETAILS_UNSIGNED)); 475 if (pVolumeDetails == NULL) 476 goto done; 477 478 /* check if line is found in registry settings */ 479 if (ReadLineConfig(PrefContext->DeviceName, 480 LineName, 481 Line->szName, 482 &Flags)) 483 { 484 /* is it selected */ 485 if (Flags != 0x4) 486 { 487 int dlgId; 488 489 if ((Line->dwComponentType == MIXERLINE_COMPONENTTYPE_DST_SPEAKERS) || 490 (Line->dwComponentType == MIXERLINE_COMPONENTTYPE_DST_HEADPHONES)) 491 dlgId = (PrefContext->MixerWindow->Mode == SMALL_MODE) ? IDD_SMALL_MASTER : IDD_NORMAL_MASTER; 492 else 493 dlgId = (PrefContext->MixerWindow->Mode == SMALL_MODE) ? IDD_SMALL_LINE : IDD_NORMAL_LINE; 494 495 /* load dialog resource */ 496 LoadDialog(hAppInstance, PrefContext->MixerWindow, MAKEINTRESOURCE(dlgId), PrefContext->MixerWindow->DialogCount); 497 498 /* get id */ 499 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_NAME; 500 501 /* set line name */ 502 SetDlgItemTextW(PrefContext->MixerWindow->hWnd, wID, Line->szName); 503 504 /* query controls */ 505 if (SndMixerQueryControls(Mixer, &ControlCount, Line, &Control) != FALSE) 506 { 507 /* now go through all controls and update their states */ 508 for (Index = 0; Index < Line->cControls; Index++) 509 { 510 if (Control[Index].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) 511 { 512 MIXERCONTROLDETAILS_BOOLEAN Details; 513 514 /* get volume control details */ 515 if (SndMixerGetVolumeControlDetails(Mixer, Control[Index].dwControlID, 1, sizeof(MIXERCONTROLDETAILS_BOOLEAN), (LPVOID)&Details) != -1) 516 { 517 /* update dialog control */ 518 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_SWITCH; 519 520 /* get dialog control */ 521 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID); 522 523 if (hDlgCtrl != NULL) 524 { 525 /* Enable the 'Mute' checkbox, if we are in play mode */ 526 if (Mixer->MixerId == PLAY_MIXER) 527 EnableWindow(hDlgCtrl, TRUE); 528 529 /* check state */ 530 if (SendMessageW(hDlgCtrl, BM_GETCHECK, 0, 0) != Details.fValue) 531 { 532 /* update control state */ 533 SendMessageW(hDlgCtrl, BM_SETCHECK, (WPARAM)Details.fValue, 0); 534 } 535 } 536 } 537 } 538 else if (Control[Index].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) 539 { 540 /* get volume control details */ 541 if (SndMixerGetVolumeControlDetails(Mixer, Control[Index].dwControlID, Line->cChannels, sizeof(MIXERCONTROLDETAILS_UNSIGNED), (LPVOID)pVolumeDetails) != -1) 542 { 543 /* update dialog control */ 544 DWORD volumePosition, volumeStep, maxVolume, i; 545 DWORD balancePosition, balanceStep; 546 547 volumeStep = (Control[Index].Bounds.dwMaximum - Control[Index].Bounds.dwMinimum) / (VOLUME_MAX - VOLUME_MIN); 548 549 maxVolume = 0; 550 for (i = 0; i < Line->cChannels; i++) 551 { 552 if (pVolumeDetails[i].dwValue > maxVolume) 553 maxVolume = pVolumeDetails[i].dwValue; 554 } 555 556 volumePosition = (maxVolume - Control[Index].Bounds.dwMinimum) / volumeStep; 557 558 if (Line->cChannels == 1) 559 { 560 balancePosition = BALANCE_CENTER; 561 } 562 else if (Line->cChannels == 2) 563 { 564 if (pVolumeDetails[0].dwValue == pVolumeDetails[1].dwValue) 565 { 566 balancePosition = BALANCE_CENTER; 567 } 568 else if (pVolumeDetails[0].dwValue == Control[Index].Bounds.dwMinimum) 569 { 570 balancePosition = BALANCE_RIGHT; 571 } 572 else if (pVolumeDetails[1].dwValue == Control[Index].Bounds.dwMinimum) 573 { 574 balancePosition = BALANCE_LEFT; 575 } 576 else 577 { 578 balanceStep = (maxVolume - Control[Index].Bounds.dwMinimum) / (BALANCE_STEPS / 2); 579 580 if (pVolumeDetails[0].dwValue < pVolumeDetails[1].dwValue) 581 { 582 balancePosition = (pVolumeDetails[0].dwValue - Control[Index].Bounds.dwMinimum) / balanceStep; 583 balancePosition = BALANCE_RIGHT - balancePosition; 584 } 585 else if (pVolumeDetails[1].dwValue < pVolumeDetails[0].dwValue) 586 { 587 balancePosition = (pVolumeDetails[1].dwValue - Control[Index].Bounds.dwMinimum) / balanceStep; 588 balancePosition = BALANCE_LEFT + balancePosition; 589 } 590 } 591 } 592 593 /* Set the volume trackbar */ 594 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_SLIDER_VERT; 595 596 /* get dialog control */ 597 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID); 598 599 if (hDlgCtrl != NULL) 600 { 601 /* check state */ 602 LRESULT OldPosition = SendMessageW(hDlgCtrl, TBM_GETPOS, 0, 0); 603 604 /* Enable the volume trackbar */ 605 EnableWindow(hDlgCtrl, TRUE); 606 607 if (OldPosition != (VOLUME_MAX - volumePosition)) 608 { 609 /* update control state */ 610 SendMessageW(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, VOLUME_MAX - volumePosition); 611 } 612 } 613 614 if (Line->cChannels == 2) 615 { 616 /* Set the balance trackbar */ 617 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_SLIDER_HORZ; 618 619 /* get dialog control */ 620 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID); 621 622 if (hDlgCtrl != NULL) 623 { 624 /* check state */ 625 LRESULT OldPosition = SendMessageW(hDlgCtrl, TBM_GETPOS, 0, 0); 626 627 /* Enable the balance trackbar */ 628 EnableWindow(hDlgCtrl, TRUE); 629 630 if (OldPosition != balancePosition) 631 { 632 /* update control state */ 633 SendMessageW(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, balancePosition); 634 } 635 } 636 } 637 } 638 } 639 else 640 { 641 if (PrefContext->MixerWindow->Mode == NORMAL_MODE) 642 { 643 PrefContext->MixerWindow->bHasExtendedControls = TRUE; 644 645 wID = (PrefContext->MixerWindow->DialogCount + 1) * IDC_LINE_ADVANCED; 646 647 /* get dialog control */ 648 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID); 649 if (hDlgCtrl != NULL) 650 { 651 ShowWindow(hDlgCtrl, 652 PrefContext->MixerWindow->bShowExtendedControls ? SW_SHOWNORMAL : SW_HIDE); 653 } 654 } 655 } 656 } 657 658 /* free controls */ 659 HeapFree(GetProcessHeap(), 0, Control); 660 } 661 662 /* increment dialog count */ 663 PrefContext->MixerWindow->DialogCount++; 664 } 665 } 666 667 done: 668 /* Free the volume details */ 669 if (pVolumeDetails) 670 HeapFree(GetProcessHeap(), 0, pVolumeDetails); 671 672 return TRUE; 673 } 674 675 VOID 676 LoadDialogCtrls( 677 PPREFERENCES_CONTEXT PrefContext) 678 { 679 WCHAR szBuffer[64]; 680 HWND hDlgCtrl; 681 RECT statusRect; 682 UINT i; 683 LONG dy; 684 685 /* set dialog count to zero */ 686 PrefContext->MixerWindow->DialogCount = 0; 687 PrefContext->MixerWindow->bHasExtendedControls = FALSE; 688 SetRectEmpty(&PrefContext->MixerWindow->rect); 689 690 /* enumerate controls */ 691 SndMixerEnumConnections(PrefContext->MixerWindow->Mixer, PrefContext->SelectedLine, EnumConnectionsCallback, (PVOID)PrefContext); 692 693 /* Update the 'Advanced Controls' menu item */ 694 EnableMenuItem(GetMenu(PrefContext->MixerWindow->hWnd), 695 IDM_ADVANCED_CONTROLS, 696 MF_BYCOMMAND | (PrefContext->MixerWindow->bHasExtendedControls ? MF_ENABLED : MF_GRAYED)); 697 698 /* Add some height for the status bar */ 699 if (PrefContext->MixerWindow->hStatusBar) 700 { 701 GetWindowRect(PrefContext->MixerWindow->hStatusBar, &statusRect); 702 PrefContext->MixerWindow->rect.bottom += (statusRect.bottom - statusRect.top); 703 } 704 705 /* Add height of the 'Advanced' button */ 706 dy = MulDiv(ADVANCED_BUTTON_HEIGHT, PrefContext->MixerWindow->baseUnit.cy, 8); 707 if (PrefContext->MixerWindow->bShowExtendedControls && PrefContext->MixerWindow->bHasExtendedControls) 708 PrefContext->MixerWindow->rect.bottom += dy; 709 710 /* now move the window */ 711 AdjustWindowRect(&PrefContext->MixerWindow->rect, WS_DLGFRAME | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, TRUE); 712 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); 713 714 /* Move the status bar */ 715 if (PrefContext->MixerWindow->hStatusBar) 716 { 717 SetWindowPos(PrefContext->MixerWindow->hStatusBar, 718 HWND_TOP, 719 statusRect.left, 720 PrefContext->MixerWindow->rect.bottom - (statusRect.bottom - statusRect.top), 721 PrefContext->MixerWindow->rect.right - PrefContext->MixerWindow->rect.left, 722 statusRect.bottom - statusRect.top, 723 SWP_NOZORDER); 724 } 725 726 if (PrefContext->MixerWindow->MixerId == RECORD_MIXER) 727 LoadStringW(hAppInstance, IDS_SELECT, szBuffer, ARRAYSIZE(szBuffer)); 728 729 for (i = 0; i < PrefContext->MixerWindow->DialogCount; i++) 730 { 731 if (PrefContext->MixerWindow->MixerId == RECORD_MIXER) 732 { 733 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, (i + 1) * IDC_LINE_SWITCH); 734 735 /* Turn the autocheckbox into a checkbox */ 736 SetWindowLongPtr(hDlgCtrl, GWL_STYLE, (GetWindowLongPtr(hDlgCtrl, GWL_STYLE) & ~BS_AUTOCHECKBOX) | BS_CHECKBOX); 737 738 /* Change text from 'Mute' to 'Select' */ 739 SetWindowTextW(hDlgCtrl, szBuffer); 740 } 741 742 /* Resize the vertical line separator */ 743 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, (i + 1) * IDC_LINE_SEP); 744 if (hDlgCtrl != NULL) 745 { 746 GetWindowRect(hDlgCtrl, &statusRect); 747 if (PrefContext->MixerWindow->bShowExtendedControls && PrefContext->MixerWindow->bHasExtendedControls) 748 statusRect.bottom += dy; 749 750 SetWindowPos(hDlgCtrl, 751 HWND_TOP, 752 0, 753 0, 754 statusRect.right - statusRect.left, 755 statusRect.bottom - statusRect.top, 756 SWP_NOMOVE | SWP_NOZORDER); 757 } 758 } 759 760 /* Hide the last line separator */ 761 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, IDC_LINE_SEP * PrefContext->MixerWindow->DialogCount); 762 if (hDlgCtrl != NULL) 763 { 764 ShowWindow(hDlgCtrl, SW_HIDE); 765 } 766 } 767 768 VOID 769 UpdateDialogLineSwitchControl( 770 PPREFERENCES_CONTEXT PrefContext, 771 LPMIXERLINE Line, 772 LONG fValue) 773 { 774 DWORD Index; 775 DWORD wID; 776 HWND hDlgCtrl; 777 WCHAR LineName[MIXER_LONG_NAME_CHARS]; 778 779 /* find the index of this line */ 780 for (Index = 0; Index < PrefContext->MixerWindow->DialogCount; Index++) 781 { 782 /* get id */ 783 wID = (Index + 1) * IDC_LINE_NAME; 784 785 if (GetDlgItemText(PrefContext->MixerWindow->hWnd, wID, LineName, MIXER_LONG_NAME_CHARS) == 0) 786 { 787 /* failed to retrieve id */ 788 continue; 789 } 790 791 /* check if the line name matches */ 792 if (!wcsicmp(LineName, Line->szName)) 793 { 794 /* found matching line name */ 795 wID = (Index + 1) * IDC_LINE_SWITCH; 796 797 /* get dialog control */ 798 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID); 799 800 if (hDlgCtrl != NULL) 801 { 802 /* check state */ 803 if (SendMessageW(hDlgCtrl, BM_GETCHECK, 0, 0) != fValue) 804 { 805 /* update control state */ 806 SendMessageW(hDlgCtrl, BM_SETCHECK, (WPARAM)fValue, 0); 807 } 808 } 809 break; 810 } 811 } 812 } 813 814 VOID 815 UpdateDialogLineSliderControl( 816 PPREFERENCES_CONTEXT PrefContext, 817 LPMIXERLINE Line, 818 DWORD dwDialogID, 819 DWORD Position) 820 { 821 DWORD Index; 822 DWORD wID; 823 HWND hDlgCtrl; 824 WCHAR LineName[MIXER_LONG_NAME_CHARS]; 825 826 /* find the index of this line */ 827 for (Index = 0; Index < PrefContext->MixerWindow->DialogCount; Index++) 828 { 829 /* get id */ 830 wID = (Index + 1) * IDC_LINE_NAME; 831 832 if (GetDlgItemText(PrefContext->MixerWindow->hWnd, wID, LineName, MIXER_LONG_NAME_CHARS) == 0) 833 { 834 /* failed to retrieve id */ 835 continue; 836 } 837 838 /* check if the line name matches */ 839 if (!wcsicmp(LineName, Line->szName)) 840 { 841 /* found matching line name */ 842 wID = (Index + 1) * dwDialogID; 843 844 /* get dialog control */ 845 hDlgCtrl = GetDlgItem(PrefContext->MixerWindow->hWnd, wID); 846 847 if (hDlgCtrl != NULL) 848 { 849 /* check state */ 850 LRESULT OldPosition = SendMessageW(hDlgCtrl, TBM_GETPOS, 0, 0); 851 if (OldPosition != Position) 852 { 853 /* update control state */ 854 SendMessageW(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, Position); 855 } 856 } 857 break; 858 } 859 } 860 } 861