6 static const TCHAR szMonitorSelWndClass
[] = TEXT("MONITORSELWNDCLASS");
8 typedef struct _MONSL_MON
13 } MONSL_MON
, *PMONSL_MON
;
15 typedef struct _MONITORSELWND
24 DWORD dwInternalFlags
;
31 UINT IsDraggingMonitor
: 1;
39 POINT ptDrag
, ptDragBegin
;
41 PMONSL_MONINFO MonitorInfo
;
48 HBITMAP hbmDisabledPattern
;
50 } MONITORSELWND
, *PMONITORSELWND
;
53 MonSelNotify(IN PMONITORSELWND infoPtr
,
59 if (infoPtr
->hNotify
!= NULL
)
61 LPNMHDR pnmh
= (LPNMHDR
)data
;
63 pnmh
->hwndFrom
= infoPtr
->hSelf
;
64 pnmh
->idFrom
= GetWindowLongPtr(infoPtr
->hSelf
,
68 Ret
= SendMessage(infoPtr
->hNotify
,
78 MonSelNotifyMonitor(IN PMONITORSELWND infoPtr
,
81 IN OUT PMONSL_MONNMHDR pmonnmh
)
83 pmonnmh
->Index
= Index
;
87 pmonnmh
->MonitorInfo
= infoPtr
->MonitorInfo
[Index
];
91 ZeroMemory(&pmonnmh
->MonitorInfo
,
92 sizeof(pmonnmh
->MonitorInfo
));
95 return MonSelNotify(infoPtr
,
101 MonSelChangeFont(IN OUT PMONITORSELWND infoPtr
,
105 HFONT hOldFont
= infoPtr
->hFont
;
106 infoPtr
->hFont
= hFont
;
110 InvalidateRect(infoPtr
->hSelf
,
119 MonSelRectToScreen(IN PMONITORSELWND infoPtr
,
121 OUT PRECT prcOnScreen
)
124 OffsetRect(prcOnScreen
,
125 -infoPtr
->ScrollPos
.x
,
126 -infoPtr
->ScrollPos
.y
);
130 MonSelScreenToPt(IN PMONITORSELWND infoPtr
,
131 IN
const POINT
*pptOnScreen
,
134 ppt
->x
= pptOnScreen
->x
+ infoPtr
->ScrollPos
.x
;
135 ppt
->y
= pptOnScreen
->y
+ infoPtr
->ScrollPos
.y
;
139 MonSelMonInfoToRect(IN
const MONSL_MONINFO
*pMonInfo
,
142 prc
->left
= pMonInfo
->Position
.x
;
143 prc
->top
= pMonInfo
->Position
.y
;
144 prc
->right
= pMonInfo
->Position
.x
+ pMonInfo
->Size
.cx
;
145 prc
->bottom
= pMonInfo
->Position
.y
+ pMonInfo
->Size
.cy
;
149 MonSelHitTest(IN PMONITORSELWND infoPtr
,
155 if (infoPtr
->CanDisplay
)
157 MonSelScreenToPt(infoPtr
,
161 for (Index
= 0; Index
< (INT
)infoPtr
->MonitorsCount
; Index
++)
163 if (PtInRect(&infoPtr
->Monitors
[Index
].rc
,
176 MonSelUpdateExtent(IN OUT PMONITORSELWND infoPtr
)
181 /* NOTE: This routine calculates the extent of all monitor coordinates.
182 These are not control coordinates! */
183 if (infoPtr
->MonitorsCount
> 0)
185 MonSelMonInfoToRect(&infoPtr
->MonitorInfo
[0],
188 for (Index
= 1; Index
< infoPtr
->MonitorsCount
; Index
++)
190 MonSelMonInfoToRect(&infoPtr
->MonitorInfo
[Index
],
193 UnionRect(&infoPtr
->rcExtent
,
200 ZeroMemory(&infoPtr
->rcExtent
,
201 sizeof(infoPtr
->rcExtent
));
206 MonSelScaleRectRelative(IN
const RECT
*prcBaseFrom
,
207 IN
const RECT
*prcFrom
,
208 IN
const RECT
*prcBaseTo
,
211 SIZE BaseFrom
, BaseTo
, From
;
213 BaseFrom
.cx
= prcBaseFrom
->right
- prcBaseFrom
->left
;
214 BaseFrom
.cy
= prcBaseFrom
->bottom
- prcBaseFrom
->top
;
215 BaseTo
.cx
= prcBaseTo
->right
- prcBaseTo
->left
;
216 BaseTo
.cy
= prcBaseTo
->bottom
- prcBaseTo
->top
;
217 From
.cx
= prcFrom
->right
- prcFrom
->left
;
218 From
.cy
= prcFrom
->bottom
- prcFrom
->top
;
220 prcTo
->left
= prcBaseTo
->left
+ (((prcFrom
->left
- prcBaseFrom
->left
) * BaseTo
.cx
) / BaseFrom
.cx
);
221 prcTo
->top
= prcBaseTo
->top
+ (((prcFrom
->top
- prcBaseFrom
->top
) * BaseTo
.cy
) / BaseFrom
.cy
);
222 prcTo
->right
= prcTo
->left
+ ((From
.cx
* BaseTo
.cx
) / BaseFrom
.cx
);
223 prcTo
->bottom
= prcTo
->top
+ ((From
.cy
* BaseTo
.cy
) / BaseFrom
.cy
);
227 ScaleRectSizeFit(IN
const RECT
*prcContainerRect
,
228 IN OUT PRECT prcRectToScale
)
230 SIZE ContainerSize
, RectSize
;
232 ContainerSize
.cx
= prcContainerRect
->right
- prcContainerRect
->left
;
233 ContainerSize
.cy
= prcContainerRect
->bottom
- prcContainerRect
->top
;
234 RectSize
.cx
= prcRectToScale
->right
- prcRectToScale
->left
;
235 RectSize
.cy
= prcRectToScale
->bottom
- prcRectToScale
->top
;
237 if (((RectSize
.cx
* 0xFFF) / RectSize
.cy
) < ((ContainerSize
.cx
* 0xFFF) / ContainerSize
.cy
))
239 RectSize
.cx
= (RectSize
.cx
* ((ContainerSize
.cy
* 0xFFF) / RectSize
.cy
)) / 0xFFF;
240 RectSize
.cy
= ContainerSize
.cy
;
244 RectSize
.cy
= (RectSize
.cy
* ((ContainerSize
.cx
* 0xFFF) / RectSize
.cx
)) / 0xFFF;
245 RectSize
.cx
= ContainerSize
.cx
;
248 prcRectToScale
->right
= prcRectToScale
->left
+ RectSize
.cx
;
249 prcRectToScale
->bottom
= prcRectToScale
->top
+ RectSize
.cy
;
251 OffsetRect(prcRectToScale
,
252 prcContainerRect
->left
+ ((ContainerSize
.cx
- RectSize
.cx
) / 2),
253 prcContainerRect
->top
+ ((ContainerSize
.cy
- RectSize
.cy
) / 2));
257 MonSelRepaint(IN PMONITORSELWND infoPtr
)
261 MonSelRectToScreen(infoPtr
,
262 &infoPtr
->rcMonitors
,
264 InvalidateRect(infoPtr
->hSelf
,
270 MonSelRepaintMonitor(IN PMONITORSELWND infoPtr
,
274 BOOL NoRepaint
= FALSE
;
276 if (Index
< infoPtr
->MonitorsCount
)
278 if (Index
== (DWORD
)infoPtr
->DraggingMonitor
)
280 if (infoPtr
->IsDraggingMonitor
)
282 MonSelRectToScreen(infoPtr
,
283 &infoPtr
->rcDragging
,
291 MonSelRectToScreen(infoPtr
,
292 &infoPtr
->Monitors
[Index
].rc
,
298 InvalidateRect(infoPtr
->hSelf
,
306 MonSelRepaintSelected(IN PMONITORSELWND infoPtr
)
308 if (infoPtr
->SelectedMonitor
>= 0)
310 MonSelRepaintMonitor(infoPtr
,
311 (DWORD
)infoPtr
->SelectedMonitor
);
316 MonSelResetMonitors(IN OUT PMONITORSELWND infoPtr
)
320 for (Index
= 0; Index
< infoPtr
->MonitorsCount
; Index
++)
322 if (infoPtr
->Monitors
[Index
].hFont
!= NULL
)
324 DeleteObject(infoPtr
->Monitors
[Index
].hFont
);
325 infoPtr
->Monitors
[Index
].hFont
= NULL
;
332 MonSelUpdateMonitorsInfo(IN OUT PMONITORSELWND infoPtr
,
335 RECT rcExtSurface
, rcExtDisplay
;
338 /* Recalculate rcExtent */
339 MonSelUpdateExtent(infoPtr
);
341 infoPtr
-> CanDisplay
= infoPtr
->MonitorsCount
!= 0 &&
342 (infoPtr
->ClientSize
.cx
> (2 * (infoPtr
->Margin
.cx
+ infoPtr
->SelectionFrame
.cx
))) &&
343 (infoPtr
->ClientSize
.cy
> (2 * (infoPtr
->Margin
.cy
+ infoPtr
->SelectionFrame
.cy
)));
345 if (infoPtr
->CanDisplay
)
347 /* Calculate the rectangle on the control in which may be painted */
348 rcExtSurface
.left
= infoPtr
->Margin
.cx
;
349 rcExtSurface
.top
= infoPtr
->Margin
.cy
;
350 rcExtSurface
.right
= rcExtSurface
.left
+ infoPtr
->ClientSize
.cx
- (2 * infoPtr
->Margin
.cx
);
351 rcExtSurface
.bottom
= rcExtSurface
.top
+ infoPtr
->ClientSize
.cy
- (2 * infoPtr
->Margin
.cy
);
353 /* Calculate the rectangle on the control that is actually painted on */
354 rcExtDisplay
.left
= rcExtDisplay
.top
= 0;
355 rcExtDisplay
.right
= infoPtr
->rcExtent
.right
- infoPtr
->rcExtent
.left
;
356 rcExtDisplay
.bottom
= infoPtr
->rcExtent
.bottom
- infoPtr
->rcExtent
.top
;
358 ScaleRectSizeFit(&rcExtSurface
,
361 infoPtr
->rcMonitors
= rcExtDisplay
;
363 /* Now that we know in which area all monitors are located,
364 calculate the monitors selection rectangles on the screen */
366 for (Index
= 0; Index
< infoPtr
->MonitorsCount
; Index
++)
368 MonSelMonInfoToRect(&infoPtr
->MonitorInfo
[Index
],
371 MonSelScaleRectRelative(&infoPtr
->rcExtent
,
373 &infoPtr
->rcMonitors
,
374 &infoPtr
->Monitors
[Index
].rc
);
377 MonSelResetMonitors(infoPtr
);
380 MonSelRepaint(infoPtr
);
384 InvalidateRect(infoPtr
->hSelf
,
391 MonSelSetMonitorsInfo(IN OUT PMONITORSELWND infoPtr
,
393 IN
const MONSL_MONINFO
*MonitorsInfo
)
398 if (infoPtr
->DraggingMonitor
>= 0)
401 if (infoPtr
->MonitorInfo
!= NULL
)
403 LocalFree((HLOCAL
)infoPtr
->MonitorInfo
);
404 infoPtr
->MonitorInfo
= NULL
;
406 MonSelResetMonitors(infoPtr
);
408 LocalFree((HLOCAL
)infoPtr
->Monitors
);
409 infoPtr
->Monitors
= NULL
;
411 infoPtr
->MonitorsCount
= 0;
416 infoPtr
->MonitorInfo
= (PMONSL_MONINFO
)LocalAlloc(LMEM_FIXED
,
417 dwMonitors
* sizeof(MONSL_MONINFO
));
418 if (infoPtr
->MonitorInfo
!= NULL
)
420 infoPtr
->Monitors
= (PMONSL_MON
)LocalAlloc(LMEM_FIXED
,
421 dwMonitors
* sizeof(MONSL_MON
));
422 if (infoPtr
->Monitors
!= NULL
)
424 CopyMemory(infoPtr
->MonitorInfo
,
426 dwMonitors
* sizeof(MONSL_MONINFO
));
427 ZeroMemory(infoPtr
->Monitors
,
428 dwMonitors
* sizeof(MONSL_MON
));
430 for (Index
= 0; Index
< dwMonitors
; Index
++)
432 _stprintf(infoPtr
->Monitors
[Index
].szCaption
,
437 infoPtr
->MonitorsCount
= dwMonitors
;
439 if (infoPtr
->SelectedMonitor
>= (INT
)infoPtr
->MonitorsCount
)
440 infoPtr
->SelectedMonitor
= -1;
442 if (!(infoPtr
->ControlExStyle
& MSLM_EX_ALLOWSELECTNONE
) && infoPtr
->SelectedMonitor
< 0)
443 infoPtr
->SelectedMonitor
= 0;
445 MonSelUpdateMonitorsInfo(infoPtr
,
450 LocalFree((HLOCAL
)infoPtr
->MonitorInfo
);
451 infoPtr
->MonitorInfo
= NULL
;
461 infoPtr
->SelectedMonitor
= -1;
463 if (!Ret
|| dwMonitors
== 0)
465 InvalidateRect(infoPtr
->hSelf
,
474 MonSelGetMonitorsInfo(IN PMONITORSELWND infoPtr
,
476 IN OUT PMONSL_MONINFO MonitorsInfo
)
480 if (dwMonitors
> infoPtr
->MonitorsCount
)
481 dwMonitors
= infoPtr
->MonitorsCount
;
483 CopyMemory(MonitorsInfo
,
484 infoPtr
->MonitorInfo
,
485 dwMonitors
* sizeof(MONSL_MONINFO
));
489 return infoPtr
->MonitorsCount
;
493 MonSelSetMonitorInfo(IN OUT PMONITORSELWND infoPtr
,
495 IN
const MONSL_MONINFO
*MonitorsInfo
)
497 if (infoPtr
->DraggingMonitor
< 0 &&
498 Index
>= 0 && Index
< (INT
)infoPtr
->MonitorsCount
)
500 CopyMemory(&infoPtr
->MonitorInfo
[Index
],
502 sizeof(MONSL_MONINFO
));
504 MonSelUpdateMonitorsInfo(infoPtr
,
513 MonSelGetMonitorInfo(IN PMONITORSELWND infoPtr
,
515 IN OUT PMONSL_MONINFO MonitorsInfo
)
517 if (Index
>= 0 && Index
< (INT
)infoPtr
->MonitorsCount
)
519 CopyMemory(MonitorsInfo
,
520 &infoPtr
->MonitorInfo
[Index
],
521 sizeof(MONSL_MONINFO
));
529 MonSelGetMonitorRect(IN OUT PMONITORSELWND infoPtr
,
535 if (Index
< 0 || Index
>= infoPtr
->MonitorsCount
)
538 if (!infoPtr
->CanDisplay
)
541 MonSelRectToScreen(infoPtr
,
542 &infoPtr
->Monitors
[Index
].rc
,
545 rcClient
.left
= rcClient
.top
= 0;
546 rcClient
.right
= infoPtr
->ClientSize
.cx
;
547 rcClient
.bottom
= infoPtr
->ClientSize
.cy
;
549 return IntersectRect(&rc
,
555 MonSelSetCurSelMonitor(IN OUT PMONITORSELWND infoPtr
,
560 BOOL PreventSelect
= FALSE
;
563 if (infoPtr
->DraggingMonitor
< 0 &&
564 (Index
== -1 || Index
< (INT
)infoPtr
->MonitorsCount
))
566 if (Index
!= infoPtr
->SelectedMonitor
)
568 if ((infoPtr
->MonitorInfo
[Index
].Flags
& MSL_MIF_DISABLED
) &&
569 !(infoPtr
->ControlExStyle
& MSLM_EX_ALLOWSELECTDISABLED
))
571 PreventSelect
= TRUE
;
574 if (!PreventSelect
&& bNotify
)
576 MONSL_MONNMMONITORCHANGING nmi
;
578 nmi
.PreviousSelected
= infoPtr
->SelectedMonitor
;
579 nmi
.AllowChanging
= TRUE
;
581 MonSelNotifyMonitor(infoPtr
,
582 MSLN_MONITORCHANGING
,
586 PreventSelect
= (nmi
.AllowChanging
== FALSE
);
591 PrevSel
= infoPtr
->SelectedMonitor
;
592 infoPtr
->SelectedMonitor
= Index
;
596 MonSelRepaintMonitor(infoPtr
,
600 if (infoPtr
->SelectedMonitor
>= 0)
601 MonSelRepaintSelected(infoPtr
);
607 MonSelNotifyMonitor(infoPtr
,
622 MonSelCreate(IN OUT PMONITORSELWND infoPtr
)
624 infoPtr
->SelectionFrame
.cx
= infoPtr
->SelectionFrame
.cy
= 4;
625 infoPtr
->Margin
.cx
= infoPtr
->Margin
.cy
= 20;
626 infoPtr
->SelectedMonitor
= -1;
627 infoPtr
->DraggingMonitor
= -1;
628 infoPtr
->ControlExStyle
= MSLM_EX_ALLOWSELECTDISABLED
| MSLM_EX_HIDENUMBERONSINGLE
|
629 MSLM_EX_SELECTONRIGHTCLICK
| MSLM_EX_SELECTBYARROWKEY
;
634 MonSelDestroy(IN OUT PMONITORSELWND infoPtr
)
636 /* Free all monitors */
637 MonSelSetMonitorsInfo(infoPtr
,
641 if (infoPtr
->hbrDisabled
!= NULL
)
643 DeleteObject(infoPtr
->hbrDisabled
);
644 infoPtr
->hbrDisabled
= NULL
;
647 if (infoPtr
->hbmDisabledPattern
!= NULL
)
649 DeleteObject(infoPtr
->hbmDisabledPattern
);
650 infoPtr
->hbmDisabledPattern
= NULL
;
655 MonSelSetExtendedStyle(IN OUT PMONITORSELWND infoPtr
,
656 IN DWORD dwExtendedStyle
)
658 if (infoPtr
->DraggingMonitor
>= 0)
661 if (dwExtendedStyle
!= infoPtr
->ControlExStyle
)
663 infoPtr
->ControlExStyle
= dwExtendedStyle
;
665 /* Repaint the control */
666 InvalidateRect(infoPtr
->hSelf
,
675 MonSelGetExtendedStyle(IN PMONITORSELWND infoPtr
)
677 return infoPtr
->ControlExStyle
;
681 MonSelGetMonitorFont(IN OUT PMONITORSELWND infoPtr
,
688 HFONT hPrevFont
, hFont
;
691 hFont
= infoPtr
->Monitors
[Index
].hFont
;
693 GetObject(infoPtr
->hFont
,
697 rcsize
.cx
= infoPtr
->Monitors
[Index
].rc
.right
- infoPtr
->Monitors
[Index
].rc
.left
-
698 (2 * infoPtr
->SelectionFrame
.cx
) - 2;
699 rcsize
.cy
= infoPtr
->Monitors
[Index
].rc
.bottom
- infoPtr
->Monitors
[Index
].rc
.top
-
700 (2 * infoPtr
->SelectionFrame
.cy
) - 2;
701 rcsize
.cy
= (rcsize
.cy
* 60) / 100;
703 len
= _tcslen(infoPtr
->Monitors
[Index
].szCaption
);
705 hPrevFont
= SelectObject(hDC
,
708 if (GetTextMetrics(hDC
,
711 lf
.lfWeight
= FW_SEMIBOLD
;
712 lf
.lfHeight
= -MulDiv(rcsize
.cy
- tm
.tmExternalLeading
,
717 hFont
= CreateFontIndirect(&lf
);
719 infoPtr
->Monitors
[Index
].hFont
= hFont
;
730 MonSelDrawDisabledRect(IN OUT PMONITORSELWND infoPtr
,
736 if (infoPtr
->hbrDisabled
== NULL
)
738 static const DWORD Pattern
[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
740 if (infoPtr
->hbmDisabledPattern
== NULL
)
742 infoPtr
->hbmDisabledPattern
= CreateBitmap(8,
749 if (infoPtr
->hbmDisabledPattern
!= NULL
)
750 infoPtr
->hbrDisabled
= CreatePatternBrush(infoPtr
->hbmDisabledPattern
);
753 if (infoPtr
->hbrDisabled
!= NULL
)
755 /* FIXME - implement */
762 MonSelPaintMonitor(IN OUT PMONITORSELWND infoPtr
,
766 IN COLORREF crDefFontColor
,
769 HFONT hFont
, hPrevFont
;
772 if ((INT
)Index
== infoPtr
->SelectedMonitor
)
776 (HBRUSH
)(COLOR_HIGHLIGHT
+ 1));
778 if (infoPtr
->HasFocus
&& !(infoPtr
->UIState
& UISF_HIDEFOCUS
))
780 /* NOTE: We need to switch the text color to the default, because
781 DrawFocusRect draws a solid line if the text is white! */
783 crPrevText
= SetTextColor(hDC
,
795 -infoPtr
->SelectionFrame
.cx
,
796 -infoPtr
->SelectionFrame
.cy
);
810 hFont
= MonSelGetMonitorFont(infoPtr
,
815 hPrevFont
= SelectObject(hDC
,
819 infoPtr
->Monitors
[Index
].szCaption
,
822 DT_VCENTER
| DT_CENTER
| DT_NOPREFIX
| DT_SINGLELINE
);
829 if (infoPtr
->MonitorInfo
[Index
].Flags
& MSL_MIF_DISABLED
)
835 MonSelDrawDisabledRect(infoPtr
,
842 MonSelPaint(IN OUT PMONITORSELWND infoPtr
,
844 IN
const RECT
*prcUpdate
)
847 HBRUSH hbBk
, hbOldBk
;
854 bHideNumber
= (infoPtr
->ControlExStyle
& MSLM_EX_HIDENUMBERS
) ||
855 ((infoPtr
->MonitorsCount
== 1) && (infoPtr
->ControlExStyle
& MSLM_EX_HIDENUMBERONSINGLE
));
857 hbBk
= GetSysColorBrush(COLOR_BACKGROUND
);
858 hpFg
= CreatePen(PS_SOLID
,
860 GetSysColor(COLOR_HIGHLIGHTTEXT
));
862 hbOldBk
= SelectObject(hDC
,
864 hpOldFg
= SelectObject(hDC
,
866 iPrevBkMode
= SetBkMode(hDC
,
868 crPrevText
= SetTextColor(hDC
,
869 GetSysColor(COLOR_HIGHLIGHTTEXT
));
871 for (Index
= 0; Index
< infoPtr
->MonitorsCount
; Index
++)
873 if (infoPtr
->IsDraggingMonitor
&&
874 (DWORD
)infoPtr
->DraggingMonitor
== Index
)
879 MonSelRectToScreen(infoPtr
,
880 &infoPtr
->Monitors
[Index
].rc
,
883 if (IntersectRect(&rctmp
,
887 MonSelPaintMonitor(infoPtr
,
896 /* Paint the dragging monitor last */
897 if (infoPtr
->IsDraggingMonitor
&&
898 infoPtr
->DraggingMonitor
>= 0)
900 MonSelRectToScreen(infoPtr
,
901 &infoPtr
->rcDragging
,
904 if (IntersectRect(&rctmp
,
908 MonSelPaintMonitor(infoPtr
,
910 (DWORD
)infoPtr
->DraggingMonitor
,
930 MonSelContextMenu(IN OUT PMONITORSELWND infoPtr
,
934 MONSL_MONNMBUTTONCLICKED nm
;
937 if (!infoPtr
->HasFocus
)
938 SetFocus(infoPtr
->hSelf
);
943 Index
= MonSelHitTest(infoPtr
,
946 MonSelNotifyMonitor(infoPtr
,
949 (PMONSL_MONNMHDR
)&nm
);
951 /* Send a WM_CONTEXTMENU notification */
952 MapWindowPoints(infoPtr
->hSelf
,
957 SendMessage(infoPtr
->hSelf
,
959 (WPARAM
)infoPtr
->hSelf
,
965 MonSelApplyCursorClipping(IN PMONITORSELWND infoPtr
,
972 rc
.left
= rc
.top
= 0;
973 rc
.right
= infoPtr
->ClientSize
.cx
;
974 rc
.bottom
= infoPtr
->ClientSize
.cy
;
976 if (MapWindowPoints(infoPtr
->hSelf
,
991 MonSelMoveDragRect(IN OUT PMONITORSELWND infoPtr
,
994 RECT rcPrev
, rcUpdate
, *prc
;
998 if (infoPtr
->CanDisplay
)
1000 hDC
= GetDC(infoPtr
->hSelf
);
1003 if (infoPtr
->ptDrag
.x
!= ppt
->x
||
1004 infoPtr
->ptDrag
.y
!= ppt
->y
)
1006 infoPtr
->ptDrag
= *ppt
;
1008 rcPrev
= infoPtr
->rcDragging
;
1010 /* Calculate updated dragging rectangle */
1011 prc
= &infoPtr
->Monitors
[infoPtr
->DraggingMonitor
].rc
;
1012 infoPtr
->rcDragging
.left
= ppt
->x
- infoPtr
->DraggingMargin
.cx
;
1013 infoPtr
->rcDragging
.top
= ppt
->y
- infoPtr
->DraggingMargin
.cy
;
1014 infoPtr
->rcDragging
.right
= infoPtr
->rcDragging
.left
+ (prc
->right
- prc
->left
);
1015 infoPtr
->rcDragging
.bottom
= infoPtr
->rcDragging
.top
+ (prc
->bottom
- prc
->top
);
1017 hRgnPrev
= CreateRectRgn(rcPrev
.left
,
1022 if (hRgnPrev
!= NULL
)
1025 infoPtr
->rcDragging
.left
- rcPrev
.left
,
1026 infoPtr
->rcDragging
.top
- rcPrev
.top
,
1031 !InvalidateRgn(infoPtr
->hSelf
,
1035 DeleteObject(hRgnPrev
);
1039 DeleteObject(hRgnPrev
);
1044 InvalidateRect(infoPtr
->hSelf
,
1047 InvalidateRect(infoPtr
->hSelf
,
1048 &infoPtr
->rcDragging
,
1053 ReleaseDC(infoPtr
->hSelf
,
1060 MonSelCancelDragging(IN OUT PMONITORSELWND infoPtr
)
1064 if (infoPtr
->DraggingMonitor
>= 0)
1066 MonSelMoveDragRect(infoPtr
,
1067 &infoPtr
->ptDragBegin
);
1069 Index
= (DWORD
)infoPtr
->DraggingMonitor
;
1070 infoPtr
->DraggingMonitor
= -1;
1072 if (infoPtr
->CanDisplay
)
1074 /* Repaint the area where the monitor was last dragged */
1075 MonSelRepaintMonitor(infoPtr
,
1078 infoPtr
->IsDraggingMonitor
= FALSE
;
1080 /* Repaint the area where the monitor is located */
1081 MonSelRepaintMonitor(infoPtr
,
1085 infoPtr
->IsDraggingMonitor
= FALSE
;
1089 MonSelApplyCursorClipping(infoPtr
,
1095 MonSelInitDragging(IN OUT PMONITORSELWND infoPtr
,
1101 MonSelCancelDragging(infoPtr
);
1102 infoPtr
->IsDraggingMonitor
= FALSE
;
1104 MonSelScreenToPt(infoPtr
,
1108 infoPtr
->ptDrag
= infoPtr
->ptDragBegin
= pt
;
1109 infoPtr
->DraggingMonitor
= (INT
)Index
;
1111 infoPtr
->DraggingMargin
.cx
= ppt
->x
- infoPtr
->Monitors
[Index
].rc
.left
;
1112 infoPtr
->DraggingMargin
.cy
= ppt
->y
- infoPtr
->Monitors
[Index
].rc
.top
;
1113 infoPtr
->rcDragging
= infoPtr
->Monitors
[Index
].rc
;
1115 MonSelApplyCursorClipping(infoPtr
,
1120 MonSelDrag(IN OUT PMONITORSELWND infoPtr
,
1127 if (infoPtr
->DraggingMonitor
>= 0)
1129 MonSelScreenToPt(infoPtr
,
1133 if (!infoPtr
->IsDraggingMonitor
)
1135 szDrag
.cx
= GetSystemMetrics(SM_CXDRAG
);
1136 szDrag
.cy
= GetSystemMetrics(SM_CYDRAG
);
1138 rcDrag
.left
= infoPtr
->Monitors
[infoPtr
->DraggingMonitor
].rc
.left
+ infoPtr
->DraggingMargin
.cx
- (szDrag
.cx
/ 2);
1139 rcDrag
.top
= infoPtr
->Monitors
[infoPtr
->DraggingMonitor
].rc
.top
+ infoPtr
->DraggingMargin
.cy
- (szDrag
.cy
/ 2);
1140 rcDrag
.right
= rcDrag
.left
+ szDrag
.cx
;
1141 rcDrag
.bottom
= rcDrag
.top
+ szDrag
.cy
;
1143 if (!PtInRect(&rcDrag
,
1146 /* The user started moving around the mouse: Begin dragging */
1147 infoPtr
->IsDraggingMonitor
= TRUE
;
1148 MonSelMoveDragRect(infoPtr
,
1154 MonSelMoveDragRect(infoPtr
,
1160 static LRESULT CALLBACK
1161 MonitorSelWndProc(IN HWND hwnd
,
1166 PMONITORSELWND infoPtr
;
1169 infoPtr
= (PMONITORSELWND
)GetWindowLongPtrW(hwnd
,
1172 if (infoPtr
== NULL
&& uMsg
!= WM_CREATE
)
1174 goto HandleDefaultMessage
;
1180 case WM_PRINTCLIENT
:
1187 if (!GetUpdateRect(hwnd
,
1197 hDC
= BeginPaint(hwnd
,
1205 if (infoPtr
->CanDisplay
)
1207 MonSelPaint(infoPtr
,
1224 if (!(wParam
& MK_LBUTTON
))
1226 MonSelCancelDragging(infoPtr
);
1230 if (infoPtr
->LeftBtnDown
)
1232 pt
.x
= (LONG
)LOWORD(lParam
);
1233 pt
.y
= (LONG
)HIWORD(lParam
);
1242 case WM_RBUTTONDOWN
:
1244 if (!(infoPtr
->ControlExStyle
& MSLM_EX_SELECTONRIGHTCLICK
))
1250 case WM_LBUTTONDBLCLK
:
1251 case WM_LBUTTONDOWN
:
1256 if (!infoPtr
->HasFocus
)
1257 SetFocus(infoPtr
->hSelf
);
1259 pt
.x
= (LONG
)LOWORD(lParam
);
1260 pt
.y
= (LONG
)HIWORD(lParam
);
1262 Index
= MonSelHitTest(infoPtr
,
1264 if (Index
>= 0 || (infoPtr
->ControlExStyle
& MSLM_EX_ALLOWSELECTNONE
))
1266 MonSelSetCurSelMonitor(infoPtr
,
1271 if (Index
>= 0 && (uMsg
== WM_LBUTTONDOWN
|| uMsg
== WM_LBUTTONDBLCLK
))
1273 infoPtr
->LeftBtnDown
= TRUE
;
1274 MonSelInitDragging(infoPtr
,
1282 case WM_MBUTTONDOWN
:
1284 if (!infoPtr
->HasFocus
)
1291 MonSelContextMenu(infoPtr
,
1292 (SHORT
)LOWORD(lParam
),
1293 (SHORT
)HIWORD(lParam
));
1299 MonSelCancelDragging(infoPtr
);
1300 infoPtr
->LeftBtnDown
= FALSE
;
1308 virtKey
= (lParam
!= 0 ? (INT
)((LPMSG
)lParam
)->wParam
: 0);
1313 /* change the UI status */
1314 SendMessage(GetAncestor(hwnd
,
1317 MAKEWPARAM(UIS_INITIALIZE
,
1324 Ret
|= DLGC_WANTARROWS
;
1326 if (infoPtr
->ControlExStyle
& MSLM_EX_SELECTBYNUMKEY
)
1327 Ret
|= DLGC_WANTCHARS
;
1333 infoPtr
->HasFocus
= TRUE
;
1334 MonSelRepaintSelected(infoPtr
);
1340 infoPtr
->HasFocus
= FALSE
;
1341 MonSelCancelDragging(infoPtr
);
1342 MonSelRepaintSelected(infoPtr
);
1346 case WM_UPDATEUISTATE
:
1350 Ret
= DefWindowProcW(hwnd
,
1355 OldUIState
= infoPtr
->UIState
;
1356 switch (LOWORD(wParam
))
1359 infoPtr
->UIState
|= HIWORD(wParam
);
1363 infoPtr
->UIState
&= ~HIWORD(wParam
);
1367 if (infoPtr
->UIState
!= OldUIState
)
1368 MonSelRepaintSelected(infoPtr
);
1374 Ret
= (LRESULT
)MonSelChangeFont(infoPtr
,
1376 (BOOL
)LOWORD(lParam
));
1382 infoPtr
->ClientSize
.cx
= LOWORD(lParam
);
1383 infoPtr
->ClientSize
.cy
= HIWORD(lParam
);
1385 /* Don't let MonSelUpdateMonitorsInfo repaint the control
1386 because this won't work properly in case the control
1388 MonSelUpdateMonitorsInfo(infoPtr
,
1390 InvalidateRect(infoPtr
->hSelf
,
1398 Ret
= (LRESULT
)infoPtr
->hFont
;
1404 infoPtr
->Enabled
= ((BOOL
)wParam
!= FALSE
);
1405 MonSelRepaint(infoPtr
);
1409 case WM_STYLECHANGED
:
1411 if (wParam
== GWL_STYLE
)
1413 unsigned int OldEnabled
= infoPtr
->Enabled
;
1414 infoPtr
->Enabled
= !(((LPSTYLESTRUCT
)lParam
)->styleNew
& WS_DISABLED
);
1416 if (OldEnabled
!= infoPtr
->Enabled
)
1417 MonSelRepaint(infoPtr
);
1426 if (infoPtr
->ControlExStyle
& MSLM_EX_SELECTBYARROWKEY
)
1433 Index
= infoPtr
->SelectedMonitor
;
1435 if (infoPtr
->MonitorsCount
!= 0)
1445 MonSelSetCurSelMonitor(infoPtr
,
1455 Index
= infoPtr
->SelectedMonitor
;
1457 if (infoPtr
->MonitorsCount
!= 0)
1460 Index
= (INT
)infoPtr
->MonitorsCount
- 1;
1461 else if (Index
< (INT
)infoPtr
->MonitorsCount
- 1)
1465 if (infoPtr
->SelectedMonitor
< infoPtr
->MonitorsCount
)
1467 MonSelSetCurSelMonitor(infoPtr
,
1480 if ((infoPtr
->ControlExStyle
& MSLM_EX_SELECTBYNUMKEY
) &&
1481 wParam
>= '1' && wParam
<= '9')
1483 INT Index
= (INT
)(wParam
- '1');
1484 if (Index
< (INT
)infoPtr
->MonitorsCount
)
1486 MonSelSetCurSelMonitor(infoPtr
,
1494 case MSLM_SETMONITORSINFO
:
1496 Ret
= MonSelSetMonitorsInfo(infoPtr
,
1498 (const MONSL_MONINFO
*)lParam
);
1502 case MSLM_GETMONITORSINFO
:
1504 Ret
= MonSelGetMonitorsInfo(infoPtr
,
1506 (PMONSL_MONINFO
)lParam
);
1510 case MSLM_GETMONITORINFOCOUNT
:
1512 Ret
= infoPtr
->MonitorsCount
;
1518 Ret
= MonSelHitTest(infoPtr
,
1519 (const POINT
*)wParam
);
1523 case MSLM_SETCURSEL
:
1525 Ret
= MonSelSetCurSelMonitor(infoPtr
,
1531 case MSLM_GETCURSEL
:
1533 Ret
= infoPtr
->SelectedMonitor
;
1537 case MSLM_SETMONITORINFO
:
1539 Ret
= MonSelSetMonitorInfo(infoPtr
,
1541 (const MONSL_MONINFO
*)lParam
);
1545 case MSLM_GETMONITORINFO
:
1547 Ret
= MonSelGetMonitorInfo(infoPtr
,
1549 (PMONSL_MONINFO
)lParam
);
1553 case MSLM_SETEXSTYLE
:
1555 Ret
= MonSelSetExtendedStyle(infoPtr
,
1560 case MSLM_GETEXSTYLE
:
1562 Ret
= MonSelGetExtendedStyle(infoPtr
);
1566 case MSLM_GETMONITORRECT
:
1568 Ret
= (LRESULT
)MonSelGetMonitorRect(infoPtr
,
1576 infoPtr
= (PMONITORSELWND
) HeapAlloc(GetProcessHeap(),
1578 sizeof(MONITORSELWND
));
1579 if (infoPtr
== NULL
)
1586 sizeof(MONITORSELWND
));
1587 infoPtr
->hSelf
= hwnd
;
1588 infoPtr
->hNotify
= ((LPCREATESTRUCTW
)lParam
)->hwndParent
;
1589 infoPtr
->Enabled
= !(((LPCREATESTRUCTW
)lParam
)->style
& WS_DISABLED
);
1590 infoPtr
->UIState
= SendMessage(hwnd
,
1595 SetWindowLongPtrW(hwnd
,
1599 MonSelCreate(infoPtr
);
1605 MonSelDestroy(infoPtr
);
1607 HeapFree(GetProcessHeap(),
1610 SetWindowLongPtrW(hwnd
,
1618 HandleDefaultMessage
:
1619 Ret
= DefWindowProcW(hwnd
,
1631 RegisterMonitorSelectionControl(IN HINSTANCE hInstance
)
1635 wc
.style
= CS_DBLCLKS
;
1636 wc
.lpfnWndProc
= MonitorSelWndProc
;
1637 wc
.cbWndExtra
= sizeof(PMONITORSELWND
);
1638 wc
.hInstance
= hInstance
;
1639 wc
.hCursor
= LoadCursorW(NULL
,
1641 wc
.hbrBackground
= (HBRUSH
)(COLOR_APPWORKSPACE
+ 1);
1642 wc
.lpszClassName
= szMonitorSelWndClass
;
1644 return RegisterClass(&wc
) != 0;
1648 UnregisterMonitorSelectionControl(IN HINSTANCE hInstance
)
1650 UnregisterClassW(szMonitorSelWndClass
,