mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
Add very basic dragging support to the monitor selection control
svn path=/trunk/; revision=29665
This commit is contained in:
parent
cabbd02835
commit
36f1aa644b
1 changed files with 389 additions and 78 deletions
|
@ -27,11 +27,17 @@ typedef struct _MONITORSELWND
|
|||
UINT Enabled : 1;
|
||||
UINT HasFocus : 1;
|
||||
UINT CanDisplay : 1;
|
||||
UINT LeftBtnDown : 1;
|
||||
UINT IsDraggingMonitor : 1;
|
||||
};
|
||||
};
|
||||
DWORD ControlExStyle;
|
||||
DWORD MonitorsCount;
|
||||
INT SelectedMonitor;
|
||||
INT DraggingMonitor;
|
||||
RECT rcDragging;
|
||||
POINT ptDrag, ptDragBegin;
|
||||
SIZE DraggingMargin;
|
||||
PMONSL_MONINFO MonitorInfo;
|
||||
PMONSL_MON Monitors;
|
||||
RECT rcExtent;
|
||||
|
@ -265,17 +271,36 @@ MonSelRepaintMonitor(IN PMONITORSELWND infoPtr,
|
|||
IN DWORD Index)
|
||||
{
|
||||
RECT rc;
|
||||
BOOL NoRepaint = FALSE;
|
||||
|
||||
if (Index < infoPtr->MonitorsCount)
|
||||
{
|
||||
if (Index == (DWORD)infoPtr->DraggingMonitor)
|
||||
{
|
||||
if (infoPtr->IsDraggingMonitor)
|
||||
{
|
||||
MonSelRectToScreen(infoPtr,
|
||||
&infoPtr->rcDragging,
|
||||
&rc);
|
||||
}
|
||||
else
|
||||
NoRepaint = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
MonSelRectToScreen(infoPtr,
|
||||
&infoPtr->Monitors[Index].rc,
|
||||
&rc);
|
||||
}
|
||||
|
||||
if (!NoRepaint)
|
||||
{
|
||||
InvalidateRect(infoPtr->hSelf,
|
||||
&rc,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
MonSelRepaintSelected(IN PMONITORSELWND infoPtr)
|
||||
|
@ -370,6 +395,9 @@ MonSelSetMonitorsInfo(IN OUT PMONITORSELWND infoPtr,
|
|||
DWORD Index;
|
||||
BOOL Ret = TRUE;
|
||||
|
||||
if (infoPtr->DraggingMonitor >= 0)
|
||||
return FALSE;
|
||||
|
||||
if (infoPtr->MonitorInfo != NULL)
|
||||
{
|
||||
LocalFree((HLOCAL)infoPtr->MonitorInfo);
|
||||
|
@ -466,7 +494,8 @@ MonSelSetMonitorInfo(IN OUT PMONITORSELWND infoPtr,
|
|||
IN INT Index,
|
||||
IN const MONSL_MONINFO *MonitorsInfo)
|
||||
{
|
||||
if (Index >= 0 && Index < (INT)infoPtr->MonitorsCount)
|
||||
if (infoPtr->DraggingMonitor < 0 &&
|
||||
Index >= 0 && Index < (INT)infoPtr->MonitorsCount)
|
||||
{
|
||||
CopyMemory(&infoPtr->MonitorInfo[Index],
|
||||
MonitorsInfo,
|
||||
|
@ -531,7 +560,8 @@ MonSelSetCurSelMonitor(IN OUT PMONITORSELWND infoPtr,
|
|||
BOOL PreventSelect = FALSE;
|
||||
BOOL Ret = FALSE;
|
||||
|
||||
if (Index == -1 || Index < (INT)infoPtr->MonitorsCount)
|
||||
if (infoPtr->DraggingMonitor < 0 &&
|
||||
(Index == -1 || Index < (INT)infoPtr->MonitorsCount))
|
||||
{
|
||||
if (Index != infoPtr->SelectedMonitor)
|
||||
{
|
||||
|
@ -594,6 +624,7 @@ MonSelCreate(IN OUT PMONITORSELWND infoPtr)
|
|||
infoPtr->SelectionFrame.cx = infoPtr->SelectionFrame.cy = 4;
|
||||
infoPtr->Margin.cx = infoPtr->Margin.cy = 20;
|
||||
infoPtr->SelectedMonitor = -1;
|
||||
infoPtr->DraggingMonitor = -1;
|
||||
infoPtr->ControlExStyle = MSLM_EX_ALLOWSELECTDISABLED | MSLM_EX_HIDENUMBERONSINGLE |
|
||||
MSLM_EX_SELECTONRIGHTCLICK;
|
||||
return;
|
||||
|
@ -624,6 +655,9 @@ static BOOL
|
|||
MonSelSetExtendedStyle(IN OUT PMONITORSELWND infoPtr,
|
||||
IN DWORD dwExtendedStyle)
|
||||
{
|
||||
if (infoPtr->DraggingMonitor >= 0)
|
||||
return FALSE;
|
||||
|
||||
if (dwExtendedStyle != infoPtr->ControlExStyle)
|
||||
{
|
||||
infoPtr->ControlExStyle = dwExtendedStyle;
|
||||
|
@ -724,13 +758,92 @@ MonSelDrawDisabledRect(IN OUT PMONITORSELWND infoPtr,
|
|||
return Ret;
|
||||
}
|
||||
|
||||
static VOID
|
||||
MonSelPaintMonitor(IN OUT PMONITORSELWND infoPtr,
|
||||
IN HDC hDC,
|
||||
IN DWORD Index,
|
||||
IN OUT PRECT prc,
|
||||
IN COLORREF crDefFontColor,
|
||||
IN BOOL bHideNumber)
|
||||
{
|
||||
HFONT hFont, hPrevFont;
|
||||
COLORREF crPrevText;
|
||||
|
||||
if ((INT)Index == infoPtr->SelectedMonitor)
|
||||
{
|
||||
FillRect(hDC,
|
||||
prc,
|
||||
(HBRUSH)(COLOR_HIGHLIGHT + 1));
|
||||
|
||||
if (infoPtr->HasFocus && !(infoPtr->UIState & UISF_HIDEFOCUS))
|
||||
{
|
||||
/* NOTE: We need to switch the text color to the default, because
|
||||
DrawFocusRect draws a solid line if the text is white! */
|
||||
|
||||
crPrevText = SetTextColor(hDC,
|
||||
crDefFontColor);
|
||||
|
||||
DrawFocusRect(hDC,
|
||||
prc);
|
||||
|
||||
SetTextColor(hDC,
|
||||
crPrevText);
|
||||
}
|
||||
}
|
||||
|
||||
InflateRect(prc,
|
||||
-infoPtr->SelectionFrame.cx,
|
||||
-infoPtr->SelectionFrame.cy);
|
||||
|
||||
Rectangle(hDC,
|
||||
prc->left,
|
||||
prc->top,
|
||||
prc->right,
|
||||
prc->bottom);
|
||||
|
||||
InflateRect(prc,
|
||||
-1,
|
||||
-1);
|
||||
|
||||
if (!bHideNumber)
|
||||
{
|
||||
hFont = MonSelGetMonitorFont(infoPtr,
|
||||
hDC,
|
||||
Index);
|
||||
if (hFont != NULL)
|
||||
{
|
||||
hPrevFont = SelectObject(hDC,
|
||||
hFont);
|
||||
|
||||
DrawText(hDC,
|
||||
infoPtr->Monitors[Index].szCaption,
|
||||
-1,
|
||||
prc,
|
||||
DT_VCENTER | DT_CENTER | DT_NOPREFIX | DT_SINGLELINE);
|
||||
|
||||
SelectObject(hDC,
|
||||
hPrevFont);
|
||||
}
|
||||
}
|
||||
|
||||
if (infoPtr->MonitorInfo[Index].Flags & MSL_MIF_DISABLED)
|
||||
{
|
||||
InflateRect(prc,
|
||||
1,
|
||||
1);
|
||||
|
||||
MonSelDrawDisabledRect(infoPtr,
|
||||
hDC,
|
||||
prc);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
MonSelPaint(IN OUT PMONITORSELWND infoPtr,
|
||||
IN HDC hDC,
|
||||
IN const RECT *prcUpdate)
|
||||
{
|
||||
COLORREF crPrevText, crPrevText2;
|
||||
HFONT hFont, hPrevFont;
|
||||
COLORREF crPrevText;
|
||||
HBRUSH hbBk, hbOldBk;
|
||||
HPEN hpFg, hpOldFg;
|
||||
DWORD Index;
|
||||
|
@ -757,83 +870,47 @@ MonSelPaint(IN OUT PMONITORSELWND infoPtr,
|
|||
|
||||
for (Index = 0; Index < infoPtr->MonitorsCount; Index++)
|
||||
{
|
||||
MonSelRectToScreen(infoPtr,
|
||||
&infoPtr->Monitors[Index].rc,
|
||||
&rc);
|
||||
|
||||
if (!IntersectRect(&rctmp,
|
||||
&rc,
|
||||
prcUpdate))
|
||||
if (infoPtr->IsDraggingMonitor &&
|
||||
(DWORD)infoPtr->DraggingMonitor == Index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((INT)Index == infoPtr->SelectedMonitor)
|
||||
{
|
||||
FillRect(hDC,
|
||||
&rc,
|
||||
(HBRUSH)(COLOR_HIGHLIGHT + 1));
|
||||
|
||||
if (infoPtr->HasFocus && !(infoPtr->UIState & UISF_HIDEFOCUS))
|
||||
{
|
||||
/* NOTE: We need to switch the text color to the default, because
|
||||
DrawFocusRect draws a solid line if the text is white! */
|
||||
|
||||
crPrevText2 = SetTextColor(hDC,
|
||||
crPrevText);
|
||||
|
||||
DrawFocusRect(hDC,
|
||||
MonSelRectToScreen(infoPtr,
|
||||
&infoPtr->Monitors[Index].rc,
|
||||
&rc);
|
||||
|
||||
SetTextColor(hDC,
|
||||
crPrevText2);
|
||||
}
|
||||
}
|
||||
|
||||
InflateRect(&rc,
|
||||
-infoPtr->SelectionFrame.cx,
|
||||
-infoPtr->SelectionFrame.cy);
|
||||
|
||||
Rectangle(hDC,
|
||||
rc.left,
|
||||
rc.top,
|
||||
rc.right,
|
||||
rc.bottom);
|
||||
|
||||
InflateRect(&rc,
|
||||
-1,
|
||||
-1);
|
||||
|
||||
if (!bHideNumber)
|
||||
{
|
||||
hFont = MonSelGetMonitorFont(infoPtr,
|
||||
hDC,
|
||||
Index);
|
||||
if (hFont != NULL)
|
||||
{
|
||||
hPrevFont = SelectObject(hDC,
|
||||
hFont);
|
||||
|
||||
DrawText(hDC,
|
||||
infoPtr->Monitors[Index].szCaption,
|
||||
-1,
|
||||
if (IntersectRect(&rctmp,
|
||||
&rc,
|
||||
DT_VCENTER | DT_CENTER | DT_NOPREFIX | DT_SINGLELINE);
|
||||
|
||||
SelectObject(hDC,
|
||||
hPrevFont);
|
||||
}
|
||||
}
|
||||
|
||||
if (infoPtr->MonitorInfo[Index].Flags & MSL_MIF_DISABLED)
|
||||
prcUpdate))
|
||||
{
|
||||
InflateRect(&rc,
|
||||
1,
|
||||
1);
|
||||
|
||||
MonSelDrawDisabledRect(infoPtr,
|
||||
MonSelPaintMonitor(infoPtr,
|
||||
hDC,
|
||||
Index,
|
||||
&rc,
|
||||
crPrevText,
|
||||
bHideNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/* Paint the dragging monitor last */
|
||||
if (infoPtr->IsDraggingMonitor &&
|
||||
(DWORD)infoPtr->DraggingMonitor >= 0)
|
||||
{
|
||||
MonSelRectToScreen(infoPtr,
|
||||
&infoPtr->rcDragging,
|
||||
&rc);
|
||||
|
||||
if (IntersectRect(&rctmp,
|
||||
&rc,
|
||||
prcUpdate))
|
||||
{
|
||||
MonSelPaintMonitor(infoPtr,
|
||||
hDC,
|
||||
(DWORD)infoPtr->DraggingMonitor,
|
||||
&rc,
|
||||
crPrevText,
|
||||
bHideNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -882,6 +959,202 @@ MonSelContextMenu(IN OUT PMONITORSELWND infoPtr,
|
|||
nm.pt.y));
|
||||
}
|
||||
|
||||
static VOID
|
||||
MonSelApplyCursorClipping(IN PMONITORSELWND infoPtr,
|
||||
IN BOOL bClip)
|
||||
{
|
||||
RECT rc;
|
||||
|
||||
if (bClip)
|
||||
{
|
||||
rc.left = rc.top = 0;
|
||||
rc.right = infoPtr->ClientSize.cx;
|
||||
rc.bottom = infoPtr->ClientSize.cy;
|
||||
|
||||
if (MapWindowPoints(infoPtr->hSelf,
|
||||
NULL,
|
||||
(LPPOINT)&rc,
|
||||
2))
|
||||
{
|
||||
ClipCursor(&rc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClipCursor(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
MonSelMoveDragRect(IN OUT PMONITORSELWND infoPtr,
|
||||
IN PPOINT ppt)
|
||||
{
|
||||
RECT rcPrev, rcUpdate, *prc;
|
||||
HRGN hRgnPrev;
|
||||
HDC hDC;
|
||||
|
||||
if (infoPtr->CanDisplay)
|
||||
{
|
||||
hDC = GetDC(infoPtr->hSelf);
|
||||
if (hDC != NULL)
|
||||
{
|
||||
if (infoPtr->ptDrag.x != ppt->x ||
|
||||
infoPtr->ptDrag.y != ppt->y)
|
||||
{
|
||||
infoPtr->ptDrag = *ppt;
|
||||
|
||||
rcPrev = infoPtr->rcDragging;
|
||||
|
||||
/* Calculate updated dragging rectangle */
|
||||
prc = &infoPtr->Monitors[infoPtr->DraggingMonitor].rc;
|
||||
infoPtr->rcDragging.left = ppt->x - infoPtr->DraggingMargin.cx;
|
||||
infoPtr->rcDragging.top = ppt->y - infoPtr->DraggingMargin.cy;
|
||||
infoPtr->rcDragging.right = infoPtr->rcDragging.left + (prc->right - prc->left);
|
||||
infoPtr->rcDragging.bottom = infoPtr->rcDragging.top + (prc->bottom - prc->top);
|
||||
|
||||
hRgnPrev = CreateRectRgn(rcPrev.left,
|
||||
rcPrev.top,
|
||||
rcPrev.right,
|
||||
rcPrev.bottom);
|
||||
|
||||
if (hRgnPrev != NULL)
|
||||
{
|
||||
if (!ScrollDC(hDC,
|
||||
infoPtr->rcDragging.left - rcPrev.left,
|
||||
infoPtr->rcDragging.top - rcPrev.top,
|
||||
&rcPrev,
|
||||
NULL,
|
||||
hRgnPrev,
|
||||
&rcUpdate) ||
|
||||
!InvalidateRgn(infoPtr->hSelf,
|
||||
hRgnPrev,
|
||||
TRUE))
|
||||
{
|
||||
DeleteObject(hRgnPrev);
|
||||
goto InvRects;
|
||||
}
|
||||
|
||||
DeleteObject(hRgnPrev);
|
||||
}
|
||||
else
|
||||
{
|
||||
InvRects:
|
||||
InvalidateRect(infoPtr->hSelf,
|
||||
&rcPrev,
|
||||
TRUE);
|
||||
InvalidateRect(infoPtr->hSelf,
|
||||
&infoPtr->rcDragging,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseDC(infoPtr->hSelf,
|
||||
hDC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
MonSelCancelDragging(IN OUT PMONITORSELWND infoPtr)
|
||||
{
|
||||
DWORD Index;
|
||||
|
||||
if (infoPtr->DraggingMonitor >= 0)
|
||||
{
|
||||
MonSelMoveDragRect(infoPtr,
|
||||
&infoPtr->ptDragBegin);
|
||||
|
||||
Index = (DWORD)infoPtr->DraggingMonitor;
|
||||
infoPtr->DraggingMonitor = -1;
|
||||
|
||||
if (infoPtr->CanDisplay)
|
||||
{
|
||||
/* Repaint the area where the monitor was last dragged */
|
||||
MonSelRepaintMonitor(infoPtr,
|
||||
Index);
|
||||
|
||||
infoPtr->IsDraggingMonitor = FALSE;
|
||||
|
||||
/* Repaint the area where the monitor is located */
|
||||
MonSelRepaintMonitor(infoPtr,
|
||||
Index);
|
||||
}
|
||||
else
|
||||
infoPtr->IsDraggingMonitor = FALSE;
|
||||
|
||||
ReleaseCapture();
|
||||
|
||||
MonSelApplyCursorClipping(infoPtr,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
MonSelInitDragging(IN OUT PMONITORSELWND infoPtr,
|
||||
IN DWORD Index,
|
||||
IN PPOINT ppt)
|
||||
{
|
||||
POINT pt;
|
||||
|
||||
MonSelCancelDragging(infoPtr);
|
||||
infoPtr->IsDraggingMonitor = FALSE;
|
||||
|
||||
MonSelScreenToPt(infoPtr,
|
||||
ppt,
|
||||
&pt);
|
||||
|
||||
infoPtr->ptDrag = infoPtr->ptDragBegin = pt;
|
||||
infoPtr->DraggingMonitor = (INT)Index;
|
||||
|
||||
infoPtr->DraggingMargin.cx = ppt->x - infoPtr->Monitors[Index].rc.left;
|
||||
infoPtr->DraggingMargin.cy = ppt->y - infoPtr->Monitors[Index].rc.top;
|
||||
infoPtr->rcDragging = infoPtr->Monitors[Index].rc;
|
||||
|
||||
MonSelApplyCursorClipping(infoPtr,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static VOID
|
||||
MonSelDrag(IN OUT PMONITORSELWND infoPtr,
|
||||
IN PPOINT ppt)
|
||||
{
|
||||
SIZE szDrag;
|
||||
POINT pt;
|
||||
RECT rcDrag;
|
||||
|
||||
if (infoPtr->DraggingMonitor >= 0)
|
||||
{
|
||||
MonSelScreenToPt(infoPtr,
|
||||
ppt,
|
||||
&pt);
|
||||
|
||||
if (!infoPtr->IsDraggingMonitor)
|
||||
{
|
||||
szDrag.cx = GetSystemMetrics(SM_CXDRAG);
|
||||
szDrag.cy = GetSystemMetrics(SM_CYDRAG);
|
||||
|
||||
rcDrag.left = infoPtr->Monitors[infoPtr->DraggingMonitor].rc.left + infoPtr->DraggingMargin.cx - (szDrag.cx / 2);
|
||||
rcDrag.top = infoPtr->Monitors[infoPtr->DraggingMonitor].rc.top + infoPtr->DraggingMargin.cy - (szDrag.cy / 2);
|
||||
rcDrag.right = rcDrag.left + szDrag.cx;
|
||||
rcDrag.bottom = rcDrag.top + szDrag.cy;
|
||||
|
||||
if (!PtInRect(&rcDrag,
|
||||
pt))
|
||||
{
|
||||
/* The user started moving around the mouse: Begin dragging */
|
||||
infoPtr->IsDraggingMonitor = TRUE;
|
||||
MonSelMoveDragRect(infoPtr,
|
||||
&pt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MonSelMoveDragRect(infoPtr,
|
||||
&pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
MonitorSelWndProc(IN HWND hwnd,
|
||||
IN UINT uMsg,
|
||||
|
@ -942,6 +1215,28 @@ MonitorSelWndProc(IN HWND hwnd,
|
|||
break;
|
||||
}
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
POINT pt;
|
||||
|
||||
if (!(wParam & MK_LBUTTON))
|
||||
{
|
||||
MonSelCancelDragging(infoPtr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (infoPtr->LeftBtnDown)
|
||||
{
|
||||
pt.x = (LONG)LOWORD(lParam);
|
||||
pt.y = (LONG)HIWORD(lParam);
|
||||
|
||||
MonSelDrag(infoPtr,
|
||||
&pt);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RBUTTONDOWN:
|
||||
{
|
||||
if (!(infoPtr->ControlExStyle & MSLM_EX_SELECTONRIGHTCLICK))
|
||||
|
@ -968,6 +1263,14 @@ MonitorSelWndProc(IN HWND hwnd,
|
|||
TRUE);
|
||||
}
|
||||
|
||||
if (Index >= 0 && (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK))
|
||||
{
|
||||
infoPtr->LeftBtnDown = TRUE;
|
||||
MonSelInitDragging(infoPtr,
|
||||
(DWORD)Index,
|
||||
&pt);
|
||||
}
|
||||
|
||||
/* fall through */
|
||||
}
|
||||
|
||||
|
@ -986,6 +1289,13 @@ MonitorSelWndProc(IN HWND hwnd,
|
|||
break;
|
||||
}
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
{
|
||||
MonSelCancelDragging(infoPtr);
|
||||
infoPtr->LeftBtnDown = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_GETDLGCODE:
|
||||
{
|
||||
INT virtKey;
|
||||
|
@ -1020,6 +1330,7 @@ MonitorSelWndProc(IN HWND hwnd,
|
|||
case WM_KILLFOCUS:
|
||||
{
|
||||
infoPtr->HasFocus = FALSE;
|
||||
MonSelCancelDragging(infoPtr);
|
||||
MonSelRepaintSelected(infoPtr);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue