4 static const TCHAR szMonitorSelWndClass
[] = TEXT("MONITORSELWNDCLASS");
6 typedef struct _MONSL_MON
11 } MONSL_MON
, *PMONSL_MON
;
13 typedef struct _MONITORSELWND
22 DWORD dwInternalFlags
;
29 UINT IsDraggingMonitor
: 1;
37 POINT ptDrag
, ptDragBegin
;
39 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
,
268 MonSelRepaintMonitor(IN PMONITORSELWND infoPtr
,
272 BOOL NoRepaint
= FALSE
;
274 if (Index
< infoPtr
->MonitorsCount
)
276 if (Index
== (DWORD
)infoPtr
->DraggingMonitor
)
278 if (infoPtr
->IsDraggingMonitor
)
280 MonSelRectToScreen(infoPtr
,
281 &infoPtr
->rcDragging
,
289 MonSelRectToScreen(infoPtr
,
290 &infoPtr
->Monitors
[Index
].rc
,
296 InvalidateRect(infoPtr
->hSelf
,
304 MonSelRepaintSelected(IN PMONITORSELWND infoPtr
)
306 if (infoPtr
->SelectedMonitor
>= 0)
308 MonSelRepaintMonitor(infoPtr
,
309 (DWORD
)infoPtr
->SelectedMonitor
);
314 MonSelResetMonitors(IN OUT PMONITORSELWND infoPtr
)
318 for (Index
= 0; Index
< infoPtr
->MonitorsCount
; Index
++)
320 if (infoPtr
->Monitors
[Index
].hFont
!= NULL
)
322 DeleteObject(infoPtr
->Monitors
[Index
].hFont
);
323 infoPtr
->Monitors
[Index
].hFont
= NULL
;
330 MonSelUpdateMonitorsInfo(IN OUT PMONITORSELWND infoPtr
,
333 RECT rcExtSurface
, rcExtDisplay
;
336 /* Recalculate rcExtent */
337 MonSelUpdateExtent(infoPtr
);
339 infoPtr
-> CanDisplay
= infoPtr
->MonitorsCount
!= 0 &&
340 (infoPtr
->ClientSize
.cx
> (2 * (infoPtr
->Margin
.cx
+ infoPtr
->SelectionFrame
.cx
))) &&
341 (infoPtr
->ClientSize
.cy
> (2 * (infoPtr
->Margin
.cy
+ infoPtr
->SelectionFrame
.cy
)));
343 if (infoPtr
->CanDisplay
)
345 /* Calculate the rectangle on the control in which may be painted */
346 rcExtSurface
.left
= infoPtr
->Margin
.cx
;
347 rcExtSurface
.top
= infoPtr
->Margin
.cy
;
348 rcExtSurface
.right
= rcExtSurface
.left
+ infoPtr
->ClientSize
.cx
- (2 * infoPtr
->Margin
.cx
);
349 rcExtSurface
.bottom
= rcExtSurface
.top
+ infoPtr
->ClientSize
.cy
- (2 * infoPtr
->Margin
.cy
);
351 /* Calculate the rectangle on the control that is actually painted on */
352 rcExtDisplay
.left
= rcExtDisplay
.top
= 0;
353 rcExtDisplay
.right
= infoPtr
->rcExtent
.right
- infoPtr
->rcExtent
.left
;
354 rcExtDisplay
.bottom
= infoPtr
->rcExtent
.bottom
- infoPtr
->rcExtent
.top
;
356 ScaleRectSizeFit(&rcExtSurface
,
359 infoPtr
->rcMonitors
= rcExtDisplay
;
361 /* Now that we know in which area all monitors are located,
362 calculate the monitors selection rectangles on the screen */
364 for (Index
= 0; Index
< infoPtr
->MonitorsCount
; Index
++)
366 MonSelMonInfoToRect(&infoPtr
->MonitorInfo
[Index
],
369 MonSelScaleRectRelative(&infoPtr
->rcExtent
,
371 &infoPtr
->rcMonitors
,
372 &infoPtr
->Monitors
[Index
].rc
);
375 MonSelResetMonitors(infoPtr
);
378 MonSelRepaint(infoPtr
);
382 InvalidateRect(infoPtr
->hSelf
,
389 MonSelSetMonitorsInfo(IN OUT PMONITORSELWND infoPtr
,
391 IN
const MONSL_MONINFO
*MonitorsInfo
)
396 if (infoPtr
->DraggingMonitor
>= 0)
399 if (infoPtr
->MonitorInfo
!= NULL
)
401 LocalFree((HLOCAL
)infoPtr
->MonitorInfo
);
402 infoPtr
->MonitorInfo
= NULL
;
404 MonSelResetMonitors(infoPtr
);
406 LocalFree((HLOCAL
)infoPtr
->Monitors
);
407 infoPtr
->Monitors
= NULL
;
409 infoPtr
->MonitorsCount
= 0;
414 infoPtr
->MonitorInfo
= (PMONSL_MONINFO
)LocalAlloc(LMEM_FIXED
,
415 dwMonitors
* sizeof(MONSL_MONINFO
));
416 if (infoPtr
->MonitorInfo
!= NULL
)
418 infoPtr
->Monitors
= (PMONSL_MON
)LocalAlloc(LMEM_FIXED
,
419 dwMonitors
* sizeof(MONSL_MON
));
420 if (infoPtr
->Monitors
!= NULL
)
422 CopyMemory(infoPtr
->MonitorInfo
,
424 dwMonitors
* sizeof(MONSL_MONINFO
));
425 ZeroMemory(infoPtr
->Monitors
,
426 dwMonitors
* sizeof(MONSL_MON
));
428 for (Index
= 0; Index
< dwMonitors
; Index
++)
430 _stprintf(infoPtr
->Monitors
[Index
].szCaption
,
435 infoPtr
->MonitorsCount
= dwMonitors
;
437 if (infoPtr
->SelectedMonitor
>= (INT
)infoPtr
->MonitorsCount
)
438 infoPtr
->SelectedMonitor
= -1;
440 if (!(infoPtr
->ControlExStyle
& MSLM_EX_ALLOWSELECTNONE
) && infoPtr
->SelectedMonitor
< 0)
441 infoPtr
->SelectedMonitor
= 0;
443 MonSelUpdateMonitorsInfo(infoPtr
,
448 LocalFree((HLOCAL
)infoPtr
->MonitorInfo
);
449 infoPtr
->MonitorInfo
= NULL
;
459 infoPtr
->SelectedMonitor
= -1;
461 if (!Ret
|| dwMonitors
== 0)
463 InvalidateRect(infoPtr
->hSelf
,
472 MonSelGetMonitorsInfo(IN PMONITORSELWND infoPtr
,
474 IN OUT PMONSL_MONINFO MonitorsInfo
)
478 if (dwMonitors
> infoPtr
->MonitorsCount
)
479 dwMonitors
= infoPtr
->MonitorsCount
;
481 CopyMemory(MonitorsInfo
,
482 infoPtr
->MonitorInfo
,
483 dwMonitors
* sizeof(MONSL_MONINFO
));
487 return infoPtr
->MonitorsCount
;
491 MonSelSetMonitorInfo(IN OUT PMONITORSELWND infoPtr
,
493 IN
const MONSL_MONINFO
*MonitorsInfo
)
495 if (infoPtr
->DraggingMonitor
< 0 &&
496 Index
>= 0 && Index
< (INT
)infoPtr
->MonitorsCount
)
498 CopyMemory(&infoPtr
->MonitorInfo
[Index
],
500 sizeof(MONSL_MONINFO
));
502 MonSelUpdateMonitorsInfo(infoPtr
,
511 MonSelGetMonitorInfo(IN PMONITORSELWND infoPtr
,
513 IN OUT PMONSL_MONINFO MonitorsInfo
)
515 if (Index
>= 0 && Index
< (INT
)infoPtr
->MonitorsCount
)
517 CopyMemory(MonitorsInfo
,
518 &infoPtr
->MonitorInfo
[Index
],
519 sizeof(MONSL_MONINFO
));
527 MonSelGetMonitorRect(IN OUT PMONITORSELWND infoPtr
,
533 if (Index
< 0 || Index
>= infoPtr
->MonitorsCount
)
536 if (!infoPtr
->CanDisplay
)
539 MonSelRectToScreen(infoPtr
,
540 &infoPtr
->Monitors
[Index
].rc
,
543 rcClient
.left
= rcClient
.top
= 0;
544 rcClient
.right
= infoPtr
->ClientSize
.cx
;
545 rcClient
.bottom
= infoPtr
->ClientSize
.cy
;
547 return IntersectRect(&rc
,
553 MonSelSetCurSelMonitor(IN OUT PMONITORSELWND infoPtr
,
558 BOOL PreventSelect
= FALSE
;
561 if (infoPtr
->DraggingMonitor
< 0 &&
562 (Index
== -1 || Index
< (INT
)infoPtr
->MonitorsCount
))
564 if (Index
!= infoPtr
->SelectedMonitor
)
566 if ((infoPtr
->MonitorInfo
[Index
].Flags
& MSL_MIF_DISABLED
) &&
567 !(infoPtr
->ControlExStyle
& MSLM_EX_ALLOWSELECTDISABLED
))
569 PreventSelect
= TRUE
;
572 if (!PreventSelect
&& bNotify
)
574 MONSL_MONNMMONITORCHANGING nmi
;
576 nmi
.PreviousSelected
= infoPtr
->SelectedMonitor
;
577 nmi
.AllowChanging
= TRUE
;
579 MonSelNotifyMonitor(infoPtr
,
580 MSLN_MONITORCHANGING
,
584 PreventSelect
= (nmi
.AllowChanging
== FALSE
);
589 PrevSel
= infoPtr
->SelectedMonitor
;
590 infoPtr
->SelectedMonitor
= Index
;
594 MonSelRepaintMonitor(infoPtr
,
598 if (infoPtr
->SelectedMonitor
>= 0)
599 MonSelRepaintSelected(infoPtr
);
605 MonSelNotifyMonitor(infoPtr
,
620 MonSelCreate(IN OUT PMONITORSELWND infoPtr
)
622 infoPtr
->SelectionFrame
.cx
= infoPtr
->SelectionFrame
.cy
= 4;
623 infoPtr
->Margin
.cx
= infoPtr
->Margin
.cy
= 20;
624 infoPtr
->SelectedMonitor
= -1;
625 infoPtr
->DraggingMonitor
= -1;
626 infoPtr
->ControlExStyle
= MSLM_EX_ALLOWSELECTDISABLED
| MSLM_EX_HIDENUMBERONSINGLE
|
627 MSLM_EX_SELECTONRIGHTCLICK
| MSLM_EX_SELECTBYARROWKEY
;
632 MonSelDestroy(IN OUT PMONITORSELWND infoPtr
)
634 /* Free all monitors */
635 MonSelSetMonitorsInfo(infoPtr
,
639 if (infoPtr
->hbrDisabled
!= NULL
)
641 DeleteObject(infoPtr
->hbrDisabled
);
642 infoPtr
->hbrDisabled
= NULL
;
645 if (infoPtr
->hbmDisabledPattern
!= NULL
)
647 DeleteObject(infoPtr
->hbmDisabledPattern
);
648 infoPtr
->hbmDisabledPattern
= NULL
;
653 MonSelSetExtendedStyle(IN OUT PMONITORSELWND infoPtr
,
654 IN DWORD dwExtendedStyle
)
656 if (infoPtr
->DraggingMonitor
>= 0)
659 if (dwExtendedStyle
!= infoPtr
->ControlExStyle
)
661 infoPtr
->ControlExStyle
= dwExtendedStyle
;
663 /* Repaint the control */
664 InvalidateRect(infoPtr
->hSelf
,
673 MonSelGetExtendedStyle(IN PMONITORSELWND infoPtr
)
675 return infoPtr
->ControlExStyle
;
679 MonSelGetMonitorFont(IN OUT PMONITORSELWND infoPtr
,
686 HFONT hPrevFont
, hFont
;
689 hFont
= infoPtr
->Monitors
[Index
].hFont
;
691 GetObject(infoPtr
->hFont
,
695 rcsize
.cx
= infoPtr
->Monitors
[Index
].rc
.right
- infoPtr
->Monitors
[Index
].rc
.left
-
696 (2 * infoPtr
->SelectionFrame
.cx
) - 2;
697 rcsize
.cy
= infoPtr
->Monitors
[Index
].rc
.bottom
- infoPtr
->Monitors
[Index
].rc
.top
-
698 (2 * infoPtr
->SelectionFrame
.cy
) - 2;
699 rcsize
.cy
= (rcsize
.cy
* 60) / 100;
701 //len = _tcslen(infoPtr->Monitors[Index].szCaption);
703 hPrevFont
= SelectObject(hDC
,
706 if (GetTextMetrics(hDC
,
709 lf
.lfWeight
= FW_SEMIBOLD
;
710 lf
.lfHeight
= -MulDiv(rcsize
.cy
- tm
.tmExternalLeading
,
715 hFont
= CreateFontIndirect(&lf
);
717 infoPtr
->Monitors
[Index
].hFont
= hFont
;
728 MonSelDrawDisabledRect(IN OUT PMONITORSELWND infoPtr
,
734 if (infoPtr
->hbrDisabled
== NULL
)
736 static const DWORD Pattern
[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
738 if (infoPtr
->hbmDisabledPattern
== NULL
)
740 infoPtr
->hbmDisabledPattern
= CreateBitmap(8,
747 if (infoPtr
->hbmDisabledPattern
!= NULL
)
748 infoPtr
->hbrDisabled
= CreatePatternBrush(infoPtr
->hbmDisabledPattern
);
751 if (infoPtr
->hbrDisabled
!= NULL
)
753 /* FIXME: Implement */
760 MonSelPaintMonitor(IN OUT PMONITORSELWND infoPtr
,
764 IN COLORREF crDefFontColor
,
767 HFONT hFont
, hPrevFont
;
770 if ((INT
)Index
== infoPtr
->SelectedMonitor
)
774 (HBRUSH
)(COLOR_HIGHLIGHT
+ 1));
776 if (infoPtr
->HasFocus
&& !(infoPtr
->UIState
& UISF_HIDEFOCUS
))
778 /* NOTE: We need to switch the text color to the default, because
779 DrawFocusRect draws a solid line if the text is white! */
781 crPrevText
= SetTextColor(hDC
,
793 -infoPtr
->SelectionFrame
.cx
,
794 -infoPtr
->SelectionFrame
.cy
);
808 hFont
= MonSelGetMonitorFont(infoPtr
,
813 hPrevFont
= SelectObject(hDC
,
817 infoPtr
->Monitors
[Index
].szCaption
,
820 DT_VCENTER
| DT_CENTER
| DT_NOPREFIX
| DT_SINGLELINE
);
827 if (infoPtr
->MonitorInfo
[Index
].Flags
& MSL_MIF_DISABLED
)
833 MonSelDrawDisabledRect(infoPtr
,
840 MonSelPaint(IN OUT PMONITORSELWND infoPtr
,
842 IN
const RECT
*prcUpdate
)
845 HBRUSH hbBk
, hbOldBk
;
852 bHideNumber
= (infoPtr
->ControlExStyle
& MSLM_EX_HIDENUMBERS
) ||
853 ((infoPtr
->MonitorsCount
== 1) && (infoPtr
->ControlExStyle
& MSLM_EX_HIDENUMBERONSINGLE
));
855 hbBk
= GetSysColorBrush(COLOR_BACKGROUND
);
856 hpFg
= CreatePen(PS_SOLID
,
858 GetSysColor(COLOR_HIGHLIGHTTEXT
));
860 hbOldBk
= SelectObject(hDC
,
862 hpOldFg
= SelectObject(hDC
,
864 iPrevBkMode
= SetBkMode(hDC
,
866 crPrevText
= SetTextColor(hDC
,
867 GetSysColor(COLOR_HIGHLIGHTTEXT
));
869 for (Index
= 0; Index
< infoPtr
->MonitorsCount
; Index
++)
871 if (infoPtr
->IsDraggingMonitor
&&
872 (DWORD
)infoPtr
->DraggingMonitor
== Index
)
877 MonSelRectToScreen(infoPtr
,
878 &infoPtr
->Monitors
[Index
].rc
,
881 if (IntersectRect(&rctmp
,
885 MonSelPaintMonitor(infoPtr
,
894 /* Paint the dragging monitor last */
895 if (infoPtr
->IsDraggingMonitor
&&
896 infoPtr
->DraggingMonitor
>= 0)
898 MonSelRectToScreen(infoPtr
,
899 &infoPtr
->rcDragging
,
902 if (IntersectRect(&rctmp
,
906 MonSelPaintMonitor(infoPtr
,
908 (DWORD
)infoPtr
->DraggingMonitor
,
928 MonSelContextMenu(IN OUT PMONITORSELWND infoPtr
,
932 MONSL_MONNMBUTTONCLICKED nm
;
935 if (!infoPtr
->HasFocus
)
936 SetFocus(infoPtr
->hSelf
);
941 Index
= MonSelHitTest(infoPtr
,
944 MonSelNotifyMonitor(infoPtr
,
947 (PMONSL_MONNMHDR
)&nm
);
949 /* Send a WM_CONTEXTMENU notification */
950 MapWindowPoints(infoPtr
->hSelf
,
955 SendMessage(infoPtr
->hSelf
,
957 (WPARAM
)infoPtr
->hSelf
,
963 MonSelApplyCursorClipping(IN PMONITORSELWND infoPtr
,
970 rc
.left
= rc
.top
= 0;
971 rc
.right
= infoPtr
->ClientSize
.cx
;
972 rc
.bottom
= infoPtr
->ClientSize
.cy
;
974 if (MapWindowPoints(infoPtr
->hSelf
,
989 MonSelMoveDragRect(IN OUT PMONITORSELWND infoPtr
,
992 RECT rcPrev
, rcUpdate
, *prc
;
996 if (infoPtr
->CanDisplay
)
998 hDC
= GetDC(infoPtr
->hSelf
);
1001 if (infoPtr
->ptDrag
.x
!= ppt
->x
||
1002 infoPtr
->ptDrag
.y
!= ppt
->y
)
1004 infoPtr
->ptDrag
= *ppt
;
1006 rcPrev
= infoPtr
->rcDragging
;
1008 /* Calculate updated dragging rectangle */
1009 prc
= &infoPtr
->Monitors
[infoPtr
->DraggingMonitor
].rc
;
1010 infoPtr
->rcDragging
.left
= ppt
->x
- infoPtr
->DraggingMargin
.cx
;
1011 infoPtr
->rcDragging
.top
= ppt
->y
- infoPtr
->DraggingMargin
.cy
;
1012 infoPtr
->rcDragging
.right
= infoPtr
->rcDragging
.left
+ (prc
->right
- prc
->left
);
1013 infoPtr
->rcDragging
.bottom
= infoPtr
->rcDragging
.top
+ (prc
->bottom
- prc
->top
);
1015 hRgnPrev
= CreateRectRgn(rcPrev
.left
,
1020 if (hRgnPrev
!= NULL
)
1023 infoPtr
->rcDragging
.left
- rcPrev
.left
,
1024 infoPtr
->rcDragging
.top
- rcPrev
.top
,
1029 !InvalidateRgn(infoPtr
->hSelf
,
1033 DeleteObject(hRgnPrev
);
1037 DeleteObject(hRgnPrev
);
1042 InvalidateRect(infoPtr
->hSelf
,
1045 InvalidateRect(infoPtr
->hSelf
,
1046 &infoPtr
->rcDragging
,
1051 ReleaseDC(infoPtr
->hSelf
,
1058 MonSelCancelDragging(IN OUT PMONITORSELWND infoPtr
)
1062 if (infoPtr
->DraggingMonitor
>= 0)
1064 MonSelMoveDragRect(infoPtr
,
1065 &infoPtr
->ptDragBegin
);
1067 Index
= (DWORD
)infoPtr
->DraggingMonitor
;
1068 infoPtr
->DraggingMonitor
= -1;
1070 if (infoPtr
->CanDisplay
)
1072 /* Repaint the area where the monitor was last dragged */
1073 MonSelRepaintMonitor(infoPtr
,
1076 infoPtr
->IsDraggingMonitor
= FALSE
;
1078 /* Repaint the area where the monitor is located */
1079 MonSelRepaintMonitor(infoPtr
,
1083 infoPtr
->IsDraggingMonitor
= FALSE
;
1087 MonSelApplyCursorClipping(infoPtr
,
1093 MonSelInitDragging(IN OUT PMONITORSELWND infoPtr
,
1099 MonSelCancelDragging(infoPtr
);
1100 infoPtr
->IsDraggingMonitor
= FALSE
;
1102 MonSelScreenToPt(infoPtr
,
1106 infoPtr
->ptDrag
= infoPtr
->ptDragBegin
= pt
;
1107 infoPtr
->DraggingMonitor
= (INT
)Index
;
1109 infoPtr
->DraggingMargin
.cx
= ppt
->x
- infoPtr
->Monitors
[Index
].rc
.left
;
1110 infoPtr
->DraggingMargin
.cy
= ppt
->y
- infoPtr
->Monitors
[Index
].rc
.top
;
1111 infoPtr
->rcDragging
= infoPtr
->Monitors
[Index
].rc
;
1113 MonSelApplyCursorClipping(infoPtr
,
1118 MonSelDrag(IN OUT PMONITORSELWND infoPtr
,
1125 if (infoPtr
->DraggingMonitor
>= 0)
1127 MonSelScreenToPt(infoPtr
,
1131 if (!infoPtr
->IsDraggingMonitor
)
1133 szDrag
.cx
= GetSystemMetrics(SM_CXDRAG
);
1134 szDrag
.cy
= GetSystemMetrics(SM_CYDRAG
);
1136 rcDrag
.left
= infoPtr
->Monitors
[infoPtr
->DraggingMonitor
].rc
.left
+ infoPtr
->DraggingMargin
.cx
- (szDrag
.cx
/ 2);
1137 rcDrag
.top
= infoPtr
->Monitors
[infoPtr
->DraggingMonitor
].rc
.top
+ infoPtr
->DraggingMargin
.cy
- (szDrag
.cy
/ 2);
1138 rcDrag
.right
= rcDrag
.left
+ szDrag
.cx
;
1139 rcDrag
.bottom
= rcDrag
.top
+ szDrag
.cy
;
1141 if (!PtInRect(&rcDrag
,
1144 /* The user started moving around the mouse: Begin dragging */
1145 infoPtr
->IsDraggingMonitor
= TRUE
;
1146 MonSelMoveDragRect(infoPtr
,
1152 MonSelMoveDragRect(infoPtr
,
1158 static LRESULT CALLBACK
1159 MonitorSelWndProc(IN HWND hwnd
,
1164 PMONITORSELWND infoPtr
;
1167 infoPtr
= (PMONITORSELWND
)GetWindowLongPtrW(hwnd
,
1170 if (infoPtr
== NULL
&& uMsg
!= WM_CREATE
)
1172 goto HandleDefaultMessage
;
1178 case WM_PRINTCLIENT
:
1185 if (!GetUpdateRect(hwnd
,
1195 hDC
= BeginPaint(hwnd
,
1203 if (infoPtr
->CanDisplay
)
1205 MonSelPaint(infoPtr
,
1222 if (!(wParam
& MK_LBUTTON
))
1224 MonSelCancelDragging(infoPtr
);
1228 if (infoPtr
->LeftBtnDown
)
1230 pt
.x
= (LONG
)LOWORD(lParam
);
1231 pt
.y
= (LONG
)HIWORD(lParam
);
1240 case WM_RBUTTONDOWN
:
1242 if (!(infoPtr
->ControlExStyle
& MSLM_EX_SELECTONRIGHTCLICK
))
1248 case WM_LBUTTONDBLCLK
:
1249 case WM_LBUTTONDOWN
:
1254 if (!infoPtr
->HasFocus
)
1255 SetFocus(infoPtr
->hSelf
);
1257 pt
.x
= (LONG
)LOWORD(lParam
);
1258 pt
.y
= (LONG
)HIWORD(lParam
);
1260 Index
= MonSelHitTest(infoPtr
,
1262 if (Index
>= 0 || (infoPtr
->ControlExStyle
& MSLM_EX_ALLOWSELECTNONE
))
1264 MonSelSetCurSelMonitor(infoPtr
,
1269 if (Index
>= 0 && (uMsg
== WM_LBUTTONDOWN
|| uMsg
== WM_LBUTTONDBLCLK
))
1271 infoPtr
->LeftBtnDown
= TRUE
;
1272 MonSelInitDragging(infoPtr
,
1280 case WM_MBUTTONDOWN
:
1282 if (!infoPtr
->HasFocus
)
1289 MonSelContextMenu(infoPtr
,
1290 (SHORT
)LOWORD(lParam
),
1291 (SHORT
)HIWORD(lParam
));
1297 MonSelCancelDragging(infoPtr
);
1298 infoPtr
->LeftBtnDown
= FALSE
;
1306 virtKey
= (lParam
!= 0 ? (INT
)((LPMSG
)lParam
)->wParam
: 0);
1311 /* Change the UI status */
1312 SendMessage(GetAncestor(hwnd
,
1315 MAKEWPARAM(UIS_INITIALIZE
,
1322 Ret
|= DLGC_WANTARROWS
;
1324 if (infoPtr
->ControlExStyle
& MSLM_EX_SELECTBYNUMKEY
)
1325 Ret
|= DLGC_WANTCHARS
;
1331 infoPtr
->HasFocus
= TRUE
;
1332 MonSelRepaintSelected(infoPtr
);
1338 infoPtr
->HasFocus
= FALSE
;
1339 MonSelCancelDragging(infoPtr
);
1340 MonSelRepaintSelected(infoPtr
);
1344 case WM_UPDATEUISTATE
:
1348 Ret
= DefWindowProcW(hwnd
,
1353 OldUIState
= infoPtr
->UIState
;
1354 switch (LOWORD(wParam
))
1357 infoPtr
->UIState
|= HIWORD(wParam
);
1361 infoPtr
->UIState
&= ~HIWORD(wParam
);
1365 if (infoPtr
->UIState
!= OldUIState
)
1366 MonSelRepaintSelected(infoPtr
);
1372 Ret
= (LRESULT
)MonSelChangeFont(infoPtr
,
1374 (BOOL
)LOWORD(lParam
));
1380 infoPtr
->ClientSize
.cx
= LOWORD(lParam
);
1381 infoPtr
->ClientSize
.cy
= HIWORD(lParam
);
1383 /* Don't let MonSelUpdateMonitorsInfo repaint the control
1384 because this won't work properly in case the control
1386 MonSelUpdateMonitorsInfo(infoPtr
,
1388 InvalidateRect(infoPtr
->hSelf
,
1396 Ret
= (LRESULT
)infoPtr
->hFont
;
1402 infoPtr
->Enabled
= ((BOOL
)wParam
!= FALSE
);
1403 MonSelRepaint(infoPtr
);
1407 case WM_STYLECHANGED
:
1409 if (wParam
== GWL_STYLE
)
1411 unsigned int OldEnabled
= infoPtr
->Enabled
;
1412 infoPtr
->Enabled
= !(((LPSTYLESTRUCT
)lParam
)->styleNew
& WS_DISABLED
);
1414 if (OldEnabled
!= infoPtr
->Enabled
)
1415 MonSelRepaint(infoPtr
);
1424 if (infoPtr
->ControlExStyle
& MSLM_EX_SELECTBYARROWKEY
)
1431 Index
= infoPtr
->SelectedMonitor
;
1433 if (infoPtr
->MonitorsCount
!= 0)
1443 MonSelSetCurSelMonitor(infoPtr
,
1453 Index
= infoPtr
->SelectedMonitor
;
1455 if (infoPtr
->MonitorsCount
!= 0)
1458 Index
= (INT
)infoPtr
->MonitorsCount
- 1;
1459 else if (Index
< (INT
)infoPtr
->MonitorsCount
- 1)
1463 if (infoPtr
->SelectedMonitor
< infoPtr
->MonitorsCount
)
1465 MonSelSetCurSelMonitor(infoPtr
,
1478 if ((infoPtr
->ControlExStyle
& MSLM_EX_SELECTBYNUMKEY
) &&
1479 wParam
>= '1' && wParam
<= '9')
1481 INT Index
= (INT
)(wParam
- '1');
1482 if (Index
< (INT
)infoPtr
->MonitorsCount
)
1484 MonSelSetCurSelMonitor(infoPtr
,
1492 case MSLM_SETMONITORSINFO
:
1494 Ret
= MonSelSetMonitorsInfo(infoPtr
,
1496 (const MONSL_MONINFO
*)lParam
);
1500 case MSLM_GETMONITORSINFO
:
1502 Ret
= MonSelGetMonitorsInfo(infoPtr
,
1504 (PMONSL_MONINFO
)lParam
);
1508 case MSLM_GETMONITORINFOCOUNT
:
1510 Ret
= infoPtr
->MonitorsCount
;
1516 Ret
= MonSelHitTest(infoPtr
,
1517 (const POINT
*)wParam
);
1521 case MSLM_SETCURSEL
:
1523 Ret
= MonSelSetCurSelMonitor(infoPtr
,
1529 case MSLM_GETCURSEL
:
1531 Ret
= infoPtr
->SelectedMonitor
;
1535 case MSLM_SETMONITORINFO
:
1537 Ret
= MonSelSetMonitorInfo(infoPtr
,
1539 (const MONSL_MONINFO
*)lParam
);
1543 case MSLM_GETMONITORINFO
:
1545 Ret
= MonSelGetMonitorInfo(infoPtr
,
1547 (PMONSL_MONINFO
)lParam
);
1551 case MSLM_SETEXSTYLE
:
1553 Ret
= MonSelSetExtendedStyle(infoPtr
,
1558 case MSLM_GETEXSTYLE
:
1560 Ret
= MonSelGetExtendedStyle(infoPtr
);
1564 case MSLM_GETMONITORRECT
:
1566 Ret
= (LRESULT
)MonSelGetMonitorRect(infoPtr
,
1574 infoPtr
= (PMONITORSELWND
) HeapAlloc(GetProcessHeap(),
1576 sizeof(MONITORSELWND
));
1577 if (infoPtr
== NULL
)
1584 sizeof(MONITORSELWND
));
1585 infoPtr
->hSelf
= hwnd
;
1586 infoPtr
->hNotify
= ((LPCREATESTRUCTW
)lParam
)->hwndParent
;
1587 infoPtr
->Enabled
= !(((LPCREATESTRUCTW
)lParam
)->style
& WS_DISABLED
);
1588 infoPtr
->UIState
= SendMessage(hwnd
,
1593 SetWindowLongPtrW(hwnd
,
1597 MonSelCreate(infoPtr
);
1603 MonSelDestroy(infoPtr
);
1605 HeapFree(GetProcessHeap(),
1608 SetWindowLongPtrW(hwnd
,
1616 HandleDefaultMessage
:
1617 Ret
= DefWindowProcW(hwnd
,
1629 RegisterMonitorSelectionControl(IN HINSTANCE hInstance
)
1633 wc
.style
= CS_DBLCLKS
;
1634 wc
.lpfnWndProc
= MonitorSelWndProc
;
1635 wc
.cbWndExtra
= sizeof(PMONITORSELWND
);
1636 wc
.hInstance
= hInstance
;
1637 wc
.hCursor
= LoadCursorW(NULL
,
1639 wc
.hbrBackground
= (HBRUSH
)(COLOR_APPWORKSPACE
+ 1);
1640 wc
.lpszClassName
= szMonitorSelWndClass
;
1642 return RegisterClass(&wc
) != 0;
1646 UnregisterMonitorSelectionControl(IN HINSTANCE hInstance
)
1648 UnregisterClassW(szMonitorSelWndClass
,