1 #include "desk.h" 2 3 static const TCHAR szMonitorSelWndClass[] = TEXT("MONITORSELWNDCLASS"); 4 5 typedef struct _MONSL_MON 6 { 7 RECT rc; 8 HFONT hFont; 9 TCHAR szCaption[12]; 10 } MONSL_MON, *PMONSL_MON; 11 12 typedef struct _MONITORSELWND 13 { 14 HWND hSelf; 15 HWND hNotify; 16 HFONT hFont; 17 SIZE ClientSize; 18 DWORD UIState; 19 union 20 { 21 DWORD dwInternalFlags; 22 struct 23 { 24 UINT Enabled : 1; 25 UINT HasFocus : 1; 26 UINT CanDisplay : 1; 27 UINT LeftBtnDown : 1; 28 UINT IsDraggingMonitor : 1; 29 }; 30 }; 31 DWORD ControlExStyle; 32 DWORD MonitorsCount; 33 INT SelectedMonitor; 34 INT DraggingMonitor; 35 RECT rcDragging; 36 POINT ptDrag, ptDragBegin; 37 SIZE DraggingMargin; 38 PMONSL_MONINFO MonitorInfo; 39 PMONSL_MON Monitors; 40 RECT rcExtent; 41 RECT rcMonitors; 42 RECT rcOldMonitors; 43 POINT ScrollPos; 44 SIZE Margin; 45 SIZE SelectionFrame; 46 HBITMAP hbmDisabledPattern; 47 HBRUSH hbrDisabled; 48 } MONITORSELWND, *PMONITORSELWND; 49 50 static LRESULT 51 MonSelNotify(IN PMONITORSELWND infoPtr, 52 IN UINT code, 53 IN OUT PVOID data) 54 { 55 LRESULT Ret = 0; 56 57 if (infoPtr->hNotify != NULL) 58 { 59 LPNMHDR pnmh = (LPNMHDR)data; 60 61 pnmh->hwndFrom = infoPtr->hSelf; 62 pnmh->idFrom = GetWindowLongPtr(infoPtr->hSelf, 63 GWLP_ID); 64 pnmh->code = code; 65 66 Ret = SendMessage(infoPtr->hNotify, 67 WM_NOTIFY, 68 (WPARAM)pnmh->idFrom, 69 (LPARAM)pnmh); 70 } 71 72 return Ret; 73 } 74 75 static LRESULT 76 MonSelNotifyMonitor(IN PMONITORSELWND infoPtr, 77 IN UINT code, 78 IN INT Index, 79 IN OUT PMONSL_MONNMHDR pmonnmh) 80 { 81 pmonnmh->Index = Index; 82 83 if (Index >= 0) 84 { 85 pmonnmh->MonitorInfo = infoPtr->MonitorInfo[Index]; 86 } 87 else 88 { 89 ZeroMemory(&pmonnmh->MonitorInfo, 90 sizeof(pmonnmh->MonitorInfo)); 91 } 92 93 return MonSelNotify(infoPtr, 94 code, 95 pmonnmh); 96 } 97 98 static HFONT 99 MonSelChangeFont(IN OUT PMONITORSELWND infoPtr, 100 IN HFONT hFont, 101 IN BOOL Redraw) 102 { 103 HFONT hOldFont = infoPtr->hFont; 104 infoPtr->hFont = hFont; 105 106 if (Redraw) 107 { 108 InvalidateRect(infoPtr->hSelf, 109 NULL, 110 TRUE); 111 } 112 113 return hOldFont; 114 } 115 116 static VOID 117 MonSelRectToScreen(IN PMONITORSELWND infoPtr, 118 IN const RECT *prc, 119 OUT PRECT prcOnScreen) 120 { 121 *prcOnScreen = *prc; 122 OffsetRect(prcOnScreen, 123 -infoPtr->ScrollPos.x, 124 -infoPtr->ScrollPos.y); 125 } 126 127 static VOID 128 MonSelScreenToPt(IN PMONITORSELWND infoPtr, 129 IN const POINT *pptOnScreen, 130 OUT PPOINT ppt) 131 { 132 ppt->x = pptOnScreen->x + infoPtr->ScrollPos.x; 133 ppt->y = pptOnScreen->y + infoPtr->ScrollPos.y; 134 } 135 136 static VOID 137 MonSelMonInfoToRect(IN const MONSL_MONINFO *pMonInfo, 138 OUT PRECT prc) 139 { 140 prc->left = pMonInfo->Position.x; 141 prc->top = pMonInfo->Position.y; 142 prc->right = pMonInfo->Position.x + pMonInfo->Size.cx; 143 prc->bottom = pMonInfo->Position.y + pMonInfo->Size.cy; 144 } 145 146 static INT 147 MonSelHitTest(IN PMONITORSELWND infoPtr, 148 IN const POINT *ppt) 149 { 150 POINT pt; 151 INT Index, Ret = -1; 152 153 if (infoPtr->CanDisplay) 154 { 155 MonSelScreenToPt(infoPtr, 156 ppt, 157 &pt); 158 159 for (Index = 0; Index < (INT)infoPtr->MonitorsCount; Index++) 160 { 161 if (PtInRect(&infoPtr->Monitors[Index].rc, 162 pt)) 163 { 164 Ret = Index; 165 break; 166 } 167 } 168 } 169 170 return Ret; 171 } 172 173 static VOID 174 MonSelUpdateExtent(IN OUT PMONITORSELWND infoPtr) 175 { 176 DWORD Index; 177 RECT rcMonitor; 178 179 /* NOTE: This routine calculates the extent of all monitor coordinates. 180 These are not control coordinates! */ 181 if (infoPtr->MonitorsCount > 0) 182 { 183 MonSelMonInfoToRect(&infoPtr->MonitorInfo[0], 184 &infoPtr->rcExtent); 185 186 for (Index = 1; Index < infoPtr->MonitorsCount; Index++) 187 { 188 MonSelMonInfoToRect(&infoPtr->MonitorInfo[Index], 189 &rcMonitor); 190 191 UnionRect(&infoPtr->rcExtent, 192 &infoPtr->rcExtent, 193 &rcMonitor); 194 } 195 } 196 else 197 { 198 ZeroMemory(&infoPtr->rcExtent, 199 sizeof(infoPtr->rcExtent)); 200 } 201 } 202 203 static VOID 204 MonSelScaleRectRelative(IN const RECT *prcBaseFrom, 205 IN const RECT *prcFrom, 206 IN const RECT *prcBaseTo, 207 OUT PRECT prcTo) 208 { 209 SIZE BaseFrom, BaseTo, From; 210 211 BaseFrom.cx = prcBaseFrom->right - prcBaseFrom->left; 212 BaseFrom.cy = prcBaseFrom->bottom - prcBaseFrom->top; 213 BaseTo.cx = prcBaseTo->right - prcBaseTo->left; 214 BaseTo.cy = prcBaseTo->bottom - prcBaseTo->top; 215 From.cx = prcFrom->right - prcFrom->left; 216 From.cy = prcFrom->bottom - prcFrom->top; 217 218 prcTo->left = prcBaseTo->left + (((prcFrom->left - prcBaseFrom->left) * BaseTo.cx) / BaseFrom.cx); 219 prcTo->top = prcBaseTo->top + (((prcFrom->top - prcBaseFrom->top) * BaseTo.cy) / BaseFrom.cy); 220 prcTo->right = prcTo->left + ((From.cx * BaseTo.cx) / BaseFrom.cx); 221 prcTo->bottom = prcTo->top + ((From.cy * BaseTo.cy) / BaseFrom.cy); 222 } 223 224 static VOID 225 ScaleRectSizeFit(IN const RECT *prcContainerRect, 226 IN OUT PRECT prcRectToScale) 227 { 228 SIZE ContainerSize, RectSize; 229 230 ContainerSize.cx = prcContainerRect->right - prcContainerRect->left; 231 ContainerSize.cy = prcContainerRect->bottom - prcContainerRect->top; 232 RectSize.cx = prcRectToScale->right - prcRectToScale->left; 233 RectSize.cy = prcRectToScale->bottom - prcRectToScale->top; 234 235 if (((RectSize.cx * 0xFFF) / RectSize.cy) < ((ContainerSize.cx * 0xFFF) / ContainerSize.cy)) 236 { 237 RectSize.cx = (RectSize.cx * ((ContainerSize.cy * 0xFFF) / RectSize.cy)) / 0xFFF; 238 RectSize.cy = ContainerSize.cy; 239 } 240 else 241 { 242 RectSize.cy = (RectSize.cy * ((ContainerSize.cx * 0xFFF) / RectSize.cx)) / 0xFFF; 243 RectSize.cx = ContainerSize.cx; 244 } 245 246 prcRectToScale->right = prcRectToScale->left + RectSize.cx; 247 prcRectToScale->bottom = prcRectToScale->top + RectSize.cy; 248 249 OffsetRect(prcRectToScale, 250 prcContainerRect->left + ((ContainerSize.cx - RectSize.cx) / 2), 251 prcContainerRect->top + ((ContainerSize.cy - RectSize.cy) / 2)); 252 } 253 254 static VOID 255 MonSelRepaint(IN PMONITORSELWND infoPtr) 256 { 257 RECT rc; 258 259 MonSelRectToScreen(infoPtr, 260 &infoPtr->rcMonitors, 261 &rc); 262 InvalidateRect(infoPtr->hSelf, 263 &rc, 264 TRUE); 265 266 if (!EqualRect(&infoPtr->rcMonitors, &infoPtr->rcOldMonitors) && 267 infoPtr->rcOldMonitors.right != infoPtr->rcOldMonitors.left) 268 { 269 MonSelRectToScreen(infoPtr, &infoPtr->rcOldMonitors, &rc); 270 InvalidateRect(infoPtr->hSelf, &rc, TRUE); 271 infoPtr->rcOldMonitors = infoPtr->rcMonitors; 272 } 273 } 274 275 static VOID 276 MonSelRepaintMonitor(IN PMONITORSELWND infoPtr, 277 IN DWORD Index) 278 { 279 RECT rc; 280 BOOL NoRepaint = FALSE; 281 282 if (Index < infoPtr->MonitorsCount) 283 { 284 if (Index == (DWORD)infoPtr->DraggingMonitor) 285 { 286 if (infoPtr->IsDraggingMonitor) 287 { 288 MonSelRectToScreen(infoPtr, 289 &infoPtr->rcDragging, 290 &rc); 291 } 292 else 293 NoRepaint = TRUE; 294 } 295 else 296 { 297 MonSelRectToScreen(infoPtr, 298 &infoPtr->Monitors[Index].rc, 299 &rc); 300 } 301 302 if (!NoRepaint) 303 { 304 InvalidateRect(infoPtr->hSelf, 305 &rc, 306 TRUE); 307 } 308 } 309 } 310 311 static VOID 312 MonSelRepaintSelected(IN PMONITORSELWND infoPtr) 313 { 314 if (infoPtr->SelectedMonitor >= 0) 315 { 316 MonSelRepaintMonitor(infoPtr, 317 (DWORD)infoPtr->SelectedMonitor); 318 } 319 } 320 321 static VOID 322 MonSelResetMonitors(IN OUT PMONITORSELWND infoPtr) 323 { 324 DWORD Index; 325 326 for (Index = 0; Index < infoPtr->MonitorsCount; Index++) 327 { 328 if (infoPtr->Monitors[Index].hFont != NULL) 329 { 330 DeleteObject(infoPtr->Monitors[Index].hFont); 331 infoPtr->Monitors[Index].hFont = NULL; 332 } 333 } 334 } 335 336 337 static VOID 338 MonSelUpdateMonitorsInfo(IN OUT PMONITORSELWND infoPtr, 339 IN BOOL bRepaint) 340 { 341 RECT rcExtSurface, rcExtDisplay; 342 DWORD Index; 343 344 /* Recalculate rcExtent */ 345 MonSelUpdateExtent(infoPtr); 346 347 infoPtr-> CanDisplay = infoPtr->MonitorsCount != 0 && 348 (infoPtr->ClientSize.cx > (2 * (infoPtr->Margin.cx + infoPtr->SelectionFrame.cx))) && 349 (infoPtr->ClientSize.cy > (2 * (infoPtr->Margin.cy + infoPtr->SelectionFrame.cy))); 350 351 if (infoPtr->CanDisplay) 352 { 353 /* Calculate the rectangle on the control in which may be painted */ 354 rcExtSurface.left = infoPtr->Margin.cx; 355 rcExtSurface.top = infoPtr->Margin.cy; 356 rcExtSurface.right = rcExtSurface.left + infoPtr->ClientSize.cx - (2 * infoPtr->Margin.cx); 357 rcExtSurface.bottom = rcExtSurface.top + infoPtr->ClientSize.cy - (2 * infoPtr->Margin.cy); 358 359 /* Calculate the rectangle on the control that is actually painted on */ 360 rcExtDisplay.left = rcExtDisplay.top = 0; 361 rcExtDisplay.right = infoPtr->rcExtent.right - infoPtr->rcExtent.left; 362 rcExtDisplay.bottom = infoPtr->rcExtent.bottom - infoPtr->rcExtent.top; 363 364 ScaleRectSizeFit(&rcExtSurface, 365 &rcExtDisplay); 366 367 infoPtr->rcOldMonitors = infoPtr->rcMonitors; 368 infoPtr->rcMonitors = rcExtDisplay; 369 370 /* Now that we know in which area all monitors are located, 371 calculate the monitors selection rectangles on the screen */ 372 373 for (Index = 0; Index < infoPtr->MonitorsCount; Index++) 374 { 375 MonSelMonInfoToRect(&infoPtr->MonitorInfo[Index], 376 &rcExtDisplay); 377 378 MonSelScaleRectRelative(&infoPtr->rcExtent, 379 &rcExtDisplay, 380 &infoPtr->rcMonitors, 381 &infoPtr->Monitors[Index].rc); 382 } 383 384 MonSelResetMonitors(infoPtr); 385 386 if (bRepaint) 387 MonSelRepaint(infoPtr); 388 } 389 else if (bRepaint) 390 { 391 InvalidateRect(infoPtr->hSelf, 392 NULL, 393 TRUE); 394 } 395 } 396 397 static BOOL 398 MonSelSetMonitorsInfo(IN OUT PMONITORSELWND infoPtr, 399 IN DWORD dwMonitors, 400 IN const MONSL_MONINFO *MonitorsInfo) 401 { 402 DWORD Index; 403 BOOL Ret = TRUE; 404 405 if (infoPtr->DraggingMonitor >= 0) 406 return FALSE; 407 408 if (infoPtr->MonitorInfo != NULL) 409 { 410 LocalFree((HLOCAL)infoPtr->MonitorInfo); 411 infoPtr->MonitorInfo = NULL; 412 413 MonSelResetMonitors(infoPtr); 414 415 LocalFree((HLOCAL)infoPtr->Monitors); 416 infoPtr->Monitors = NULL; 417 418 infoPtr->MonitorsCount = 0; 419 } 420 421 if (dwMonitors != 0) 422 { 423 infoPtr->MonitorInfo = (PMONSL_MONINFO)LocalAlloc(LMEM_FIXED, 424 dwMonitors * sizeof(MONSL_MONINFO)); 425 if (infoPtr->MonitorInfo != NULL) 426 { 427 infoPtr->Monitors = (PMONSL_MON)LocalAlloc(LMEM_FIXED, 428 dwMonitors * sizeof(MONSL_MON)); 429 if (infoPtr->Monitors != NULL) 430 { 431 CopyMemory(infoPtr->MonitorInfo, 432 MonitorsInfo, 433 dwMonitors * sizeof(MONSL_MONINFO)); 434 ZeroMemory(infoPtr->Monitors, 435 dwMonitors * sizeof(MONSL_MON)); 436 437 for (Index = 0; Index < dwMonitors; Index++) 438 { 439 _stprintf(infoPtr->Monitors[Index].szCaption, 440 _T("%u"), 441 Index + 1); 442 } 443 444 infoPtr->MonitorsCount = dwMonitors; 445 446 if (infoPtr->SelectedMonitor >= (INT)infoPtr->MonitorsCount) 447 infoPtr->SelectedMonitor = -1; 448 449 if (!(infoPtr->ControlExStyle & MSLM_EX_ALLOWSELECTNONE) && infoPtr->SelectedMonitor < 0) 450 infoPtr->SelectedMonitor = 0; 451 452 MonSelUpdateMonitorsInfo(infoPtr, 453 TRUE); 454 } 455 else 456 { 457 LocalFree((HLOCAL)infoPtr->MonitorInfo); 458 infoPtr->MonitorInfo = NULL; 459 460 Ret = FALSE; 461 } 462 } 463 else 464 Ret = FALSE; 465 } 466 467 if (!Ret) 468 infoPtr->SelectedMonitor = -1; 469 470 if (!Ret || dwMonitors == 0) 471 { 472 InvalidateRect(infoPtr->hSelf, 473 NULL, 474 TRUE); 475 } 476 477 return Ret; 478 } 479 480 static DWORD 481 MonSelGetMonitorsInfo(IN PMONITORSELWND infoPtr, 482 IN DWORD dwMonitors, 483 IN OUT PMONSL_MONINFO MonitorsInfo) 484 { 485 if (dwMonitors != 0) 486 { 487 if (dwMonitors > infoPtr->MonitorsCount) 488 dwMonitors = infoPtr->MonitorsCount; 489 490 CopyMemory(MonitorsInfo, 491 infoPtr->MonitorInfo, 492 dwMonitors * sizeof(MONSL_MONINFO)); 493 return dwMonitors; 494 } 495 else 496 return infoPtr->MonitorsCount; 497 } 498 499 static BOOL 500 MonSelSetMonitorInfo(IN OUT PMONITORSELWND infoPtr, 501 IN INT Index, 502 IN const MONSL_MONINFO *MonitorsInfo) 503 { 504 if (infoPtr->DraggingMonitor < 0 && 505 Index >= 0 && Index < (INT)infoPtr->MonitorsCount) 506 { 507 CopyMemory(&infoPtr->MonitorInfo[Index], 508 MonitorsInfo, 509 sizeof(MONSL_MONINFO)); 510 511 MonSelUpdateMonitorsInfo(infoPtr, 512 TRUE); 513 return TRUE; 514 } 515 516 return FALSE; 517 } 518 519 static BOOL 520 MonSelGetMonitorInfo(IN PMONITORSELWND infoPtr, 521 IN INT Index, 522 IN OUT PMONSL_MONINFO MonitorsInfo) 523 { 524 if (Index >= 0 && Index < (INT)infoPtr->MonitorsCount) 525 { 526 CopyMemory(MonitorsInfo, 527 &infoPtr->MonitorInfo[Index], 528 sizeof(MONSL_MONINFO)); 529 return TRUE; 530 } 531 532 return FALSE; 533 } 534 535 static INT 536 MonSelGetMonitorRect(IN OUT PMONITORSELWND infoPtr, 537 IN INT Index, 538 OUT PRECT prc) 539 { 540 RECT rc, rcClient; 541 542 if (Index < 0 || (UINT)Index >= infoPtr->MonitorsCount) 543 return -1; 544 545 if (!infoPtr->CanDisplay) 546 return 0; 547 548 MonSelRectToScreen(infoPtr, 549 &infoPtr->Monitors[Index].rc, 550 prc); 551 552 rcClient.left = rcClient.top = 0; 553 rcClient.right = infoPtr->ClientSize.cx; 554 rcClient.bottom = infoPtr->ClientSize.cy; 555 556 return IntersectRect(&rc, 557 &rcClient, 558 prc) != FALSE; 559 } 560 561 static BOOL 562 MonSelSetCurSelMonitor(IN OUT PMONITORSELWND infoPtr, 563 IN INT Index, 564 IN BOOL bNotify) 565 { 566 INT PrevSel; 567 BOOL PreventSelect = FALSE; 568 BOOL Ret = FALSE; 569 570 if (infoPtr->DraggingMonitor < 0 && 571 (Index == -1 || Index < (INT)infoPtr->MonitorsCount)) 572 { 573 if (Index != infoPtr->SelectedMonitor) 574 { 575 if ((infoPtr->MonitorInfo[Index].Flags & MSL_MIF_DISABLED) && 576 !(infoPtr->ControlExStyle & MSLM_EX_ALLOWSELECTDISABLED)) 577 { 578 PreventSelect = TRUE; 579 } 580 581 if (!PreventSelect && bNotify) 582 { 583 MONSL_MONNMMONITORCHANGING nmi; 584 585 nmi.PreviousSelected = infoPtr->SelectedMonitor; 586 nmi.AllowChanging = TRUE; 587 588 MonSelNotifyMonitor(infoPtr, 589 MSLN_MONITORCHANGING, 590 Index, 591 &nmi.hdr); 592 593 PreventSelect = (nmi.AllowChanging == FALSE); 594 } 595 596 if (!PreventSelect) 597 { 598 PrevSel = infoPtr->SelectedMonitor; 599 infoPtr->SelectedMonitor = Index; 600 601 if (PrevSel >= 0) 602 { 603 MonSelRepaintMonitor(infoPtr, 604 PrevSel); 605 } 606 607 if (infoPtr->SelectedMonitor >= 0) 608 MonSelRepaintSelected(infoPtr); 609 610 if (bNotify) 611 { 612 MONSL_MONNMHDR nm; 613 614 MonSelNotifyMonitor(infoPtr, 615 MSLN_MONITORCHANGED, 616 Index, 617 &nm); 618 } 619 } 620 } 621 622 Ret = TRUE; 623 } 624 625 return Ret; 626 } 627 628 static VOID 629 MonSelCreate(IN OUT PMONITORSELWND infoPtr) 630 { 631 infoPtr->SelectionFrame.cx = infoPtr->SelectionFrame.cy = 4; 632 infoPtr->Margin.cx = infoPtr->Margin.cy = 20; 633 infoPtr->SelectedMonitor = -1; 634 infoPtr->DraggingMonitor = -1; 635 infoPtr->ControlExStyle = MSLM_EX_ALLOWSELECTDISABLED | MSLM_EX_HIDENUMBERONSINGLE | 636 MSLM_EX_SELECTONRIGHTCLICK | MSLM_EX_SELECTBYARROWKEY; 637 return; 638 } 639 640 static VOID 641 MonSelDestroy(IN OUT PMONITORSELWND infoPtr) 642 { 643 /* Free all monitors */ 644 MonSelSetMonitorsInfo(infoPtr, 645 0, 646 NULL); 647 648 if (infoPtr->hbrDisabled != NULL) 649 { 650 DeleteObject(infoPtr->hbrDisabled); 651 infoPtr->hbrDisabled = NULL; 652 } 653 654 if (infoPtr->hbmDisabledPattern != NULL) 655 { 656 DeleteObject(infoPtr->hbmDisabledPattern); 657 infoPtr->hbmDisabledPattern = NULL; 658 } 659 } 660 661 static BOOL 662 MonSelSetExtendedStyle(IN OUT PMONITORSELWND infoPtr, 663 IN DWORD dwExtendedStyle) 664 { 665 if (infoPtr->DraggingMonitor >= 0) 666 return FALSE; 667 668 if (dwExtendedStyle != infoPtr->ControlExStyle) 669 { 670 infoPtr->ControlExStyle = dwExtendedStyle; 671 672 /* Repaint the control */ 673 InvalidateRect(infoPtr->hSelf, 674 NULL, 675 TRUE); 676 } 677 678 return TRUE; 679 } 680 681 static DWORD 682 MonSelGetExtendedStyle(IN PMONITORSELWND infoPtr) 683 { 684 return infoPtr->ControlExStyle; 685 } 686 687 static HFONT 688 MonSelGetMonitorFont(IN OUT PMONITORSELWND infoPtr, 689 IN HDC hDC, 690 IN INT Index) 691 { 692 TEXTMETRIC tm; 693 SIZE rcsize; 694 LOGFONT lf; 695 HFONT hPrevFont, hFont; 696 //INT len; 697 698 hFont = infoPtr->Monitors[Index].hFont; 699 if (hFont == NULL && 700 GetObject(infoPtr->hFont, 701 sizeof(lf), 702 &lf) != 0) 703 { 704 rcsize.cx = infoPtr->Monitors[Index].rc.right - infoPtr->Monitors[Index].rc.left - 705 (2 * infoPtr->SelectionFrame.cx) - 2; 706 rcsize.cy = infoPtr->Monitors[Index].rc.bottom - infoPtr->Monitors[Index].rc.top - 707 (2 * infoPtr->SelectionFrame.cy) - 2; 708 rcsize.cy = (rcsize.cy * 60) / 100; 709 710 //len = _tcslen(infoPtr->Monitors[Index].szCaption); 711 712 hPrevFont = SelectObject(hDC, 713 infoPtr->hFont); 714 715 if (GetTextMetrics(hDC, 716 &tm)) 717 { 718 lf.lfWeight = FW_SEMIBOLD; 719 lf.lfHeight = -MulDiv(rcsize.cy - tm.tmExternalLeading, 720 GetDeviceCaps(hDC, 721 LOGPIXELSY), 722 72); 723 724 hFont = CreateFontIndirect(&lf); 725 if (hFont != NULL) 726 infoPtr->Monitors[Index].hFont = hFont; 727 } 728 729 SelectObject(hDC, 730 hPrevFont); 731 } 732 733 return hFont; 734 } 735 736 static BOOL 737 MonSelDrawDisabledRect(IN OUT PMONITORSELWND infoPtr, 738 IN HDC hDC, 739 IN const RECT *prc) 740 { 741 BOOL Ret = FALSE; 742 743 if (infoPtr->hbrDisabled == NULL) 744 { 745 static const DWORD Pattern[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA}; 746 747 if (infoPtr->hbmDisabledPattern == NULL) 748 { 749 infoPtr->hbmDisabledPattern = CreateBitmap(8, 750 8, 751 1, 752 1, 753 Pattern); 754 } 755 756 if (infoPtr->hbmDisabledPattern != NULL) 757 infoPtr->hbrDisabled = CreatePatternBrush(infoPtr->hbmDisabledPattern); 758 } 759 760 if (infoPtr->hbrDisabled != NULL) 761 { 762 /* FIXME: Implement */ 763 } 764 765 return Ret; 766 } 767 768 static VOID 769 MonSelPaintMonitor(IN OUT PMONITORSELWND infoPtr, 770 IN HDC hDC, 771 IN DWORD Index, 772 IN OUT PRECT prc, 773 IN COLORREF crDefFontColor, 774 IN BOOL bHideNumber) 775 { 776 HFONT hFont, hPrevFont; 777 COLORREF crPrevText; 778 779 if ((INT)Index == infoPtr->SelectedMonitor) 780 { 781 FillRect(hDC, 782 prc, 783 (HBRUSH)(COLOR_HIGHLIGHT + 1)); 784 785 if (infoPtr->HasFocus && !(infoPtr->UIState & UISF_HIDEFOCUS)) 786 { 787 /* NOTE: We need to switch the text color to the default, because 788 DrawFocusRect draws a solid line if the text is white! */ 789 790 crPrevText = SetTextColor(hDC, 791 crDefFontColor); 792 793 DrawFocusRect(hDC, 794 prc); 795 796 SetTextColor(hDC, 797 crPrevText); 798 } 799 } 800 801 InflateRect(prc, 802 -infoPtr->SelectionFrame.cx, 803 -infoPtr->SelectionFrame.cy); 804 805 Rectangle(hDC, 806 prc->left, 807 prc->top, 808 prc->right, 809 prc->bottom); 810 811 InflateRect(prc, 812 -1, 813 -1); 814 815 if (!bHideNumber) 816 { 817 hFont = MonSelGetMonitorFont(infoPtr, 818 hDC, 819 Index); 820 if (hFont != NULL) 821 { 822 hPrevFont = SelectObject(hDC, 823 hFont); 824 825 DrawText(hDC, 826 infoPtr->Monitors[Index].szCaption, 827 -1, 828 prc, 829 DT_VCENTER | DT_CENTER | DT_NOPREFIX | DT_SINGLELINE); 830 831 SelectObject(hDC, 832 hPrevFont); 833 } 834 } 835 836 if (infoPtr->MonitorInfo[Index].Flags & MSL_MIF_DISABLED) 837 { 838 InflateRect(prc, 839 1, 840 1); 841 842 MonSelDrawDisabledRect(infoPtr, 843 hDC, 844 prc); 845 } 846 } 847 848 static VOID 849 MonSelPaint(IN OUT PMONITORSELWND infoPtr, 850 IN HDC hDC, 851 IN const RECT *prcUpdate) 852 { 853 COLORREF crPrevText; 854 HBRUSH hbBk, hbOldBk; 855 HPEN hpFg, hpOldFg; 856 DWORD Index; 857 RECT rc, rctmp; 858 INT iPrevBkMode; 859 BOOL bHideNumber; 860 861 bHideNumber = (infoPtr->ControlExStyle & MSLM_EX_HIDENUMBERS) || 862 ((infoPtr->MonitorsCount == 1) && (infoPtr->ControlExStyle & MSLM_EX_HIDENUMBERONSINGLE)); 863 864 hbBk = GetSysColorBrush(COLOR_BACKGROUND); 865 hpFg = CreatePen(PS_SOLID, 866 0, 867 GetSysColor(COLOR_HIGHLIGHTTEXT)); 868 869 hbOldBk = SelectObject(hDC, 870 hbBk); 871 hpOldFg = SelectObject(hDC, 872 hpFg); 873 iPrevBkMode = SetBkMode(hDC, 874 TRANSPARENT); 875 crPrevText = SetTextColor(hDC, 876 GetSysColor(COLOR_HIGHLIGHTTEXT)); 877 878 for (Index = 0; Index < infoPtr->MonitorsCount; Index++) 879 { 880 if (infoPtr->IsDraggingMonitor && 881 (DWORD)infoPtr->DraggingMonitor == Index) 882 { 883 continue; 884 } 885 886 MonSelRectToScreen(infoPtr, 887 &infoPtr->Monitors[Index].rc, 888 &rc); 889 890 if (IntersectRect(&rctmp, 891 &rc, 892 prcUpdate)) 893 { 894 MonSelPaintMonitor(infoPtr, 895 hDC, 896 Index, 897 &rc, 898 crPrevText, 899 bHideNumber); 900 } 901 } 902 903 /* Paint the dragging monitor last */ 904 if (infoPtr->IsDraggingMonitor && 905 infoPtr->DraggingMonitor >= 0) 906 { 907 MonSelRectToScreen(infoPtr, 908 &infoPtr->rcDragging, 909 &rc); 910 911 if (IntersectRect(&rctmp, 912 &rc, 913 prcUpdate)) 914 { 915 MonSelPaintMonitor(infoPtr, 916 hDC, 917 (DWORD)infoPtr->DraggingMonitor, 918 &rc, 919 crPrevText, 920 bHideNumber); 921 } 922 } 923 924 SetTextColor(hDC, 925 crPrevText); 926 SetBkMode(hDC, 927 iPrevBkMode); 928 SelectObject(hDC, 929 hpOldFg); 930 SelectObject(hDC, 931 hbOldBk); 932 933 DeleteObject(hpFg); 934 } 935 936 static VOID 937 MonSelContextMenu(IN OUT PMONITORSELWND infoPtr, 938 IN SHORT x, 939 IN SHORT y) 940 { 941 MONSL_MONNMBUTTONCLICKED nm; 942 INT Index; 943 944 if (!infoPtr->HasFocus) 945 SetFocus(infoPtr->hSelf); 946 947 nm.pt.x = x; 948 nm.pt.y = y; 949 950 Index = MonSelHitTest(infoPtr, 951 &nm.pt); 952 953 MonSelNotifyMonitor(infoPtr, 954 MSLN_RBUTTONUP, 955 Index, 956 (PMONSL_MONNMHDR)&nm); 957 958 /* Send a WM_CONTEXTMENU notification */ 959 MapWindowPoints(infoPtr->hSelf, 960 NULL, 961 &nm.pt, 962 1); 963 964 SendMessage(infoPtr->hSelf, 965 WM_CONTEXTMENU, 966 (WPARAM)infoPtr->hSelf, 967 MAKELPARAM(nm.pt.x, 968 nm.pt.y)); 969 } 970 971 static VOID 972 MonSelApplyCursorClipping(IN PMONITORSELWND infoPtr, 973 IN BOOL bClip) 974 { 975 RECT rc; 976 977 if (bClip) 978 { 979 rc.left = rc.top = 0; 980 rc.right = infoPtr->ClientSize.cx; 981 rc.bottom = infoPtr->ClientSize.cy; 982 983 if (MapWindowPoints(infoPtr->hSelf, 984 NULL, 985 (LPPOINT)&rc, 986 2)) 987 { 988 ClipCursor(&rc); 989 } 990 } 991 else 992 { 993 ClipCursor(NULL); 994 } 995 } 996 997 static VOID 998 MonSelMoveDragRect(IN OUT PMONITORSELWND infoPtr, 999 IN PPOINT ppt) 1000 { 1001 RECT rcPrev, rcUpdate, *prc; 1002 HRGN hRgnPrev; 1003 HDC hDC; 1004 1005 if (infoPtr->CanDisplay) 1006 { 1007 hDC = GetDC(infoPtr->hSelf); 1008 if (hDC != NULL) 1009 { 1010 if (infoPtr->ptDrag.x != ppt->x || 1011 infoPtr->ptDrag.y != ppt->y) 1012 { 1013 infoPtr->ptDrag = *ppt; 1014 1015 rcPrev = infoPtr->rcDragging; 1016 1017 /* Calculate updated dragging rectangle */ 1018 prc = &infoPtr->Monitors[infoPtr->DraggingMonitor].rc; 1019 infoPtr->rcDragging.left = ppt->x - infoPtr->DraggingMargin.cx; 1020 infoPtr->rcDragging.top = ppt->y - infoPtr->DraggingMargin.cy; 1021 infoPtr->rcDragging.right = infoPtr->rcDragging.left + (prc->right - prc->left); 1022 infoPtr->rcDragging.bottom = infoPtr->rcDragging.top + (prc->bottom - prc->top); 1023 1024 hRgnPrev = CreateRectRgn(rcPrev.left, 1025 rcPrev.top, 1026 rcPrev.right, 1027 rcPrev.bottom); 1028 1029 if (hRgnPrev != NULL) 1030 { 1031 if (!ScrollDC(hDC, 1032 infoPtr->rcDragging.left - rcPrev.left, 1033 infoPtr->rcDragging.top - rcPrev.top, 1034 &rcPrev, 1035 NULL, 1036 hRgnPrev, 1037 &rcUpdate) || 1038 !InvalidateRgn(infoPtr->hSelf, 1039 hRgnPrev, 1040 TRUE)) 1041 { 1042 DeleteObject(hRgnPrev); 1043 goto InvRects; 1044 } 1045 1046 DeleteObject(hRgnPrev); 1047 } 1048 else 1049 { 1050 InvRects: 1051 InvalidateRect(infoPtr->hSelf, 1052 &rcPrev, 1053 TRUE); 1054 InvalidateRect(infoPtr->hSelf, 1055 &infoPtr->rcDragging, 1056 TRUE); 1057 } 1058 } 1059 1060 ReleaseDC(infoPtr->hSelf, 1061 hDC); 1062 } 1063 } 1064 } 1065 1066 static VOID 1067 MonSelCancelDragging(IN OUT PMONITORSELWND infoPtr) 1068 { 1069 DWORD Index; 1070 1071 if (infoPtr->DraggingMonitor >= 0) 1072 { 1073 MonSelMoveDragRect(infoPtr, 1074 &infoPtr->ptDragBegin); 1075 1076 Index = (DWORD)infoPtr->DraggingMonitor; 1077 infoPtr->DraggingMonitor = -1; 1078 1079 if (infoPtr->CanDisplay) 1080 { 1081 /* Repaint the area where the monitor was last dragged */ 1082 MonSelRepaintMonitor(infoPtr, 1083 Index); 1084 1085 infoPtr->IsDraggingMonitor = FALSE; 1086 1087 /* Repaint the area where the monitor is located */ 1088 MonSelRepaintMonitor(infoPtr, 1089 Index); 1090 } 1091 else 1092 infoPtr->IsDraggingMonitor = FALSE; 1093 1094 ReleaseCapture(); 1095 1096 MonSelApplyCursorClipping(infoPtr, 1097 FALSE); 1098 } 1099 } 1100 1101 static VOID 1102 MonSelInitDragging(IN OUT PMONITORSELWND infoPtr, 1103 IN DWORD Index, 1104 IN PPOINT ppt) 1105 { 1106 POINT pt; 1107 1108 MonSelCancelDragging(infoPtr); 1109 infoPtr->IsDraggingMonitor = FALSE; 1110 1111 MonSelScreenToPt(infoPtr, 1112 ppt, 1113 &pt); 1114 1115 infoPtr->ptDrag = infoPtr->ptDragBegin = pt; 1116 infoPtr->DraggingMonitor = (INT)Index; 1117 1118 infoPtr->DraggingMargin.cx = ppt->x - infoPtr->Monitors[Index].rc.left; 1119 infoPtr->DraggingMargin.cy = ppt->y - infoPtr->Monitors[Index].rc.top; 1120 infoPtr->rcDragging = infoPtr->Monitors[Index].rc; 1121 1122 MonSelApplyCursorClipping(infoPtr, 1123 TRUE); 1124 } 1125 1126 static VOID 1127 MonSelDrag(IN OUT PMONITORSELWND infoPtr, 1128 IN PPOINT ppt) 1129 { 1130 SIZE szDrag; 1131 POINT pt; 1132 RECT rcDrag; 1133 1134 if (infoPtr->DraggingMonitor >= 0) 1135 { 1136 MonSelScreenToPt(infoPtr, 1137 ppt, 1138 &pt); 1139 1140 if (!infoPtr->IsDraggingMonitor) 1141 { 1142 szDrag.cx = GetSystemMetrics(SM_CXDRAG); 1143 szDrag.cy = GetSystemMetrics(SM_CYDRAG); 1144 1145 rcDrag.left = infoPtr->Monitors[infoPtr->DraggingMonitor].rc.left + infoPtr->DraggingMargin.cx - (szDrag.cx / 2); 1146 rcDrag.top = infoPtr->Monitors[infoPtr->DraggingMonitor].rc.top + infoPtr->DraggingMargin.cy - (szDrag.cy / 2); 1147 rcDrag.right = rcDrag.left + szDrag.cx; 1148 rcDrag.bottom = rcDrag.top + szDrag.cy; 1149 1150 if (!PtInRect(&rcDrag, 1151 pt)) 1152 { 1153 /* The user started moving around the mouse: Begin dragging */ 1154 infoPtr->IsDraggingMonitor = TRUE; 1155 MonSelMoveDragRect(infoPtr, 1156 &pt); 1157 } 1158 } 1159 else 1160 { 1161 MonSelMoveDragRect(infoPtr, 1162 &pt); 1163 } 1164 } 1165 } 1166 1167 static LRESULT CALLBACK 1168 MonitorSelWndProc(IN HWND hwnd, 1169 IN UINT uMsg, 1170 IN WPARAM wParam, 1171 IN LPARAM lParam) 1172 { 1173 PMONITORSELWND infoPtr; 1174 LRESULT Ret = 0; 1175 1176 infoPtr = (PMONITORSELWND)GetWindowLongPtrW(hwnd, 1177 0); 1178 1179 if (infoPtr == NULL && uMsg != WM_CREATE) 1180 { 1181 goto HandleDefaultMessage; 1182 } 1183 1184 switch (uMsg) 1185 { 1186 case WM_PAINT: 1187 case WM_PRINTCLIENT: 1188 { 1189 PAINTSTRUCT ps; 1190 HDC hDC; 1191 1192 if (wParam != 0) 1193 { 1194 if (!GetUpdateRect(hwnd, 1195 &ps.rcPaint, 1196 TRUE)) 1197 { 1198 break; 1199 } 1200 hDC = (HDC)wParam; 1201 } 1202 else 1203 { 1204 hDC = BeginPaint(hwnd, 1205 &ps); 1206 if (hDC == NULL) 1207 { 1208 break; 1209 } 1210 } 1211 1212 if (infoPtr->CanDisplay) 1213 { 1214 MonSelPaint(infoPtr, 1215 hDC, 1216 &ps.rcPaint); 1217 } 1218 1219 if (wParam == 0) 1220 { 1221 EndPaint(hwnd, 1222 &ps); 1223 } 1224 break; 1225 } 1226 1227 case WM_MOUSEMOVE: 1228 { 1229 POINT pt; 1230 1231 if (!(wParam & MK_LBUTTON)) 1232 { 1233 MonSelCancelDragging(infoPtr); 1234 break; 1235 } 1236 1237 if (infoPtr->LeftBtnDown) 1238 { 1239 pt.x = (LONG)LOWORD(lParam); 1240 pt.y = (LONG)HIWORD(lParam); 1241 1242 MonSelDrag(infoPtr, 1243 &pt); 1244 } 1245 1246 break; 1247 } 1248 1249 case WM_RBUTTONDOWN: 1250 { 1251 if (!(infoPtr->ControlExStyle & MSLM_EX_SELECTONRIGHTCLICK)) 1252 break; 1253 1254 /* Fall through */ 1255 } 1256 1257 case WM_LBUTTONDBLCLK: 1258 case WM_LBUTTONDOWN: 1259 { 1260 INT Index; 1261 POINT pt; 1262 1263 if (!infoPtr->HasFocus) 1264 SetFocus(infoPtr->hSelf); 1265 1266 pt.x = (LONG)LOWORD(lParam); 1267 pt.y = (LONG)HIWORD(lParam); 1268 1269 Index = MonSelHitTest(infoPtr, 1270 &pt); 1271 if (Index >= 0 || (infoPtr->ControlExStyle & MSLM_EX_ALLOWSELECTNONE)) 1272 { 1273 MonSelSetCurSelMonitor(infoPtr, 1274 Index, 1275 TRUE); 1276 } 1277 1278 if (Index >= 0 && (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK)) 1279 { 1280 infoPtr->LeftBtnDown = TRUE; 1281 MonSelInitDragging(infoPtr, 1282 (DWORD)Index, 1283 &pt); 1284 } 1285 1286 /* Fall through */ 1287 } 1288 1289 case WM_MBUTTONDOWN: 1290 { 1291 if (!infoPtr->HasFocus) 1292 SetFocus(hwnd); 1293 break; 1294 } 1295 1296 case WM_RBUTTONUP: 1297 { 1298 MonSelContextMenu(infoPtr, 1299 (SHORT)LOWORD(lParam), 1300 (SHORT)HIWORD(lParam)); 1301 break; 1302 } 1303 1304 case WM_LBUTTONUP: 1305 { 1306 MonSelCancelDragging(infoPtr); 1307 infoPtr->LeftBtnDown = FALSE; 1308 break; 1309 } 1310 1311 case WM_GETDLGCODE: 1312 { 1313 INT virtKey; 1314 1315 virtKey = (lParam != 0 ? (INT)((LPMSG)lParam)->wParam : 0); 1316 switch (virtKey) 1317 { 1318 case VK_TAB: 1319 { 1320 /* Change the UI status */ 1321 SendMessage(GetAncestor(hwnd, 1322 GA_PARENT), 1323 WM_CHANGEUISTATE, 1324 MAKEWPARAM(UIS_INITIALIZE, 1325 0), 1326 0); 1327 break; 1328 } 1329 } 1330 1331 Ret |= DLGC_WANTARROWS; 1332 1333 if (infoPtr->ControlExStyle & MSLM_EX_SELECTBYNUMKEY) 1334 Ret |= DLGC_WANTCHARS; 1335 break; 1336 } 1337 1338 case WM_SETFOCUS: 1339 { 1340 infoPtr->HasFocus = TRUE; 1341 MonSelRepaintSelected(infoPtr); 1342 break; 1343 } 1344 1345 case WM_KILLFOCUS: 1346 { 1347 infoPtr->HasFocus = FALSE; 1348 MonSelCancelDragging(infoPtr); 1349 MonSelRepaintSelected(infoPtr); 1350 break; 1351 } 1352 1353 case WM_UPDATEUISTATE: 1354 { 1355 DWORD OldUIState; 1356 1357 Ret = DefWindowProcW(hwnd, 1358 uMsg, 1359 wParam, 1360 lParam); 1361 1362 OldUIState = infoPtr->UIState; 1363 switch (LOWORD(wParam)) 1364 { 1365 case UIS_SET: 1366 infoPtr->UIState |= HIWORD(wParam); 1367 break; 1368 1369 case UIS_CLEAR: 1370 infoPtr->UIState &= ~HIWORD(wParam); 1371 break; 1372 } 1373 1374 if (infoPtr->UIState != OldUIState) 1375 MonSelRepaintSelected(infoPtr); 1376 break; 1377 } 1378 1379 case WM_SETFONT: 1380 { 1381 Ret = (LRESULT)MonSelChangeFont(infoPtr, 1382 (HFONT)wParam, 1383 (BOOL)LOWORD(lParam)); 1384 break; 1385 } 1386 1387 case WM_SIZE: 1388 { 1389 infoPtr->ClientSize.cx = LOWORD(lParam); 1390 infoPtr->ClientSize.cy = HIWORD(lParam); 1391 1392 /* Don't let MonSelUpdateMonitorsInfo repaint the control 1393 because this won't work properly in case the control 1394 was sized down! */ 1395 MonSelUpdateMonitorsInfo(infoPtr, 1396 FALSE); 1397 InvalidateRect(infoPtr->hSelf, 1398 NULL, 1399 TRUE); 1400 break; 1401 } 1402 1403 case WM_GETFONT: 1404 { 1405 Ret = (LRESULT)infoPtr->hFont; 1406 break; 1407 } 1408 1409 case WM_ENABLE: 1410 { 1411 infoPtr->Enabled = ((BOOL)wParam != FALSE); 1412 MonSelRepaint(infoPtr); 1413 break; 1414 } 1415 1416 case WM_STYLECHANGED: 1417 { 1418 if (wParam == GWL_STYLE) 1419 { 1420 unsigned int OldEnabled = infoPtr->Enabled; 1421 infoPtr->Enabled = !(((LPSTYLESTRUCT)lParam)->styleNew & WS_DISABLED); 1422 1423 if (OldEnabled != infoPtr->Enabled) 1424 MonSelRepaint(infoPtr); 1425 } 1426 break; 1427 } 1428 1429 case WM_KEYDOWN: 1430 { 1431 INT Index; 1432 1433 if (infoPtr->ControlExStyle & MSLM_EX_SELECTBYARROWKEY) 1434 { 1435 switch (wParam) 1436 { 1437 case VK_UP: 1438 case VK_LEFT: 1439 { 1440 Index = infoPtr->SelectedMonitor; 1441 1442 if (infoPtr->MonitorsCount != 0) 1443 { 1444 if (Index < 0) 1445 Index = 0; 1446 else if (Index > 0) 1447 Index--; 1448 } 1449 1450 if (Index >= 0) 1451 { 1452 MonSelSetCurSelMonitor(infoPtr, 1453 Index, 1454 TRUE); 1455 } 1456 break; 1457 } 1458 1459 case VK_DOWN: 1460 case VK_RIGHT: 1461 { 1462 Index = infoPtr->SelectedMonitor; 1463 1464 if (infoPtr->MonitorsCount != 0) 1465 { 1466 if (Index < 0) 1467 Index = (INT)infoPtr->MonitorsCount - 1; 1468 else if (Index < (INT)infoPtr->MonitorsCount - 1) 1469 Index++; 1470 } 1471 1472 if (infoPtr->SelectedMonitor < (INT)infoPtr->MonitorsCount) 1473 { 1474 MonSelSetCurSelMonitor(infoPtr, 1475 Index, 1476 TRUE); 1477 } 1478 break; 1479 } 1480 } 1481 } 1482 break; 1483 } 1484 1485 case WM_CHAR: 1486 { 1487 if ((infoPtr->ControlExStyle & MSLM_EX_SELECTBYNUMKEY) && 1488 wParam >= '1' && wParam <= '9') 1489 { 1490 INT Index = (INT)(wParam - '1'); 1491 if (Index < (INT)infoPtr->MonitorsCount) 1492 { 1493 MonSelSetCurSelMonitor(infoPtr, 1494 Index, 1495 TRUE); 1496 } 1497 } 1498 break; 1499 } 1500 1501 case MSLM_SETMONITORSINFO: 1502 { 1503 Ret = MonSelSetMonitorsInfo(infoPtr, 1504 (DWORD)wParam, 1505 (const MONSL_MONINFO *)lParam); 1506 break; 1507 } 1508 1509 case MSLM_GETMONITORSINFO: 1510 { 1511 Ret = MonSelGetMonitorsInfo(infoPtr, 1512 (DWORD)wParam, 1513 (PMONSL_MONINFO)lParam); 1514 break; 1515 } 1516 1517 case MSLM_GETMONITORINFOCOUNT: 1518 { 1519 Ret = infoPtr->MonitorsCount; 1520 break; 1521 } 1522 1523 case MSLM_HITTEST: 1524 { 1525 Ret = MonSelHitTest(infoPtr, 1526 (const POINT *)wParam); 1527 break; 1528 } 1529 1530 case MSLM_SETCURSEL: 1531 { 1532 Ret = MonSelSetCurSelMonitor(infoPtr, 1533 (INT)wParam, 1534 FALSE); 1535 break; 1536 } 1537 1538 case MSLM_GETCURSEL: 1539 { 1540 Ret = infoPtr->SelectedMonitor; 1541 break; 1542 } 1543 1544 case MSLM_SETMONITORINFO: 1545 { 1546 Ret = MonSelSetMonitorInfo(infoPtr, 1547 (INT)wParam, 1548 (const MONSL_MONINFO *)lParam); 1549 break; 1550 } 1551 1552 case MSLM_GETMONITORINFO: 1553 { 1554 Ret = MonSelGetMonitorInfo(infoPtr, 1555 (INT)wParam, 1556 (PMONSL_MONINFO)lParam); 1557 break; 1558 } 1559 1560 case MSLM_SETEXSTYLE: 1561 { 1562 Ret = MonSelSetExtendedStyle(infoPtr, 1563 (DWORD)lParam); 1564 break; 1565 } 1566 1567 case MSLM_GETEXSTYLE: 1568 { 1569 Ret = MonSelGetExtendedStyle(infoPtr); 1570 break; 1571 } 1572 1573 case MSLM_GETMONITORRECT: 1574 { 1575 Ret = (LRESULT)MonSelGetMonitorRect(infoPtr, 1576 (INT)wParam, 1577 (PRECT)lParam); 1578 break; 1579 } 1580 1581 case WM_CREATE: 1582 { 1583 infoPtr = (PMONITORSELWND)HeapAlloc(GetProcessHeap(), 1584 0, 1585 sizeof(MONITORSELWND)); 1586 if (infoPtr == NULL) 1587 { 1588 Ret = (LRESULT)-1; 1589 break; 1590 } 1591 1592 ZeroMemory(infoPtr, 1593 sizeof(MONITORSELWND)); 1594 infoPtr->hSelf = hwnd; 1595 infoPtr->hNotify = ((LPCREATESTRUCTW)lParam)->hwndParent; 1596 infoPtr->Enabled = !(((LPCREATESTRUCTW)lParam)->style & WS_DISABLED); 1597 infoPtr->UIState = SendMessage(hwnd, 1598 WM_QUERYUISTATE, 1599 0, 1600 0); 1601 1602 SetWindowLongPtrW(hwnd, 1603 0, 1604 (LONG_PTR)infoPtr); 1605 1606 MonSelCreate(infoPtr); 1607 break; 1608 } 1609 1610 case WM_DESTROY: 1611 { 1612 MonSelDestroy(infoPtr); 1613 1614 HeapFree(GetProcessHeap(), 1615 0, 1616 infoPtr); 1617 SetWindowLongPtrW(hwnd, 1618 0, 1619 (DWORD_PTR)NULL); 1620 break; 1621 } 1622 1623 default: 1624 { 1625 HandleDefaultMessage: 1626 Ret = DefWindowProcW(hwnd, 1627 uMsg, 1628 wParam, 1629 lParam); 1630 break; 1631 } 1632 } 1633 1634 return Ret; 1635 } 1636 1637 BOOL 1638 RegisterMonitorSelectionControl(IN HINSTANCE hInstance) 1639 { 1640 WNDCLASS wc = {0}; 1641 1642 wc.style = CS_DBLCLKS; 1643 wc.lpfnWndProc = MonitorSelWndProc; 1644 wc.cbWndExtra = sizeof(PMONITORSELWND); 1645 wc.hInstance = hInstance; 1646 wc.hCursor = LoadCursorW(NULL, 1647 (LPWSTR)IDC_ARROW); 1648 wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); 1649 wc.lpszClassName = szMonitorSelWndClass; 1650 1651 return RegisterClass(&wc) != 0; 1652 } 1653 1654 VOID 1655 UnregisterMonitorSelectionControl(IN HINSTANCE hInstance) 1656 { 1657 UnregisterClassW(szMonitorSelWndClass, 1658 hInstance); 1659 } 1660