diff --git a/reactos/lib/user32/controls/scrollbar.c b/reactos/lib/user32/controls/scrollbar.c index f37a2c28e84..841db090260 100644 --- a/reactos/lib/user32/controls/scrollbar.c +++ b/reactos/lib/user32/controls/scrollbar.c @@ -1,4 +1,5 @@ -/* +/* $Id $ + * * ReactOS User32 Library * - ScrollBar control * @@ -6,7 +7,7 @@ * Copyright 2003 Thomas Weidenmueller * Copyright 2003 Filip Navara * - * Portions based on Wine code. + * Based on Wine code. * * Copyright 1993 Martin Ayotte * Copyright 1994, 1996 Alexandre Julliard @@ -35,6 +36,7 @@ #include #include #include +#include /* GLOBAL VARIABLES ***********************************************************/ @@ -46,15 +48,33 @@ #define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */ #define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right arrow */ +#define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when + holding the button down */ +#define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */ + +#define SCROLL_TIMER 0 /* Scroll timer id */ + + /* Thumb-tracking info */ +static HWND ScrollTrackingWin = 0; +static INT ScrollTrackingBar = 0; +static INT ScrollTrackingPos = 0; +static INT ScrollTrackingVal = 0; +static BOOL ScrollMovingThumb = FALSE; + +static DWORD ScrollTrackHitTest = SCROLL_NOWHERE; +static BOOL ScrollTrackVertical; + HBRUSH DefWndControlColor(HDC hDC, UINT ctlType); /* PRIVATE FUNCTIONS **********************************************************/ + static void IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, - INT ArrowSize, PSCROLLBARINFO ScrollBarInfo) + PSCROLLBARINFO ScrollBarInfo) { INT ThumbSize = ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; + INT ThumbTop = ScrollBarInfo->xyThumbTop; RECT Rect; HPEN hSavePen; HBRUSH hSaveBrush, hBrush; @@ -87,8 +107,8 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, /* Calculate the scroll rectangle */ if (Vertical) { - Rect.top = ScrollBarInfo->rcScrollBar.top + ArrowSize; - Rect.bottom = ScrollBarInfo->rcScrollBar.bottom - ArrowSize; + Rect.top = ScrollBarInfo->rcScrollBar.top + ScrollBarInfo->dxyLineButton; + Rect.bottom = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->dxyLineButton; Rect.left = ScrollBarInfo->rcScrollBar.left; Rect.right = ScrollBarInfo->rcScrollBar.right; } @@ -96,8 +116,8 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, { Rect.top = ScrollBarInfo->rcScrollBar.top; Rect.bottom = ScrollBarInfo->rcScrollBar.bottom; - Rect.left = ScrollBarInfo->rcScrollBar.left + ArrowSize; - Rect.right = ScrollBarInfo->rcScrollBar.right - ArrowSize; + Rect.left = ScrollBarInfo->rcScrollBar.left + ScrollBarInfo->dxyLineButton; + Rect.right = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->dxyLineButton; } /* Draw the scroll rectangles and thumb */ @@ -112,7 +132,7 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, return; } - ScrollBarInfo->xyThumbTop -= ArrowSize; + ThumbTop -= ScrollBarInfo->dxyLineButton; if (ScrollBarInfo->dxyLineButton) { @@ -121,18 +141,18 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, if (ThumbSize) { PatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left, - ScrollBarInfo->xyThumbTop, TopSelected ? BLACKNESS : PATCOPY); - Rect.top += ScrollBarInfo->xyThumbTop; + ThumbTop, TopSelected ? BLACKNESS : PATCOPY); + Rect.top += ThumbTop; PatBlt(hDC, Rect.left, Rect.top + ThumbSize, Rect.right - Rect.left, Rect.bottom - Rect.top - ThumbSize, BottomSelected ? BLACKNESS : PATCOPY); Rect.bottom = Rect.top + ThumbSize; } else { - if (ScrollBarInfo->xyThumbTop) + if (ThumbTop) { PatBlt(hDC, Rect.left, ScrollBarInfo->dxyLineButton, - Rect.right - Rect.left, Rect.bottom - Rect.bottom, PATCOPY); + Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY); } } } @@ -140,9 +160,9 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, { if (ThumbSize) { - PatBlt(hDC, Rect.left, Rect.top, ScrollBarInfo->xyThumbTop, + PatBlt(hDC, Rect.left, Rect.top, ThumbTop, Rect.bottom - Rect.top, TopSelected ? BLACKNESS : PATCOPY); - Rect.left += ScrollBarInfo->xyThumbTop; + Rect.left += ThumbTop; PatBlt(hDC, Rect.left + ThumbSize, Rect.top, Rect.right - Rect.left - ThumbSize, Rect.bottom - Rect.top, BottomSelected ? BLACKNESS : PATCOPY); @@ -150,7 +170,7 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, } else { - if (ScrollBarInfo->xyThumbTop) + if (ThumbTop) { PatBlt(hDC, ScrollBarInfo->dxyLineButton, Rect.top, Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY); @@ -168,46 +188,90 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, SelectObject(hDC, hSaveBrush); } -static void -IntDrawScrollArrows(HDC hDC, PSCROLLBARINFO ScrollBarInfo, LPRECT Rect, - INT ArrowSize, BOOL Vertical) +STATIC VOID FASTCALL +IntDrawScrollArrows(HDC hDC, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical) { - RECT RectLT, RectRB; - INT ScrollDirFlagLT, ScrollDirFlagRB; + RECT RectLT, RectRB; + INT ScrollDirFlagLT, ScrollDirFlagRB; - RectLT = RectRB = *Rect; - if (Vertical) - { + RectLT = RectRB = ScrollBarInfo->rcScrollBar; + if (Vertical) + { ScrollDirFlagLT = DFCS_SCROLLUP; ScrollDirFlagRB = DFCS_SCROLLDOWN; - RectLT.bottom = RectLT.top + ArrowSize; - RectRB.top = RectRB.bottom - ArrowSize; - } + RectLT.bottom = RectLT.top + ScrollBarInfo->dxyLineButton; + RectRB.top = RectRB.bottom - ScrollBarInfo->dxyLineButton; + } else - { + { ScrollDirFlagLT = DFCS_SCROLLLEFT; ScrollDirFlagRB = DFCS_SCROLLRIGHT; - RectLT.right = RectLT.left + ArrowSize; - RectRB.left = RectRB.right - ArrowSize; - } + RectLT.right = RectLT.left + ScrollBarInfo->dxyLineButton; + RectRB.left = RectRB.right - ScrollBarInfo->dxyLineButton; + } if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_PRESSED) - ScrollDirFlagLT |= DFCS_PUSHED | DFCS_FLAT; + { + ScrollDirFlagLT |= DFCS_PUSHED | DFCS_FLAT; + } if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE) - ScrollDirFlagLT |= DFCS_INACTIVE; + { + ScrollDirFlagLT |= DFCS_INACTIVE; + } if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_PRESSED) - ScrollDirFlagRB |= DFCS_PUSHED | DFCS_FLAT; + { + ScrollDirFlagRB |= DFCS_PUSHED | DFCS_FLAT; + } if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE) - ScrollDirFlagRB |= DFCS_INACTIVE; + { + ScrollDirFlagRB |= DFCS_INACTIVE; + } DrawFrameControl(hDC, &RectLT, DFC_SCROLL, ScrollDirFlagLT); DrawFrameControl(hDC, &RectRB, DFC_SCROLL, ScrollDirFlagRB); } +STATIC VOID FASTCALL +IntScrollDrawMovingThumb(HDC Dc, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical) +{ + INT Pos = ScrollTrackingPos; + INT MaxSize; + INT OldTop; + + if (Vertical) + { + MaxSize = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->rcScrollBar.top; + } + else + { + MaxSize = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->rcScrollBar.left; + } + + MaxSize -= ScrollBarInfo->dxyLineButton + ScrollBarInfo->xyThumbBottom + - ScrollBarInfo->xyThumbTop; + + if (Pos < ScrollBarInfo->dxyLineButton) + { + Pos = ScrollBarInfo->dxyLineButton; + } + else if (MaxSize < Pos) + { + Pos = MaxSize; + } + + OldTop = ScrollBarInfo->xyThumbTop; + ScrollBarInfo->xyThumbBottom = Pos + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; + ScrollBarInfo->xyThumbTop = Pos; + IntDrawScrollInterior(ScrollTrackingWin, Dc, ScrollTrackingBar, Vertical, ScrollBarInfo); + ScrollBarInfo->xyThumbBottom = OldTop + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; + ScrollBarInfo->xyThumbTop = OldTop; + + ScrollMovingThumb = ! ScrollMovingThumb; +} + void IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar) { - INT ArrowSize = 0; INT ThumbSize; SCROLLBARINFO Info; BOOL Vertical; @@ -240,21 +304,20 @@ IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar) return; } - ArrowSize = Info.dxyLineButton; ThumbSize = Info.xyThumbBottom - Info.xyThumbTop; /* * Draw the arrows. */ - if (ArrowSize) - IntDrawScrollArrows(hDC, &Info, &Info.rcScrollBar, ArrowSize, Vertical); + if (Info.dxyLineButton) + IntDrawScrollArrows(hDC, &Info, Vertical); /* * Draw the interior. */ - IntDrawScrollInterior(hWnd, hDC, nBar, Vertical, ArrowSize, &Info); + IntDrawScrollInterior(hWnd, hDC, nBar, Vertical, &Info); /* * If scroll bar has focus, reposition the caret. @@ -269,79 +332,543 @@ IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar) } } -static BOOL -IntScrollPtInRectEx(LPRECT lpRect, POINT pt, BOOL Vertical) +STATIC BOOL FASTCALL +IntScrollPtInRectEx(LPRECT Rect, POINT Pt, BOOL Vertical) { - RECT Rect = *lpRect; - if (Vertical) - { - Rect.left -= lpRect->right - lpRect->left; - Rect.right += lpRect->right - lpRect->left; - } + RECT TempRect = *Rect; + if (Vertical) + { + TempRect.left -= Rect->right - Rect->left; + TempRect.right += Rect->right - Rect->left; + } else - { - Rect.top -= lpRect->bottom - lpRect->top; - Rect.bottom += lpRect->bottom - lpRect->top; - } - return PtInRect(&Rect, pt); + { + TempRect.top -= Rect->bottom - Rect->top; + TempRect.bottom += Rect->bottom - Rect->top; + } + + return PtInRect(&TempRect, Pt); } -DWORD -IntScrollHitTest(HWND hWnd, INT nBar, POINT pt, BOOL bDragging) +STATIC LONG FASTCALL +IntScrollGetObjectId(INT SBType) { - SCROLLBARINFO ScrollButtonInfo; - RECT WindowRect; - INT ArrowSize, ThumbSize, ThumbPos; - BOOL Vertical = (nBar == SB_VERT); /* FIXME - ((Window->Style & SBS_VERT) != 0) */ + if (SB_VERT == SBType) + { + return OBJID_VSCROLL; + } + if (SB_HORZ == SBType) + { + return OBJID_HSCROLL; + } - NtUserGetWindowRect(hWnd, &WindowRect); - - ScrollButtonInfo.cbSize = sizeof(SCROLLBARINFO); - NtUserGetScrollBarInfo(hWnd, Vertical ? OBJID_VSCROLL : OBJID_HSCROLL, - &ScrollButtonInfo); - - OffsetRect(&ScrollButtonInfo.rcScrollBar, WindowRect.left, WindowRect.top); + return OBJID_CLIENT; +} - if ((bDragging && !IntScrollPtInRectEx(&ScrollButtonInfo.rcScrollBar, pt, Vertical)) || - !PtInRect(&ScrollButtonInfo.rcScrollBar, pt)) - { +STATIC BOOL FASTCALL +IntGetScrollBarInfo(HWND Wnd, INT SBType, PSCROLLBARINFO ScrollBarInfo) +{ + ScrollBarInfo->cbSize = sizeof(SCROLLBARINFO); + + return NtUserGetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), ScrollBarInfo); +} + +STATIC DWORD FASTCALL +IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo, BOOL Vertical, POINT Pt, BOOL Dragging) +{ + INT ArrowSize, ThumbSize, ThumbPos; + + if ((Dragging && ! IntScrollPtInRectEx(&ScrollBarInfo->rcScrollBar, Pt, Vertical)) || + ! PtInRect(&ScrollBarInfo->rcScrollBar, Pt)) + { return SCROLL_NOWHERE; - } + } - ThumbPos = ScrollButtonInfo.xyThumbTop; - ThumbSize = ScrollButtonInfo.xyThumbBottom - ThumbPos; - ArrowSize = ScrollButtonInfo.dxyLineButton; + ThumbPos = ScrollBarInfo->xyThumbTop; + ThumbSize = ScrollBarInfo->xyThumbBottom - ThumbPos; + ArrowSize = ScrollBarInfo->dxyLineButton; - if (Vertical) - { - if (pt.y < ScrollButtonInfo.rcScrollBar.top + ArrowSize) - return SCROLL_TOP_ARROW; - if (pt.y >= ScrollButtonInfo.rcScrollBar.bottom - ArrowSize) - return SCROLL_BOTTOM_ARROW; - if (!ThumbPos) - return SCROLL_TOP_RECT; - pt.y -= ScrollButtonInfo.rcScrollBar.top; - if (pt.y < ThumbPos) - return SCROLL_TOP_RECT; - if (pt.y >= ThumbPos + ThumbSize) - return SCROLL_BOTTOM_RECT; - } - else - { - if (pt.x < ScrollButtonInfo.rcScrollBar.left + ArrowSize) - return SCROLL_TOP_ARROW; - if (pt.x >= ScrollButtonInfo.rcScrollBar.right - ArrowSize) - return SCROLL_BOTTOM_ARROW; - if (!ThumbPos) - return SCROLL_TOP_RECT; - pt.x -= ScrollButtonInfo.rcScrollBar.left; - if (pt.x < ThumbPos) - return SCROLL_TOP_RECT; - if (pt.x >= ThumbPos + ThumbSize) - return SCROLL_BOTTOM_RECT; - } + if (Vertical) + { + if (Pt.y < ScrollBarInfo->rcScrollBar.top + ArrowSize) + { + return SCROLL_TOP_ARROW; + } + if (ScrollBarInfo->rcScrollBar.bottom - ArrowSize <= Pt.y) + { + return SCROLL_BOTTOM_ARROW; + } + if (0 == ThumbPos) + { + return SCROLL_TOP_RECT; + } + Pt.y -= ScrollBarInfo->rcScrollBar.top; + if (Pt.y < ThumbPos) + { + return SCROLL_TOP_RECT; + } + if (ThumbPos + ThumbSize <= Pt.y) + { + return SCROLL_BOTTOM_RECT; + } + } + else + { + if (Pt.x < ScrollBarInfo->rcScrollBar.left + ArrowSize) + { + return SCROLL_TOP_ARROW; + } + if (ScrollBarInfo->rcScrollBar.right - ArrowSize <= Pt.x) + { + return SCROLL_BOTTOM_ARROW; + } + if (0 == ThumbPos) + { + return SCROLL_TOP_RECT; + } + Pt.x -= ScrollBarInfo->rcScrollBar.left; + if (Pt.x < ThumbPos) + { + return SCROLL_TOP_RECT; + } + if (ThumbPos + ThumbSize <= Pt.x) + { + return SCROLL_BOTTOM_RECT; + } + } - return SCROLL_THUMB; + return SCROLL_THUMB; +} + +/*********************************************************************** + * IntScrollGetThumbVal + * + * Compute the current scroll position based on the thumb position in pixels + * from the top of the scroll-bar. + */ +STATIC UINT FASTCALL +IntScrollGetThumbVal(HWND Wnd, INT SBType, PSCROLLBARINFO ScrollBarInfo, + BOOL Vertical, INT Pos) +{ + SCROLLINFO si; + INT Pixels = Vertical ? ScrollBarInfo->rcScrollBar.bottom + - ScrollBarInfo->rcScrollBar.top + : ScrollBarInfo->rcScrollBar.right + - ScrollBarInfo->rcScrollBar.left; + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_RANGE | SIF_PAGE; + NtUserGetScrollInfo(Wnd, SBType, &si); + if ((Pixels -= 2 * ScrollBarInfo->dxyLineButton) <= 0) + { + return si.nMin; + } + + if ((Pixels -= (ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop)) <= 0) + { + return si.nMin; + } + + Pos = RtlRosMax(0, Pos - ScrollBarInfo->dxyLineButton); + if (Pixels < Pos) + { + Pos = Pixels; + } + + if (0 == si.nPage) + { + Pos *= si.nMax - si.nMin; + } + else + { + Pos *= si.nMax - si.nMin - si.nPage + 1; + } + return si.nMin + ((Pos + Pixels / 2) / Pixels); +} + +/*********************************************************************** + * IntScrollClipPos + */ +STATIC POINT IntScrollClipPos(PRECT Rect, POINT Pt) +{ + if (Pt.x < Rect->left) + { + Pt.x = Rect->left; + } + else if (Rect->right < Pt.x) + { + Pt.x = Rect->right; + } + + if (Pt.y < Rect->top) + { + Pt.y = Rect->top; + } + else if (Rect->bottom < Pt.y) + { + Pt.y = Rect->bottom; + } + + return Pt; +} + +/*********************************************************************** + * IntScrollHandleScrollEvent + * + * Handle a mouse or timer event for the scrollbar. + * 'Pt' is the location of the mouse event in drawing coordinates + */ +STATIC VOID FASTCALL +IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt) +{ + static POINT PrevPt; /* Previous mouse position for timer events */ + static UINT TrackThumbPos; /* Thumb position when tracking started. */ + static INT LastClickPos; /* Position in the scroll-bar of the last + button-down event. */ + static INT LastMousePos; /* Position in the scroll-bar of the last + mouse event. */ + + DWORD HitTest; + HWND WndOwner, WndCtl; + BOOL Vertical; + HDC Dc; + SCROLLBARINFO ScrollBarInfo; + SETSCROLLBARINFO NewInfo; + + if (! IntGetScrollBarInfo(Wnd, SBType, &ScrollBarInfo)) + { + return; + } + if (SCROLL_NOWHERE == ScrollTrackHitTest && WM_LBUTTONDOWN != Msg) + { + return; + } + + NewInfo.nTrackPos = ScrollTrackingVal; + NewInfo.reserved = ScrollBarInfo.reserved; + memcpy(NewInfo.rgstate, ScrollBarInfo.rgstate, (CCHILDREN_SCROLLBAR + 1) * sizeof(DWORD)); + + if (SB_CTL == SBType + && 0 != (GetWindowLongW(Wnd, GWL_STYLE) & (SBS_SIZEGRIP | SBS_SIZEBOX))) + { + switch(Msg) + { + case WM_LBUTTONDOWN: /* Initialise mouse tracking */ + HideCaret(Wnd); /* hide caret while holding down LBUTTON */ + SetCapture(Wnd); + PrevPt = Pt; + ScrollTrackHitTest = HitTest = SCROLL_THUMB; + break; + case WM_MOUSEMOVE: + GetClientRect(GetParent(GetParent(Wnd)), &ScrollBarInfo.rcScrollBar); + PrevPt = Pt; + break; + case WM_LBUTTONUP: + ReleaseCapture(); + ScrollTrackHitTest = HitTest = SCROLL_NOWHERE; + if (Wnd == GetFocus()) + { + ShowCaret(Wnd); + } + break; + case WM_SYSTIMER: + Pt = PrevPt; + break; + } + return; + } + + Dc = GetDCEx(Wnd, 0, DCX_CACHE | ((SB_CTL == SBType) ? 0 : DCX_WINDOW)); + if (SB_VERT == SBType) + { + Vertical = TRUE; + } + else if (SB_HORZ == SBType) + { + Vertical = FALSE; + } + else + { + Vertical = (0 != (GetWindowLongW(Wnd, GWL_STYLE) & SBS_VERT)); + } + WndOwner = (SB_CTL == SBType) ? GetParent(Wnd) : Wnd; + WndCtl = (SB_CTL == SBType) ? Wnd : NULL; + + switch (Msg) + { + case WM_LBUTTONDOWN: /* Initialise mouse tracking */ + HideCaret(Wnd); /* hide caret while holding down LBUTTON */ + ScrollTrackVertical = Vertical; + ScrollTrackHitTest = HitTest = IntScrollHitTest(&ScrollBarInfo, Vertical, Pt, FALSE ); + LastClickPos = Vertical ? (Pt.y - ScrollBarInfo.rcScrollBar.top) + : (Pt.x - ScrollBarInfo.rcScrollBar.left); + LastMousePos = LastClickPos; + TrackThumbPos = ScrollBarInfo.xyThumbTop; + PrevPt = Pt; + if (SB_CTL == SBType && 0 != (GetWindowLongW(Wnd, GWL_STYLE) & WS_TABSTOP)) + { + SetFocus(Wnd); + } + SetCapture(Wnd); + ScrollBarInfo.rgstate[ScrollTrackHitTest] |= STATE_SYSTEM_PRESSED; + NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest]; + NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); + break; + + case WM_MOUSEMOVE: + HitTest = IntScrollHitTest(&ScrollBarInfo, Vertical, Pt, TRUE); + PrevPt = Pt; + break; + + case WM_LBUTTONUP: + HitTest = SCROLL_NOWHERE; + ReleaseCapture(); + /* if scrollbar has focus, show back caret */ + if (Wnd == GetFocus()) + { + ShowCaret(Wnd); + } + ScrollBarInfo.rgstate[ScrollTrackHitTest] &= ~STATE_SYSTEM_PRESSED; + NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest]; + NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); + break; + + case WM_SYSTIMER: + Pt = PrevPt; + HitTest = IntScrollHitTest(&ScrollBarInfo, Vertical, Pt, FALSE); + break; + + default: + return; /* Should never happen */ + } + + switch (ScrollTrackHitTest) + { + case SCROLL_NOWHERE: /* No tracking in progress */ + break; + + case SCROLL_TOP_ARROW: + if (HitTest == ScrollTrackHitTest) + { + if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) + { + SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, + SB_LINEUP, (LPARAM) WndCtl); + } + SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? + SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, + (TIMERPROC) NULL); + } + else + { + KillSystemTimer(Wnd, SCROLL_TIMER); + } + break; + + case SCROLL_TOP_RECT: + if (HitTest == ScrollTrackHitTest) + { + if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) + { + SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, + SB_PAGEUP, (LPARAM) WndCtl); + } + SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? + SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, + (TIMERPROC) NULL); + } + else + { + KillSystemTimer(Wnd, SCROLL_TIMER); + } + break; + + case SCROLL_THUMB: + if (WM_LBUTTONDOWN == Msg) + { + ScrollTrackingWin = Wnd; + ScrollTrackingBar = SBType; + ScrollTrackingPos = TrackThumbPos + LastMousePos - LastClickPos; + ScrollTrackingVal = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, + Vertical, ScrollTrackingPos); + NewInfo.nTrackPos = ScrollTrackingVal; + NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); + IntScrollDrawMovingThumb(Dc, &ScrollBarInfo, Vertical); + } + else if (WM_LBUTTONUP == Msg) + { + ScrollTrackingWin = 0; + ScrollTrackingVal = 0; + IntDrawScrollInterior(Wnd, Dc, SBType, Vertical, &ScrollBarInfo); + } + else /* WM_MOUSEMOVE */ + { + UINT Pos; + + if (! IntScrollPtInRectEx(&ScrollBarInfo.rcScrollBar, Pt, Vertical)) + { + Pos = LastClickPos; + } + else + { + Pt = IntScrollClipPos(&ScrollBarInfo.rcScrollBar, Pt); + Pos = Vertical ? (Pt.y - ScrollBarInfo.rcScrollBar.top) + : (Pt.x - ScrollBarInfo.rcScrollBar.left); + } + if (Pos != LastMousePos || ! ScrollMovingThumb) + { + LastMousePos = Pos; + ScrollTrackingPos = TrackThumbPos + Pos - LastClickPos; + ScrollTrackingVal = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, + Vertical, ScrollTrackingPos); + NewInfo.nTrackPos = ScrollTrackingVal; + NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); + IntScrollDrawMovingThumb(Dc, &ScrollBarInfo, Vertical); + SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, + MAKEWPARAM(SB_THUMBTRACK, ScrollTrackingVal), + (LPARAM) WndCtl); + } + } + break; + + case SCROLL_BOTTOM_RECT: + if (HitTest == ScrollTrackHitTest) + { + if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) + { + SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, + SB_PAGEDOWN, (LPARAM) WndCtl); + } + SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? + SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, + (TIMERPROC) NULL); + } + else + { + KillSystemTimer(Wnd, SCROLL_TIMER); + } + break; + + case SCROLL_BOTTOM_ARROW: + if (HitTest == ScrollTrackHitTest) + { + if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) + { + SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, + SB_LINEDOWN, (LPARAM) WndCtl); + } + SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? + SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, + (TIMERPROC) NULL); + } + else + { + KillSystemTimer(Wnd, SCROLL_TIMER); + } + break; + } + + if (WM_LBUTTONDOWN == Msg) + { + if (SCROLL_THUMB == HitTest) + { + UINT Val = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, + TrackThumbPos + LastMousePos - LastClickPos); + SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, + MAKEWPARAM(SB_THUMBTRACK, Val), (LPARAM) WndCtl); + } + } + + if (WM_LBUTTONUP == Msg) + { + HitTest = ScrollTrackHitTest; + ScrollTrackHitTest = SCROLL_NOWHERE; /* Terminate tracking */ + + if (SCROLL_THUMB == HitTest) + { + UINT Val = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, + TrackThumbPos + LastMousePos - LastClickPos); + SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, + MAKEWPARAM(SB_THUMBPOSITION, Val), (LPARAM) WndCtl); + } + SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, + SB_ENDSCROLL, (LPARAM) WndCtl); + } + + ReleaseDC(Wnd, Dc); +} + + +/* USER32 INTERNAL FUNCTIONS **************************************************/ + +/*********************************************************************** + * ScrollTrackScrollBar + * + * Track a mouse button press on a scroll-bar. + * pt is in screen-coordinates for non-client scroll bars. + */ +VOID FASTCALL +ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt) +{ + MSG Msg; + RECT WindowRect; + UINT XOffset, YOffset; + POINT TopLeft; + + if (SB_CTL != SBType) + { + NtUserGetWindowRect(Wnd, &WindowRect); + + Pt.x -= WindowRect.left; + Pt.y -= WindowRect.top; + + TopLeft.x = WindowRect.left; + TopLeft.y = WindowRect.top; + ScreenToClient(Wnd, &TopLeft); + XOffset = - TopLeft.x; + YOffset = - TopLeft.y; + } + else + { + XOffset = 0; + YOffset = 0; + } + + IntScrollHandleScrollEvent(Wnd, SBType, WM_LBUTTONDOWN, Pt); + + do + { + if (! GetMessageW(&Msg, 0, 0, 0)) + { + break; + } + if (CallMsgFilterW(&Msg, MSGF_SCROLLBAR)) + { + continue; + } + + switch(Msg.message) + { + case WM_SYSTIMER: + case WM_LBUTTONUP: + case WM_MOUSEMOVE: + Pt.x = LOWORD(Msg.lParam) + XOffset; + Pt.y = HIWORD(Msg.lParam) + YOffset; + IntScrollHandleScrollEvent(Wnd, SBType, Msg.message, Pt); + break; + default: + TranslateMessage(&Msg); + DispatchMessageW(&Msg); + break; + } + + if (! IsWindow(Wnd)) + { + ReleaseCapture(); + break; + } + } + while (WM_LBUTTONUP != Msg.message); } /* PUBLIC FUNCTIONS ***********************************************************/ @@ -352,7 +879,7 @@ IntScrollHitTest(HWND hWnd, INT nBar, POINT pt, BOOL bDragging) WINBOOL STDCALL EnableScrollBar(HWND hWnd, UINT wSBflags, UINT wArrows) { - return NtUserEnableScrollBar(hWnd, wSBflags, wArrows); + return NtUserEnableScrollBar(hWnd, wSBflags, wArrows); } /* @@ -361,16 +888,16 @@ EnableScrollBar(HWND hWnd, UINT wSBflags, UINT wArrows) BOOL STDCALL GetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi) { - return NtUserGetScrollBarInfo(hWnd, idObject, psbi); + return NtUserGetScrollBarInfo(hWnd, idObject, psbi); } /* * @implemented */ BOOL STDCALL -GetScrollInfo(HWND hWnd, INT nBar, LPSCROLLINFO lpsi) +GetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO lpsi) { - return NtUserGetScrollInfo(hWnd, nBar, lpsi); + return NtUserGetScrollInfo(Wnd, SBType, lpsi); } /* @@ -379,13 +906,16 @@ GetScrollInfo(HWND hWnd, INT nBar, LPSCROLLINFO lpsi) INT STDCALL GetScrollPos(HWND hWnd, INT nBar) { - SCROLLINFO ScrollInfo; + SCROLLINFO ScrollInfo; - ScrollInfo.cbSize = sizeof(SCROLLINFO); - ScrollInfo.fMask = SIF_POS; - if (NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo)) - return ScrollInfo.nPos; - return 0; + ScrollInfo.cbSize = sizeof(SCROLLINFO); + ScrollInfo.fMask = SIF_POS; + if (! NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo)) + { + return 0; + } + + return ScrollInfo.nPos; } /* @@ -394,25 +924,25 @@ GetScrollPos(HWND hWnd, INT nBar) BOOL STDCALL GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos) { - BOOL Result; - SCROLLINFO ScrollInfo; + BOOL Result; + SCROLLINFO ScrollInfo; - if (!lpMinPos || !lpMaxPos) - { + if (NULL == lpMinPos || NULL == lpMaxPos) + { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; - } + } - ScrollInfo.cbSize = sizeof(SCROLLINFO); - ScrollInfo.fMask = SIF_RANGE; - Result = NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo); - if (Result) - { + ScrollInfo.cbSize = sizeof(SCROLLINFO); + ScrollInfo.fMask = SIF_RANGE; + Result = NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo); + if (Result) + { *lpMinPos = ScrollInfo.nMin; *lpMaxPos = ScrollInfo.nMax; - } + } - return Result; + return Result; } /* @@ -421,7 +951,7 @@ GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos) INT STDCALL SetScrollInfo(HWND hWnd, int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) { - return NtUserSetScrollInfo(hWnd, nBar, lpsi, bRedraw); + return NtUserSetScrollInfo(hWnd, nBar, lpsi, bRedraw); } /* @@ -430,28 +960,28 @@ SetScrollInfo(HWND hWnd, int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) INT STDCALL SetScrollPos(HWND hWnd, INT nBar, INT nPos, BOOL bRedraw) { - INT Result = 0; - SCROLLINFO ScrollInfo; + INT Result = 0; + SCROLLINFO ScrollInfo; - ScrollInfo.cbSize = sizeof(SCROLLINFO); - ScrollInfo.fMask = SIF_POS; + ScrollInfo.cbSize = sizeof(SCROLLINFO); + ScrollInfo.fMask = SIF_POS; - /* - * Call NtUserGetScrollInfo() to get the previous position that - * we will later return. - */ - if (NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo)) - { + /* + * Call NtUserGetScrollInfo() to get the previous position that + * we will later return. + */ + if (NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo)) + { Result = ScrollInfo.nPos; if (Result != nPos) - { - ScrollInfo.nPos = nPos; - /* Finally set the new position */ - NtUserSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); - } - } + { + ScrollInfo.nPos = nPos; + /* Finally set the new position */ + NtUserSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); + } + } - return Result; + return Result; } /* @@ -460,14 +990,15 @@ SetScrollPos(HWND hWnd, INT nBar, INT nPos, BOOL bRedraw) BOOL STDCALL SetScrollRange(HWND hWnd, INT nBar, INT nMinPos, INT nMaxPos, BOOL bRedraw) { - SCROLLINFO ScrollInfo; + SCROLLINFO ScrollInfo; - ScrollInfo.cbSize = sizeof(SCROLLINFO); - ScrollInfo.fMask = SIF_RANGE; - ScrollInfo.nMin = nMinPos; - ScrollInfo.nMax = nMaxPos; - NtUserSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); - return TRUE; + ScrollInfo.cbSize = sizeof(SCROLLINFO); + ScrollInfo.fMask = SIF_RANGE; + ScrollInfo.nMin = nMinPos; + ScrollInfo.nMax = nMaxPos; + NtUserSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); + + return TRUE; } /* @@ -476,5 +1007,5 @@ SetScrollRange(HWND hWnd, INT nBar, INT nMinPos, INT nMaxPos, BOOL bRedraw) BOOL STDCALL ShowScrollBar(HWND hWnd, INT wBar, BOOL bShow) { - return NtUserShowScrollBar(hWnd, wBar, bShow); + return NtUserShowScrollBar(hWnd, wBar, bShow); } diff --git a/reactos/lib/user32/include/scroll.h b/reactos/lib/user32/include/scroll.h new file mode 100644 index 00000000000..6324d0c7757 --- /dev/null +++ b/reactos/lib/user32/include/scroll.h @@ -0,0 +1,14 @@ +/* $Id: scroll.h,v 1.1 2004/01/14 21:28:24 gvg Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: include/user32.h + * PURPOSE: Global user32 definitions + */ + +#ifndef USER32_SCROLL_H_INCLUDED +#define USER32_SCROLL_H_INCLUDED + +extern VOID FASTCALL ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt); + +#endif diff --git a/reactos/lib/user32/windows/defwnd.c b/reactos/lib/user32/windows/defwnd.c index a625a2dbe51..cac40b7b354 100644 --- a/reactos/lib/user32/windows/defwnd.c +++ b/reactos/lib/user32/windows/defwnd.c @@ -1,4 +1,4 @@ -/* $Id: defwnd.c,v 1.121 2004/01/12 20:38:59 gvg Exp $ +/* $Id: defwnd.c,v 1.122 2004/01/14 21:28:24 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -16,8 +16,9 @@ #include #include #include -#include #include +#include +#include #include #define NDEBUG @@ -29,7 +30,6 @@ LRESULT DefWndNCActivate(HWND hWnd, WPARAM wParam); LRESULT DefWndNCHitTest(HWND hWnd, POINT Point); LRESULT DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam); LRESULT DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam); -VOID DefWndTrackScrollBar(HWND hWnd, WPARAM wParam, POINT Point); /* GLOBALS *******************************************************************/ @@ -748,6 +748,36 @@ DefWndDoSizeMove(HWND hwnd, WORD wParam) } +/*********************************************************************** + * DefWndTrackScrollBar + * + * Track a mouse button press on the horizontal or vertical scroll-bar. + */ +STATIC VOID +DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt) +{ + INT ScrollBar; + + if (SC_HSCROLL == (wParam & 0xfff0)) + { + if (HTHSCROLL != (wParam & 0x0f)) + { + return; + } + ScrollBar = SB_HORZ; + } + else /* SC_VSCROLL */ + { + if (HTVSCROLL != (wParam & 0x0f)) + { + return; + } + ScrollBar = SB_VERT; + } + ScrollTrackScrollBar(Wnd, ScrollBar, Pt ); +} + + LRESULT DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt) { @@ -792,6 +822,10 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt) case SC_KEYMENU: MenuTrackKbdMenuBar(hWnd, wParam, Pt.x); break; + case SC_VSCROLL: + case SC_HSCROLL: + DefWndTrackScrollBar(hWnd, wParam, Pt); + break; default: /* FIXME: Implement */ @@ -867,6 +901,7 @@ DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos) HBRUSH DefWndControlColor(HDC hDC, UINT ctlType) { +#if 0 /* FIXME: Re-enable when pattern brushes are implemented */ if (CTLCOLOR_SCROLLBAR == ctlType) { HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR); @@ -897,6 +932,7 @@ DefWndControlColor(HDC hDC, UINT ctlType) UnrealizeObject(hb); return hb; } +#endif SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); diff --git a/reactos/lib/user32/windows/nonclient.c b/reactos/lib/user32/windows/nonclient.c index cd541facaff..77afc656437 100644 --- a/reactos/lib/user32/windows/nonclient.c +++ b/reactos/lib/user32/windows/nonclient.c @@ -715,7 +715,7 @@ DefWndNCHitTest(HWND hWnd, POINT Point) TempRect2.left += GetSystemMetrics(SM_CXVSCROLL); else TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL); - if (PtInRect(&TempRect, Point)) + if (PtInRect(&TempRect2, Point)) return HTHSCROLL; TempRect.top = TempRect2.top; @@ -755,19 +755,6 @@ DefWndNCHitTest(HWND hWnd, POINT Point) return HTNOWHERE; } -VOID -DefWndDoScrollBarDown(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - POINT Point; - DWORD hit; - Point.x = GET_X_LPARAM(lParam); - Point.y = GET_Y_LPARAM(lParam); - - hit = IntScrollHitTest(hWnd, (wParam == HTHSCROLL) ? SB_HORZ : SB_VERT, Point, FALSE); - - SendMessageW(hWnd, WM_SYSCOMMAND, Msg + (UINT)wParam, lParam); -} - VOID DefWndDoButton(HWND hWnd, WPARAM wParam) { @@ -879,14 +866,12 @@ DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam) } case HTHSCROLL: { - DefWndDoScrollBarDown(hWnd, SC_HSCROLL, HTHSCROLL, lParam); - //SendMessageW(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam); + SendMessageW(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam); break; } case HTVSCROLL: { - DefWndDoScrollBarDown(hWnd, SC_VSCROLL, HTVSCROLL, lParam); - //SendMessageW(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam); + SendMessageW(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam); break; } case HTMINBUTTON: