3 static const TCHAR szMonitorSelWndClass
[] = TEXT("MONITORSELWNDCLASS");
5 typedef struct _MONSL_MON
10 } MONSL_MON
, *PMONSL_MON
;
12 typedef struct _MONITORSELWND
21 DWORD dwInternalFlags
;
28 UINT IsDraggingMonitor
: 1;
36 POINT ptDrag
, ptDragBegin
;
38 PMONSL_MONINFO MonitorInfo
;
46 HBITMAP hbmDisabledPattern
;
48 } MONITORSELWND
, *PMONITORSELWND
;
51 MonSelNotify(IN PMONITORSELWND infoPtr
,
57 if (infoPtr
->hNotify
!= NULL
)
59 LPNMHDR pnmh
= (LPNMHDR
)data
;
61 pnmh
->hwndFrom
= infoPtr
->hSelf
;
62 pnmh
->idFrom
= GetWindowLongPtr(infoPtr
->hSelf
,
66 Ret
= SendMessage(infoPtr
->hNotify
,
76 MonSelNotifyMonitor(IN PMONITORSELWND infoPtr
,
79 IN OUT PMONSL_MONNMHDR pmonnmh
)
81 pmonnmh
->Index
= Index
;
85 pmonnmh
->MonitorInfo
= infoPtr
->MonitorInfo
[Index
];
89 ZeroMemory(&pmonnmh
->MonitorInfo
,
90 sizeof(pmonnmh
->MonitorInfo
));
93 return MonSelNotify(infoPtr
,
99 MonSelChangeFont(IN OUT PMONITORSELWND infoPtr
,
103 HFONT hOldFont
= infoPtr
->hFont
;
104 infoPtr
->hFont
= hFont
;
108 InvalidateRect(infoPtr
->hSelf
,
117 MonSelRectToScreen(IN PMONITORSELWND infoPtr
,
119 OUT PRECT prcOnScreen
)
122 OffsetRect(prcOnScreen
,
123 -infoPtr
->ScrollPos
.x
,
124 -infoPtr
->ScrollPos
.y
);
128 MonSelScreenToPt(IN PMONITORSELWND infoPtr
,
129 IN
const POINT
*pptOnScreen
,
132 ppt
->x
= pptOnScreen
->x
+ infoPtr
->ScrollPos
.x
;
133 ppt
->y
= pptOnScreen
->y
+ infoPtr
->ScrollPos
.y
;
137 MonSelMonInfoToRect(IN
const MONSL_MONINFO
*pMonInfo
,
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
;
147 MonSelHitTest(IN PMONITORSELWND infoPtr
,
153 if (infoPtr
->CanDisplay
)
155 MonSelScreenToPt(infoPtr
,
159 for (Index
= 0; Index
< (INT
)infoPtr
->MonitorsCount
; Index
++)
161 if (PtInRect(&infoPtr
->Monitors
[Index
].rc
,
174 MonSelUpdateExtent(IN OUT PMONITORSELWND infoPtr
)
179 /* NOTE: This routine calculates the extent of all monitor coordinates.
180 These are not control coordinates! */
181 if (infoPtr
->MonitorsCount
> 0)
183 MonSelMonInfoToRect(&infoPtr
->MonitorInfo
[0],
186 for (Index
= 1; Index
< infoPtr
->MonitorsCount
; Index
++)
188 MonSelMonInfoToRect(&infoPtr
->MonitorInfo
[Index
],
191 UnionRect(&infoPtr
->rcExtent
,
198 ZeroMemory(&infoPtr
->rcExtent
,
199 sizeof(infoPtr
->rcExtent
));
204 MonSelScaleRectRelative(IN
const RECT
*prcBaseFrom
,
205 IN
const RECT
*prcFrom
,
206 IN
const RECT
*prcBaseTo
,
209 SIZE BaseFrom
, BaseTo
, From
;
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
;
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
);
225 ScaleRectSizeFit(IN
const RECT
*prcContainerRect
,
226 IN OUT PRECT prcRectToScale
)
228 SIZE ContainerSize
, RectSize
;
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
;
235 if (((RectSize
.cx
* 0xFFF) / RectSize
.cy
) < ((ContainerSize
.cx
* 0xFFF) / ContainerSize
.cy
))
237 RectSize
.cx
= (RectSize
.cx
* ((ContainerSize
.cy
* 0xFFF) / RectSize
.cy
)) / 0xFFF;
238 RectSize
.cy
= ContainerSize
.cy
;
242 RectSize
.cy
= (RectSize
.cy
* ((ContainerSize
.cx
* 0xFFF) / RectSize
.cx
)) / 0xFFF;
243 RectSize
.cx
= ContainerSize
.cx
;
246 prcRectToScale
->right
= prcRectToScale
->left
+ RectSize
.cx
;
247 prcRectToScale
->bottom
= prcRectToScale
->top
+ RectSize
.cy
;
249 OffsetRect(prcRectToScale
,
250 prcContainerRect
->left
+ ((ContainerSize
.cx
- RectSize
.cx
) / 2),
251 prcContainerRect
->top
+ ((ContainerSize
.cy
- RectSize
.cy
) / 2));
255 MonSelRepaint(IN PMONITORSELWND infoPtr
)
259 MonSelRectToScreen(infoPtr
,
260 &infoPtr
->rcMonitors
,
262 InvalidateRect(infoPtr
->hSelf
,
266 if (!EqualRect(&infoPtr
->rcMonitors
, &infoPtr
->rcOldMonitors
) &&
267 infoPtr
->rcOldMonitors
.right
!= infoPtr
->rcOldMonitors
.left
)
269 MonSelRectToScreen(infoPtr
, &infoPtr
->rcOldMonitors
, &rc
);
270 InvalidateRect(infoPtr
->hSelf
, &rc
, TRUE
);
271 infoPtr
->rcOldMonitors
= infoPtr
->rcMonitors
;
276 MonSelRepaintMonitor(IN PMONITORSELWND infoPtr
,
280 BOOL NoRepaint
= FALSE
;
282 if (Index
< infoPtr
->MonitorsCount
)
284 if (Index
== (DWORD
)infoPtr
->DraggingMonitor
)
286 if (infoPtr
->IsDraggingMonitor
)
288 MonSelRectToScreen(infoPtr
,
289 &infoPtr
->rcDragging
,
297 MonSelRectToScreen(infoPtr
,
298 &infoPtr
->Monitors
[Index
].rc
,
304 InvalidateRect(infoPtr
->hSelf
,
312 MonSelRepaintSelected(IN PMONITORSELWND infoPtr
)
314 if (infoPtr
->SelectedMonitor
>= 0)
316 MonSelRepaintMonitor(infoPtr
,
317 (DWORD
)infoPtr
->SelectedMonitor
);
322 MonSelResetMonitors(IN OUT PMONITORSELWND infoPtr
)
326 for (Index
= 0; Index
< infoPtr
->MonitorsCount
; Index
++)
328 if (infoPtr
->Monitors
[Index
].hFont
!= NULL
)
330 DeleteObject(infoPtr
->Monitors
[Index
].hFont
);
331 infoPtr
->Monitors
[Index
].hFont
= NULL
;
338 MonSelUpdateMonitorsInfo(IN OUT PMONITORSELWND infoPtr
,
341 RECT rcExtSurface
, rcExtDisplay
;
344 /* Recalculate rcExtent */
345 MonSelUpdateExtent(infoPtr
);
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
)));
351 if (infoPtr
->CanDisplay
)
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
);
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
;
364 ScaleRectSizeFit(&rcExtSurface
,
367 infoPtr
->rcOldMonitors
= infoPtr
->rcMonitors
;
368 infoPtr
->rcMonitors
= rcExtDisplay
;
370 /* Now that we know in which area all monitors are located,
371 calculate the monitors selection rectangles on the screen */
373 for (Index
= 0; Index
< infoPtr
->MonitorsCount
; Index
++)
375 MonSelMonInfoToRect(&infoPtr
->MonitorInfo
[Index
],
378 MonSelScaleRectRelative(&infoPtr
->rcExtent
,
380 &infoPtr
->rcMonitors
,
381 &infoPtr
->Monitors
[Index
].rc
);
384 MonSelResetMonitors(infoPtr
);
387 MonSelRepaint(infoPtr
);
391 InvalidateRect(infoPtr
->hSelf
,
398 MonSelSetMonitorsInfo(IN OUT PMONITORSELWND infoPtr
,
400 IN
const MONSL_MONINFO
*MonitorsInfo
)
405 if (infoPtr
->DraggingMonitor
>= 0)
408 if (infoPtr
->MonitorInfo
!= NULL
)
410 LocalFree((HLOCAL
)infoPtr
->MonitorInfo
);
411 infoPtr
->MonitorInfo
= NULL
;
413 MonSelResetMonitors(infoPtr
);
415 LocalFree((HLOCAL
)infoPtr
->Monitors
);
416 infoPtr
->Monitors
= NULL
;
418 infoPtr
->MonitorsCount
= 0;
423 infoPtr
->MonitorInfo
= (PMONSL_MONINFO
)LocalAlloc(LMEM_FIXED
,
424 dwMonitors
* sizeof(MONSL_MONINFO
));
425 if (infoPtr
->MonitorInfo
!= NULL
)
427 infoPtr
->Monitors
= (PMONSL_MON
)LocalAlloc(LMEM_FIXED
,
428 dwMonitors
* sizeof(MONSL_MON
));
429 if (infoPtr
->Monitors
!= NULL
)
431 CopyMemory(infoPtr
->MonitorInfo
,
433 dwMonitors
* sizeof(MONSL_MONINFO
));
434 ZeroMemory(infoPtr
->Monitors
,
435 dwMonitors
* sizeof(MONSL_MON
));
437 for (Index
= 0; Index
< dwMonitors
; Index
++)
439 _stprintf(infoPtr
->Monitors
[Index
].szCaption
,
444 infoPtr
->MonitorsCount
= dwMonitors
;
446 if (infoPtr
->SelectedMonitor
>= (INT
)infoPtr
->MonitorsCount
)
447 infoPtr
->SelectedMonitor
= -1;
449 if (!(infoPtr
->ControlExStyle
& MSLM_EX_ALLOWSELECTNONE
) && infoPtr
->SelectedMonitor
< 0)
450 infoPtr
->SelectedMonitor
= 0;
452 MonSelUpdateMonitorsInfo(infoPtr
,
457 LocalFree((HLOCAL
)infoPtr
->MonitorInfo
);
458 infoPtr
->MonitorInfo
= NULL
;
468 infoPtr
->SelectedMonitor
= -1;
470 if (!Ret
|| dwMonitors
== 0)
472 InvalidateRect(infoPtr
->hSelf
,
481 MonSelGetMonitorsInfo(IN PMONITORSELWND infoPtr
,
483 IN OUT PMONSL_MONINFO MonitorsInfo
)
487 if (dwMonitors
> infoPtr
->MonitorsCount
)
488 dwMonitors
= infoPtr
->MonitorsCount
;
490 CopyMemory(MonitorsInfo
,
491 infoPtr
->MonitorInfo
,
492 dwMonitors
* sizeof(MONSL_MONINFO
));
496 return infoPtr
->MonitorsCount
;
500 MonSelSetMonitorInfo(IN OUT PMONITORSELWND infoPtr
,
502 IN
const MONSL_MONINFO
*MonitorsInfo
)
504 if (infoPtr
->DraggingMonitor
< 0 &&
505 Index
>= 0 && Index
< (INT
)infoPtr
->MonitorsCount
)
507 CopyMemory(&infoPtr
->MonitorInfo
[Index
],
509 sizeof(MONSL_MONINFO
));
511 MonSelUpdateMonitorsInfo(infoPtr
,
520 MonSelGetMonitorInfo(IN PMONITORSELWND infoPtr
,
522 IN OUT PMONSL_MONINFO MonitorsInfo
)
524 if (Index
>= 0 && Index
< (INT
)infoPtr
->MonitorsCount
)
526 CopyMemory(MonitorsInfo
,
527 &infoPtr
->MonitorInfo
[Index
],
528 sizeof(MONSL_MONINFO
));
536 MonSelGetMonitorRect(IN OUT PMONITORSELWND infoPtr
,
542 if (Index
< 0 || (UINT
)Index
>= infoPtr
->MonitorsCount
)
545 if (!infoPtr
->CanDisplay
)
548 MonSelRectToScreen(infoPtr
,
549 &infoPtr
->Monitors
[Index
].rc
,
552 rcClient
.left
= rcClient
.top
= 0;
553 rcClient
.right
= infoPtr
->ClientSize
.cx
;
554 rcClient
.bottom
= infoPtr
->ClientSize
.cy
;
556 return IntersectRect(&rc
,
562 MonSelSetCurSelMonitor(IN OUT PMONITORSELWND infoPtr
,
567 BOOL PreventSelect
= FALSE
;
570 if (infoPtr
->DraggingMonitor
< 0 &&
571 (Index
== -1 || Index
< (INT
)infoPtr
->MonitorsCount
))
573 if (Index
!= infoPtr
->SelectedMonitor
)
575 if ((infoPtr
->MonitorInfo
[Index
].Flags
& MSL_MIF_DISABLED
) &&
576 !(infoPtr
->ControlExStyle
& MSLM_EX_ALLOWSELECTDISABLED
))
578 PreventSelect
= TRUE
;
581 if (!PreventSelect
&& bNotify
)
583 MONSL_MONNMMONITORCHANGING nmi
;
585 nmi
.PreviousSelected
= infoPtr
->SelectedMonitor
;
586 nmi
.AllowChanging
= TRUE
;
588 MonSelNotifyMonitor(infoPtr
,
589 MSLN_MONITORCHANGING
,
593 PreventSelect
= (nmi
.AllowChanging
== FALSE
);
598 PrevSel
= infoPtr
->SelectedMonitor
;
599 infoPtr
->SelectedMonitor
= Index
;
603 MonSelRepaintMonitor(infoPtr
,
607 if (infoPtr
->SelectedMonitor
>= 0)
608 MonSelRepaintSelected(infoPtr
);
614 MonSelNotifyMonitor(infoPtr
,
629 MonSelCreate(IN OUT PMONITORSELWND infoPtr
)
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
;
641 MonSelDestroy(IN OUT PMONITORSELWND infoPtr
)
643 /* Free all monitors */
644 MonSelSetMonitorsInfo(infoPtr
,
648 if (infoPtr
->hbrDisabled
!= NULL
)
650 DeleteObject(infoPtr
->hbrDisabled
);
651 infoPtr
->hbrDisabled
= NULL
;
654 if (infoPtr
->hbmDisabledPattern
!= NULL
)
656 DeleteObject(infoPtr
->hbmDisabledPattern
);
657 infoPtr
->hbmDisabledPattern
= NULL
;
662 MonSelSetExtendedStyle(IN OUT PMONITORSELWND infoPtr
,
663 IN DWORD dwExtendedStyle
)
665 if (infoPtr
->DraggingMonitor
>= 0)
668 if (dwExtendedStyle
!= infoPtr
->ControlExStyle
)
670 infoPtr
->ControlExStyle
= dwExtendedStyle
;
672 /* Repaint the control */
673 InvalidateRect(infoPtr
->hSelf
,
682 MonSelGetExtendedStyle(IN PMONITORSELWND infoPtr
)
684 return infoPtr
->ControlExStyle
;
688 MonSelGetMonitorFont(IN OUT PMONITORSELWND infoPtr
,
695 HFONT hPrevFont
, hFont
;
698 hFont
= infoPtr
->Monitors
[Index
].hFont
;
700 GetObject(infoPtr
->hFont
,
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;
710 //len = _tcslen(infoPtr->Monitors[Index].szCaption);
712 hPrevFont
= SelectObject(hDC
,
715 if (GetTextMetrics(hDC
,
718 lf
.lfWeight
= FW_SEMIBOLD
;
719 lf
.lfHeight
= -MulDiv(rcsize
.cy
- tm
.tmExternalLeading
,
724 hFont
= CreateFontIndirect(&lf
);
726 infoPtr
->Monitors
[Index
].hFont
= hFont
;
737 MonSelDrawDisabledRect(IN OUT PMONITORSELWND infoPtr
,
743 if (infoPtr
->hbrDisabled
== NULL
)
745 static const DWORD Pattern
[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
747 if (infoPtr
->hbmDisabledPattern
== NULL
)
749 infoPtr
->hbmDisabledPattern
= CreateBitmap(8,
756 if (infoPtr
->hbmDisabledPattern
!= NULL
)
757 infoPtr
->hbrDisabled
= CreatePatternBrush(infoPtr
->hbmDisabledPattern
);
760 if (infoPtr
->hbrDisabled
!= NULL
)
762 /* FIXME: Implement */
769 MonSelPaintMonitor(IN OUT PMONITORSELWND infoPtr
,
773 IN COLORREF crDefFontColor
,
776 HFONT hFont
, hPrevFont
;
779 if ((INT
)Index
== infoPtr
->SelectedMonitor
)
783 (HBRUSH
)(COLOR_HIGHLIGHT
+ 1));
785 if (infoPtr
->HasFocus
&& !(infoPtr
->UIState
& UISF_HIDEFOCUS
))
787 /* NOTE: We need to switch the text color to the default, because
788 DrawFocusRect draws a solid line if the text is white! */
790 crPrevText
= SetTextColor(hDC
,
802 -infoPtr
->SelectionFrame
.cx
,
803 -infoPtr
->SelectionFrame
.cy
);
817 hFont
= MonSelGetMonitorFont(infoPtr
,
822 hPrevFont
= SelectObject(hDC
,
826 infoPtr
->Monitors
[Index
].szCaption
,
829 DT_VCENTER
| DT_CENTER
| DT_NOPREFIX
| DT_SINGLELINE
);
836 if (infoPtr
->MonitorInfo
[Index
].Flags
& MSL_MIF_DISABLED
)
842 MonSelDrawDisabledRect(infoPtr
,
849 MonSelPaint(IN OUT PMONITORSELWND infoPtr
,
851 IN
const RECT
*prcUpdate
)
854 HBRUSH hbBk
, hbOldBk
;
861 bHideNumber
= (infoPtr
->ControlExStyle
& MSLM_EX_HIDENUMBERS
) ||
862 ((infoPtr
->MonitorsCount
== 1) && (infoPtr
->ControlExStyle
& MSLM_EX_HIDENUMBERONSINGLE
));
864 hbBk
= GetSysColorBrush(COLOR_BACKGROUND
);
865 hpFg
= CreatePen(PS_SOLID
,
867 GetSysColor(COLOR_HIGHLIGHTTEXT
));
869 hbOldBk
= SelectObject(hDC
,
871 hpOldFg
= SelectObject(hDC
,
873 iPrevBkMode
= SetBkMode(hDC
,
875 crPrevText
= SetTextColor(hDC
,
876 GetSysColor(COLOR_HIGHLIGHTTEXT
));
878 for (Index
= 0; Index
< infoPtr
->MonitorsCount
; Index
++)
880 if (infoPtr
->IsDraggingMonitor
&&
881 (DWORD
)infoPtr
->DraggingMonitor
== Index
)
886 MonSelRectToScreen(infoPtr
,
887 &infoPtr
->Monitors
[Index
].rc
,
890 if (IntersectRect(&rctmp
,
894 MonSelPaintMonitor(infoPtr
,
903 /* Paint the dragging monitor last */
904 if (infoPtr
->IsDraggingMonitor
&&
905 infoPtr
->DraggingMonitor
>= 0)
907 MonSelRectToScreen(infoPtr
,
908 &infoPtr
->rcDragging
,
911 if (IntersectRect(&rctmp
,
915 MonSelPaintMonitor(infoPtr
,
917 (DWORD
)infoPtr
->DraggingMonitor
,
937 MonSelContextMenu(IN OUT PMONITORSELWND infoPtr
,
941 MONSL_MONNMBUTTONCLICKED nm
;
944 if (!infoPtr
->HasFocus
)
945 SetFocus(infoPtr
->hSelf
);
950 Index
= MonSelHitTest(infoPtr
,
953 MonSelNotifyMonitor(infoPtr
,
956 (PMONSL_MONNMHDR
)&nm
);
958 /* Send a WM_CONTEXTMENU notification */
959 MapWindowPoints(infoPtr
->hSelf
,
964 SendMessage(infoPtr
->hSelf
,
966 (WPARAM
)infoPtr
->hSelf
,
972 MonSelApplyCursorClipping(IN PMONITORSELWND infoPtr
,
979 rc
.left
= rc
.top
= 0;
980 rc
.right
= infoPtr
->ClientSize
.cx
;
981 rc
.bottom
= infoPtr
->ClientSize
.cy
;
983 if (MapWindowPoints(infoPtr
->hSelf
,
998 MonSelMoveDragRect(IN OUT PMONITORSELWND infoPtr
,
1001 RECT rcPrev
, rcUpdate
, *prc
;
1005 if (infoPtr
->CanDisplay
)
1007 hDC
= GetDC(infoPtr
->hSelf
);
1010 if (infoPtr
->ptDrag
.x
!= ppt
->x
||
1011 infoPtr
->ptDrag
.y
!= ppt
->y
)
1013 infoPtr
->ptDrag
= *ppt
;
1015 rcPrev
= infoPtr
->rcDragging
;
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
);
1024 hRgnPrev
= CreateRectRgn(rcPrev
.left
,
1029 if (hRgnPrev
!= NULL
)
1032 infoPtr
->rcDragging
.left
- rcPrev
.left
,
1033 infoPtr
->rcDragging
.top
- rcPrev
.top
,
1038 !InvalidateRgn(infoPtr
->hSelf
,
1042 DeleteObject(hRgnPrev
);
1046 DeleteObject(hRgnPrev
);
1051 InvalidateRect(infoPtr
->hSelf
,
1054 InvalidateRect(infoPtr
->hSelf
,
1055 &infoPtr
->rcDragging
,
1060 ReleaseDC(infoPtr
->hSelf
,
1067 MonSelCancelDragging(IN OUT PMONITORSELWND infoPtr
)
1071 if (infoPtr
->DraggingMonitor
>= 0)
1073 MonSelMoveDragRect(infoPtr
,
1074 &infoPtr
->ptDragBegin
);
1076 Index
= (DWORD
)infoPtr
->DraggingMonitor
;
1077 infoPtr
->DraggingMonitor
= -1;
1079 if (infoPtr
->CanDisplay
)
1081 /* Repaint the area where the monitor was last dragged */
1082 MonSelRepaintMonitor(infoPtr
,
1085 infoPtr
->IsDraggingMonitor
= FALSE
;
1087 /* Repaint the area where the monitor is located */
1088 MonSelRepaintMonitor(infoPtr
,
1092 infoPtr
->IsDraggingMonitor
= FALSE
;
1096 MonSelApplyCursorClipping(infoPtr
,
1102 MonSelInitDragging(IN OUT PMONITORSELWND infoPtr
,
1108 MonSelCancelDragging(infoPtr
);
1109 infoPtr
->IsDraggingMonitor
= FALSE
;
1111 MonSelScreenToPt(infoPtr
,
1115 infoPtr
->ptDrag
= infoPtr
->ptDragBegin
= pt
;
1116 infoPtr
->DraggingMonitor
= (INT
)Index
;
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
;
1122 MonSelApplyCursorClipping(infoPtr
,
1127 MonSelDrag(IN OUT PMONITORSELWND infoPtr
,
1134 if (infoPtr
->DraggingMonitor
>= 0)
1136 MonSelScreenToPt(infoPtr
,
1140 if (!infoPtr
->IsDraggingMonitor
)
1142 szDrag
.cx
= GetSystemMetrics(SM_CXDRAG
);
1143 szDrag
.cy
= GetSystemMetrics(SM_CYDRAG
);
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
;
1150 if (!PtInRect(&rcDrag
,
1153 /* The user started moving around the mouse: Begin dragging */
1154 infoPtr
->IsDraggingMonitor
= TRUE
;
1155 MonSelMoveDragRect(infoPtr
,
1161 MonSelMoveDragRect(infoPtr
,
1167 static LRESULT CALLBACK
1168 MonitorSelWndProc(IN HWND hwnd
,
1173 PMONITORSELWND infoPtr
;
1176 infoPtr
= (PMONITORSELWND
)GetWindowLongPtrW(hwnd
,
1179 if (infoPtr
== NULL
&& uMsg
!= WM_CREATE
)
1181 goto HandleDefaultMessage
;
1187 case WM_PRINTCLIENT
:
1194 if (!GetUpdateRect(hwnd
,
1204 hDC
= BeginPaint(hwnd
,
1212 if (infoPtr
->CanDisplay
)
1214 MonSelPaint(infoPtr
,
1231 if (!(wParam
& MK_LBUTTON
))
1233 MonSelCancelDragging(infoPtr
);
1237 if (infoPtr
->LeftBtnDown
)
1239 pt
.x
= (LONG
)LOWORD(lParam
);
1240 pt
.y
= (LONG
)HIWORD(lParam
);
1249 case WM_RBUTTONDOWN
:
1251 if (!(infoPtr
->ControlExStyle
& MSLM_EX_SELECTONRIGHTCLICK
))
1257 case WM_LBUTTONDBLCLK
:
1258 case WM_LBUTTONDOWN
:
1263 if (!infoPtr
->HasFocus
)
1264 SetFocus(infoPtr
->hSelf
);
1266 pt
.x
= (LONG
)LOWORD(lParam
);
1267 pt
.y
= (LONG
)HIWORD(lParam
);
1269 Index
= MonSelHitTest(infoPtr
,
1271 if (Index
>= 0 || (infoPtr
->ControlExStyle
& MSLM_EX_ALLOWSELECTNONE
))
1273 MonSelSetCurSelMonitor(infoPtr
,
1278 if (Index
>= 0 && (uMsg
== WM_LBUTTONDOWN
|| uMsg
== WM_LBUTTONDBLCLK
))
1280 infoPtr
->LeftBtnDown
= TRUE
;
1281 MonSelInitDragging(infoPtr
,
1289 case WM_MBUTTONDOWN
:
1291 if (!infoPtr
->HasFocus
)
1298 MonSelContextMenu(infoPtr
,
1299 (SHORT
)LOWORD(lParam
),
1300 (SHORT
)HIWORD(lParam
));
1306 MonSelCancelDragging(infoPtr
);
1307 infoPtr
->LeftBtnDown
= FALSE
;
1315 virtKey
= (lParam
!= 0 ? (INT
)((LPMSG
)lParam
)->wParam
: 0);
1320 /* Change the UI status */
1321 SendMessage(GetAncestor(hwnd
,
1324 MAKEWPARAM(UIS_INITIALIZE
,
1331 Ret
|= DLGC_WANTARROWS
;
1333 if (infoPtr
->ControlExStyle
& MSLM_EX_SELECTBYNUMKEY
)
1334 Ret
|= DLGC_WANTCHARS
;
1340 infoPtr
->HasFocus
= TRUE
;
1341 MonSelRepaintSelected(infoPtr
);
1347 infoPtr
->HasFocus
= FALSE
;
1348 MonSelCancelDragging(infoPtr
);
1349 MonSelRepaintSelected(infoPtr
);
1353 case WM_UPDATEUISTATE
:
1357 Ret
= DefWindowProcW(hwnd
,
1362 OldUIState
= infoPtr
->UIState
;
1363 switch (LOWORD(wParam
))
1366 infoPtr
->UIState
|= HIWORD(wParam
);
1370 infoPtr
->UIState
&= ~HIWORD(wParam
);
1374 if (infoPtr
->UIState
!= OldUIState
)
1375 MonSelRepaintSelected(infoPtr
);
1381 Ret
= (LRESULT
)MonSelChangeFont(infoPtr
,
1383 (BOOL
)LOWORD(lParam
));
1389 infoPtr
->ClientSize
.cx
= LOWORD(lParam
);
1390 infoPtr
->ClientSize
.cy
= HIWORD(lParam
);
1392 /* Don't let MonSelUpdateMonitorsInfo repaint the control
1393 because this won't work properly in case the control
1395 MonSelUpdateMonitorsInfo(infoPtr
,
1397 InvalidateRect(infoPtr
->hSelf
,
1405 Ret
= (LRESULT
)infoPtr
->hFont
;
1411 infoPtr
->Enabled
= ((BOOL
)wParam
!= FALSE
);
1412 MonSelRepaint(infoPtr
);
1416 case WM_STYLECHANGED
:
1418 if (wParam
== GWL_STYLE
)
1420 unsigned int OldEnabled
= infoPtr
->Enabled
;
1421 infoPtr
->Enabled
= !(((LPSTYLESTRUCT
)lParam
)->styleNew
& WS_DISABLED
);
1423 if (OldEnabled
!= infoPtr
->Enabled
)
1424 MonSelRepaint(infoPtr
);
1433 if (infoPtr
->ControlExStyle
& MSLM_EX_SELECTBYARROWKEY
)
1440 Index
= infoPtr
->SelectedMonitor
;
1442 if (infoPtr
->MonitorsCount
!= 0)
1452 MonSelSetCurSelMonitor(infoPtr
,
1462 Index
= infoPtr
->SelectedMonitor
;
1464 if (infoPtr
->MonitorsCount
!= 0)
1467 Index
= (INT
)infoPtr
->MonitorsCount
- 1;
1468 else if (Index
< (INT
)infoPtr
->MonitorsCount
- 1)
1472 if (infoPtr
->SelectedMonitor
< (INT
)infoPtr
->MonitorsCount
)
1474 MonSelSetCurSelMonitor(infoPtr
,
1487 if ((infoPtr
->ControlExStyle
& MSLM_EX_SELECTBYNUMKEY
) &&
1488 wParam
>= '1' && wParam
<= '9')
1490 INT Index
= (INT
)(wParam
- '1');
1491 if (Index
< (INT
)infoPtr
->MonitorsCount
)
1493 MonSelSetCurSelMonitor(infoPtr
,
1501 case MSLM_SETMONITORSINFO
:
1503 Ret
= MonSelSetMonitorsInfo(infoPtr
,
1505 (const MONSL_MONINFO
*)lParam
);
1509 case MSLM_GETMONITORSINFO
:
1511 Ret
= MonSelGetMonitorsInfo(infoPtr
,
1513 (PMONSL_MONINFO
)lParam
);
1517 case MSLM_GETMONITORINFOCOUNT
:
1519 Ret
= infoPtr
->MonitorsCount
;
1525 Ret
= MonSelHitTest(infoPtr
,
1526 (const POINT
*)wParam
);
1530 case MSLM_SETCURSEL
:
1532 Ret
= MonSelSetCurSelMonitor(infoPtr
,
1538 case MSLM_GETCURSEL
:
1540 Ret
= infoPtr
->SelectedMonitor
;
1544 case MSLM_SETMONITORINFO
:
1546 Ret
= MonSelSetMonitorInfo(infoPtr
,
1548 (const MONSL_MONINFO
*)lParam
);
1552 case MSLM_GETMONITORINFO
:
1554 Ret
= MonSelGetMonitorInfo(infoPtr
,
1556 (PMONSL_MONINFO
)lParam
);
1560 case MSLM_SETEXSTYLE
:
1562 Ret
= MonSelSetExtendedStyle(infoPtr
,
1567 case MSLM_GETEXSTYLE
:
1569 Ret
= MonSelGetExtendedStyle(infoPtr
);
1573 case MSLM_GETMONITORRECT
:
1575 Ret
= (LRESULT
)MonSelGetMonitorRect(infoPtr
,
1583 infoPtr
= (PMONITORSELWND
)HeapAlloc(GetProcessHeap(),
1585 sizeof(MONITORSELWND
));
1586 if (infoPtr
== NULL
)
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
,
1602 SetWindowLongPtrW(hwnd
,
1606 MonSelCreate(infoPtr
);
1612 MonSelDestroy(infoPtr
);
1614 HeapFree(GetProcessHeap(),
1617 SetWindowLongPtrW(hwnd
,
1625 HandleDefaultMessage
:
1626 Ret
= DefWindowProcW(hwnd
,
1638 RegisterMonitorSelectionControl(IN HINSTANCE hInstance
)
1642 wc
.style
= CS_DBLCLKS
;
1643 wc
.lpfnWndProc
= MonitorSelWndProc
;
1644 wc
.cbWndExtra
= sizeof(PMONITORSELWND
);
1645 wc
.hInstance
= hInstance
;
1646 wc
.hCursor
= LoadCursorW(NULL
,
1648 wc
.hbrBackground
= (HBRUSH
)(COLOR_APPWORKSPACE
+ 1);
1649 wc
.lpszClassName
= szMonitorSelWndClass
;
1651 return RegisterClass(&wc
) != 0;
1655 UnregisterMonitorSelectionControl(IN HINSTANCE hInstance
)
1657 UnregisterClassW(szMonitorSelWndClass
,