Scrollbar implementation

svn path=/trunk/; revision=7625
This commit is contained in:
Gé van Geldorp 2004-01-14 21:28:25 +00:00
parent eb5f406f20
commit fa6209cc0f
4 changed files with 736 additions and 170 deletions

View file

@ -1,4 +1,5 @@
/* /* $Id $
*
* ReactOS User32 Library * ReactOS User32 Library
* - ScrollBar control * - ScrollBar control
* *
@ -6,7 +7,7 @@
* Copyright 2003 Thomas Weidenmueller * Copyright 2003 Thomas Weidenmueller
* Copyright 2003 Filip Navara * Copyright 2003 Filip Navara
* *
* Portions based on Wine code. * Based on Wine code.
* *
* Copyright 1993 Martin Ayotte * Copyright 1993 Martin Ayotte
* Copyright 1994, 1996 Alexandre Julliard * Copyright 1994, 1996 Alexandre Julliard
@ -35,6 +36,7 @@
#include <draw.h> #include <draw.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <rosrtl/minmax.h>
/* GLOBAL VARIABLES ***********************************************************/ /* GLOBAL VARIABLES ***********************************************************/
@ -46,15 +48,33 @@
#define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */ #define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */
#define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right 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); HBRUSH DefWndControlColor(HDC hDC, UINT ctlType);
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
static void static void
IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical,
INT ArrowSize, PSCROLLBARINFO ScrollBarInfo) PSCROLLBARINFO ScrollBarInfo)
{ {
INT ThumbSize = ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; INT ThumbSize = ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop;
INT ThumbTop = ScrollBarInfo->xyThumbTop;
RECT Rect; RECT Rect;
HPEN hSavePen; HPEN hSavePen;
HBRUSH hSaveBrush, hBrush; HBRUSH hSaveBrush, hBrush;
@ -87,8 +107,8 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical,
/* Calculate the scroll rectangle */ /* Calculate the scroll rectangle */
if (Vertical) if (Vertical)
{ {
Rect.top = ScrollBarInfo->rcScrollBar.top + ArrowSize; Rect.top = ScrollBarInfo->rcScrollBar.top + ScrollBarInfo->dxyLineButton;
Rect.bottom = ScrollBarInfo->rcScrollBar.bottom - ArrowSize; Rect.bottom = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->dxyLineButton;
Rect.left = ScrollBarInfo->rcScrollBar.left; Rect.left = ScrollBarInfo->rcScrollBar.left;
Rect.right = ScrollBarInfo->rcScrollBar.right; Rect.right = ScrollBarInfo->rcScrollBar.right;
} }
@ -96,8 +116,8 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical,
{ {
Rect.top = ScrollBarInfo->rcScrollBar.top; Rect.top = ScrollBarInfo->rcScrollBar.top;
Rect.bottom = ScrollBarInfo->rcScrollBar.bottom; Rect.bottom = ScrollBarInfo->rcScrollBar.bottom;
Rect.left = ScrollBarInfo->rcScrollBar.left + ArrowSize; Rect.left = ScrollBarInfo->rcScrollBar.left + ScrollBarInfo->dxyLineButton;
Rect.right = ScrollBarInfo->rcScrollBar.right - ArrowSize; Rect.right = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->dxyLineButton;
} }
/* Draw the scroll rectangles and thumb */ /* Draw the scroll rectangles and thumb */
@ -112,7 +132,7 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical,
return; return;
} }
ScrollBarInfo->xyThumbTop -= ArrowSize; ThumbTop -= ScrollBarInfo->dxyLineButton;
if (ScrollBarInfo->dxyLineButton) if (ScrollBarInfo->dxyLineButton)
{ {
@ -121,18 +141,18 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical,
if (ThumbSize) if (ThumbSize)
{ {
PatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left, PatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left,
ScrollBarInfo->xyThumbTop, TopSelected ? BLACKNESS : PATCOPY); ThumbTop, TopSelected ? BLACKNESS : PATCOPY);
Rect.top += ScrollBarInfo->xyThumbTop; Rect.top += ThumbTop;
PatBlt(hDC, Rect.left, Rect.top + ThumbSize, Rect.right - Rect.left, PatBlt(hDC, Rect.left, Rect.top + ThumbSize, Rect.right - Rect.left,
Rect.bottom - Rect.top - ThumbSize, BottomSelected ? BLACKNESS : PATCOPY); Rect.bottom - Rect.top - ThumbSize, BottomSelected ? BLACKNESS : PATCOPY);
Rect.bottom = Rect.top + ThumbSize; Rect.bottom = Rect.top + ThumbSize;
} }
else else
{ {
if (ScrollBarInfo->xyThumbTop) if (ThumbTop)
{ {
PatBlt(hDC, Rect.left, ScrollBarInfo->dxyLineButton, 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) 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.bottom - Rect.top, TopSelected ? BLACKNESS : PATCOPY);
Rect.left += ScrollBarInfo->xyThumbTop; Rect.left += ThumbTop;
PatBlt(hDC, Rect.left + ThumbSize, Rect.top, PatBlt(hDC, Rect.left + ThumbSize, Rect.top,
Rect.right - Rect.left - ThumbSize, Rect.bottom - Rect.top, Rect.right - Rect.left - ThumbSize, Rect.bottom - Rect.top,
BottomSelected ? BLACKNESS : PATCOPY); BottomSelected ? BLACKNESS : PATCOPY);
@ -150,7 +170,7 @@ IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical,
} }
else else
{ {
if (ScrollBarInfo->xyThumbTop) if (ThumbTop)
{ {
PatBlt(hDC, ScrollBarInfo->dxyLineButton, Rect.top, PatBlt(hDC, ScrollBarInfo->dxyLineButton, Rect.top,
Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY); 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); SelectObject(hDC, hSaveBrush);
} }
static void STATIC VOID FASTCALL
IntDrawScrollArrows(HDC hDC, PSCROLLBARINFO ScrollBarInfo, LPRECT Rect, IntDrawScrollArrows(HDC hDC, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical)
INT ArrowSize, BOOL Vertical)
{ {
RECT RectLT, RectRB; RECT RectLT, RectRB;
INT ScrollDirFlagLT, ScrollDirFlagRB; INT ScrollDirFlagLT, ScrollDirFlagRB;
RectLT = RectRB = *Rect; RectLT = RectRB = ScrollBarInfo->rcScrollBar;
if (Vertical) if (Vertical)
{ {
ScrollDirFlagLT = DFCS_SCROLLUP; ScrollDirFlagLT = DFCS_SCROLLUP;
ScrollDirFlagRB = DFCS_SCROLLDOWN; ScrollDirFlagRB = DFCS_SCROLLDOWN;
RectLT.bottom = RectLT.top + ArrowSize; RectLT.bottom = RectLT.top + ScrollBarInfo->dxyLineButton;
RectRB.top = RectRB.bottom - ArrowSize; RectRB.top = RectRB.bottom - ScrollBarInfo->dxyLineButton;
} }
else else
{ {
ScrollDirFlagLT = DFCS_SCROLLLEFT; ScrollDirFlagLT = DFCS_SCROLLLEFT;
ScrollDirFlagRB = DFCS_SCROLLRIGHT; ScrollDirFlagRB = DFCS_SCROLLRIGHT;
RectLT.right = RectLT.left + ArrowSize; RectLT.right = RectLT.left + ScrollBarInfo->dxyLineButton;
RectRB.left = RectRB.right - ArrowSize; RectRB.left = RectRB.right - ScrollBarInfo->dxyLineButton;
} }
if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_PRESSED) 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) if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE)
{
ScrollDirFlagLT |= DFCS_INACTIVE; ScrollDirFlagLT |= DFCS_INACTIVE;
}
if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_PRESSED) 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) if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE)
{
ScrollDirFlagRB |= DFCS_INACTIVE; ScrollDirFlagRB |= DFCS_INACTIVE;
}
DrawFrameControl(hDC, &RectLT, DFC_SCROLL, ScrollDirFlagLT); DrawFrameControl(hDC, &RectLT, DFC_SCROLL, ScrollDirFlagLT);
DrawFrameControl(hDC, &RectRB, DFC_SCROLL, ScrollDirFlagRB); 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 void
IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar) IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar)
{ {
INT ArrowSize = 0;
INT ThumbSize; INT ThumbSize;
SCROLLBARINFO Info; SCROLLBARINFO Info;
BOOL Vertical; BOOL Vertical;
@ -240,21 +304,20 @@ IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar)
return; return;
} }
ArrowSize = Info.dxyLineButton;
ThumbSize = Info.xyThumbBottom - Info.xyThumbTop; ThumbSize = Info.xyThumbBottom - Info.xyThumbTop;
/* /*
* Draw the arrows. * Draw the arrows.
*/ */
if (ArrowSize) if (Info.dxyLineButton)
IntDrawScrollArrows(hDC, &Info, &Info.rcScrollBar, ArrowSize, Vertical); IntDrawScrollArrows(hDC, &Info, Vertical);
/* /*
* Draw the interior. * Draw the interior.
*/ */
IntDrawScrollInterior(hWnd, hDC, nBar, Vertical, ArrowSize, &Info); IntDrawScrollInterior(hWnd, hDC, nBar, Vertical, &Info);
/* /*
* If scroll bar has focus, reposition the caret. * If scroll bar has focus, reposition the caret.
@ -269,81 +332,545 @@ IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar)
} }
} }
static BOOL STATIC BOOL FASTCALL
IntScrollPtInRectEx(LPRECT lpRect, POINT pt, BOOL Vertical) IntScrollPtInRectEx(LPRECT Rect, POINT Pt, BOOL Vertical)
{ {
RECT Rect = *lpRect; RECT TempRect = *Rect;
if (Vertical) if (Vertical)
{ {
Rect.left -= lpRect->right - lpRect->left; TempRect.left -= Rect->right - Rect->left;
Rect.right += lpRect->right - lpRect->left; TempRect.right += Rect->right - Rect->left;
} }
else else
{ {
Rect.top -= lpRect->bottom - lpRect->top; TempRect.top -= Rect->bottom - Rect->top;
Rect.bottom += lpRect->bottom - lpRect->top; TempRect.bottom += Rect->bottom - Rect->top;
}
return PtInRect(&Rect, pt);
} }
DWORD return PtInRect(&TempRect, Pt);
IntScrollHitTest(HWND hWnd, INT nBar, POINT pt, BOOL bDragging) }
STATIC LONG FASTCALL
IntScrollGetObjectId(INT SBType)
{
if (SB_VERT == SBType)
{
return OBJID_VSCROLL;
}
if (SB_HORZ == SBType)
{
return OBJID_HSCROLL;
}
return OBJID_CLIENT;
}
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)
{ {
SCROLLBARINFO ScrollButtonInfo;
RECT WindowRect;
INT ArrowSize, ThumbSize, ThumbPos; INT ArrowSize, ThumbSize, ThumbPos;
BOOL Vertical = (nBar == SB_VERT); /* FIXME - ((Window->Style & SBS_VERT) != 0) */
NtUserGetWindowRect(hWnd, &WindowRect); if ((Dragging && ! IntScrollPtInRectEx(&ScrollBarInfo->rcScrollBar, Pt, Vertical)) ||
! PtInRect(&ScrollBarInfo->rcScrollBar, Pt))
ScrollButtonInfo.cbSize = sizeof(SCROLLBARINFO);
NtUserGetScrollBarInfo(hWnd, Vertical ? OBJID_VSCROLL : OBJID_HSCROLL,
&ScrollButtonInfo);
OffsetRect(&ScrollButtonInfo.rcScrollBar, WindowRect.left, WindowRect.top);
if ((bDragging && !IntScrollPtInRectEx(&ScrollButtonInfo.rcScrollBar, pt, Vertical)) ||
!PtInRect(&ScrollButtonInfo.rcScrollBar, pt))
{ {
return SCROLL_NOWHERE; return SCROLL_NOWHERE;
} }
ThumbPos = ScrollButtonInfo.xyThumbTop; ThumbPos = ScrollBarInfo->xyThumbTop;
ThumbSize = ScrollButtonInfo.xyThumbBottom - ThumbPos; ThumbSize = ScrollBarInfo->xyThumbBottom - ThumbPos;
ArrowSize = ScrollButtonInfo.dxyLineButton; ArrowSize = ScrollBarInfo->dxyLineButton;
if (Vertical) if (Vertical)
{ {
if (pt.y < ScrollButtonInfo.rcScrollBar.top + ArrowSize) if (Pt.y < ScrollBarInfo->rcScrollBar.top + ArrowSize)
{
return SCROLL_TOP_ARROW; return SCROLL_TOP_ARROW;
if (pt.y >= ScrollButtonInfo.rcScrollBar.bottom - ArrowSize) }
if (ScrollBarInfo->rcScrollBar.bottom - ArrowSize <= Pt.y)
{
return SCROLL_BOTTOM_ARROW; return SCROLL_BOTTOM_ARROW;
if (!ThumbPos) }
if (0 == ThumbPos)
{
return SCROLL_TOP_RECT; return SCROLL_TOP_RECT;
pt.y -= ScrollButtonInfo.rcScrollBar.top; }
if (pt.y < ThumbPos) Pt.y -= ScrollBarInfo->rcScrollBar.top;
if (Pt.y < ThumbPos)
{
return SCROLL_TOP_RECT; return SCROLL_TOP_RECT;
if (pt.y >= ThumbPos + ThumbSize) }
if (ThumbPos + ThumbSize <= Pt.y)
{
return SCROLL_BOTTOM_RECT; return SCROLL_BOTTOM_RECT;
} }
}
else else
{ {
if (pt.x < ScrollButtonInfo.rcScrollBar.left + ArrowSize) if (Pt.x < ScrollBarInfo->rcScrollBar.left + ArrowSize)
{
return SCROLL_TOP_ARROW; return SCROLL_TOP_ARROW;
if (pt.x >= ScrollButtonInfo.rcScrollBar.right - ArrowSize) }
if (ScrollBarInfo->rcScrollBar.right - ArrowSize <= Pt.x)
{
return SCROLL_BOTTOM_ARROW; return SCROLL_BOTTOM_ARROW;
if (!ThumbPos) }
if (0 == ThumbPos)
{
return SCROLL_TOP_RECT; return SCROLL_TOP_RECT;
pt.x -= ScrollButtonInfo.rcScrollBar.left; }
if (pt.x < ThumbPos) Pt.x -= ScrollBarInfo->rcScrollBar.left;
if (Pt.x < ThumbPos)
{
return SCROLL_TOP_RECT; return SCROLL_TOP_RECT;
if (pt.x >= ThumbPos + ThumbSize) }
if (ThumbPos + ThumbSize <= Pt.x)
{
return SCROLL_BOTTOM_RECT; 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 ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
/* /*
@ -368,9 +895,9 @@ GetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
* @implemented * @implemented
*/ */
BOOL STDCALL 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);
} }
/* /*
@ -383,11 +910,14 @@ GetScrollPos(HWND hWnd, INT nBar)
ScrollInfo.cbSize = sizeof(SCROLLINFO); ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_POS; ScrollInfo.fMask = SIF_POS;
if (NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo)) if (! NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo))
return ScrollInfo.nPos; {
return 0; return 0;
} }
return ScrollInfo.nPos;
}
/* /*
* @implemented * @implemented
*/ */
@ -397,7 +927,7 @@ GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos)
BOOL Result; BOOL Result;
SCROLLINFO ScrollInfo; SCROLLINFO ScrollInfo;
if (!lpMinPos || !lpMaxPos) if (NULL == lpMinPos || NULL == lpMaxPos)
{ {
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
@ -467,6 +997,7 @@ SetScrollRange(HWND hWnd, INT nBar, INT nMinPos, INT nMaxPos, BOOL bRedraw)
ScrollInfo.nMin = nMinPos; ScrollInfo.nMin = nMinPos;
ScrollInfo.nMax = nMaxPos; ScrollInfo.nMax = nMaxPos;
NtUserSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); NtUserSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw);
return TRUE; return TRUE;
} }

View file

@ -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

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS user32.dll * PROJECT: ReactOS user32.dll
@ -16,8 +16,9 @@
#include <window.h> #include <window.h>
#include <user32/wininternal.h> #include <user32/wininternal.h>
#include <string.h> #include <string.h>
#include <menu.h>
#include <cursor.h> #include <cursor.h>
#include <menu.h>
#include <scroll.h>
#include <winpos.h> #include <winpos.h>
#define NDEBUG #define NDEBUG
@ -29,7 +30,6 @@ LRESULT DefWndNCActivate(HWND hWnd, WPARAM wParam);
LRESULT DefWndNCHitTest(HWND hWnd, POINT Point); LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
LRESULT DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam); LRESULT DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);
LRESULT DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam); LRESULT DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam);
VOID DefWndTrackScrollBar(HWND hWnd, WPARAM wParam, POINT Point);
/* GLOBALS *******************************************************************/ /* 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 LRESULT
DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt) DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
{ {
@ -792,6 +822,10 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
case SC_KEYMENU: case SC_KEYMENU:
MenuTrackKbdMenuBar(hWnd, wParam, Pt.x); MenuTrackKbdMenuBar(hWnd, wParam, Pt.x);
break; break;
case SC_VSCROLL:
case SC_HSCROLL:
DefWndTrackScrollBar(hWnd, wParam, Pt);
break;
default: default:
/* FIXME: Implement */ /* FIXME: Implement */
@ -867,6 +901,7 @@ DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
HBRUSH HBRUSH
DefWndControlColor(HDC hDC, UINT ctlType) DefWndControlColor(HDC hDC, UINT ctlType)
{ {
#if 0 /* FIXME: Re-enable when pattern brushes are implemented */
if (CTLCOLOR_SCROLLBAR == ctlType) if (CTLCOLOR_SCROLLBAR == ctlType)
{ {
HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR); HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
@ -897,6 +932,7 @@ DefWndControlColor(HDC hDC, UINT ctlType)
UnrealizeObject(hb); UnrealizeObject(hb);
return hb; return hb;
} }
#endif
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));

View file

@ -715,7 +715,7 @@ DefWndNCHitTest(HWND hWnd, POINT Point)
TempRect2.left += GetSystemMetrics(SM_CXVSCROLL); TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
else else
TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL); TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
if (PtInRect(&TempRect, Point)) if (PtInRect(&TempRect2, Point))
return HTHSCROLL; return HTHSCROLL;
TempRect.top = TempRect2.top; TempRect.top = TempRect2.top;
@ -755,19 +755,6 @@ DefWndNCHitTest(HWND hWnd, POINT Point)
return HTNOWHERE; 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 VOID
DefWndDoButton(HWND hWnd, WPARAM wParam) DefWndDoButton(HWND hWnd, WPARAM wParam)
{ {
@ -879,14 +866,12 @@ DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
} }
case HTHSCROLL: 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; break;
} }
case HTVSCROLL: 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; break;
} }
case HTMINBUTTON: case HTMINBUTTON: