[PATCH 6/7] win32u: Move scroll tracking implementation from user32.
Jacek Caban
wine at gitlab.winehq.org
Mon Jul 4 07:05:57 CDT 2022
From: Jacek Caban <jacek at codeweavers.com>
---
dlls/user32/controls.h | 3 -
dlls/user32/defwnd.c | 24 +-
dlls/user32/edit.c | 4 +-
dlls/user32/listbox.c | 14 +-
dlls/user32/mdi.c | 4 +-
dlls/user32/nonclient.c | 69 --
dlls/user32/scroll.c | 1304 +---------------------------------
dlls/user32/user32.spec | 6 +-
dlls/user32/user_main.c | 12 +-
dlls/user32/win.c | 14 -
dlls/user32/win.h | 1 -
dlls/win32u/defwnd.c | 77 +-
dlls/win32u/gdiobj.c | 3 +
dlls/win32u/ntuser_private.h | 1 -
dlls/win32u/scroll.c | 1032 ++++++++++++++++++++++++++-
dlls/win32u/win32u.spec | 6 +-
dlls/win32u/win32u_private.h | 8 +
dlls/win32u/window.c | 11 +-
dlls/win32u/wrappers.c | 18 +
include/ntuser.h | 36 +-
20 files changed, 1219 insertions(+), 1428 deletions(-)
diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h
index 48127ca6bb2..955c9092a54 100644
--- a/dlls/user32/controls.h
+++ b/dlls/user32/controls.h
@@ -113,13 +113,10 @@ extern HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType ) DECLSPEC_HIDDEN;
extern BOOL update_wallpaper( const WCHAR *wallpaper, const WCHAR *pattern ) DECLSPEC_HIDDEN;
/* nonclient area */
-extern LRESULT NC_HandleNCMouseMove( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN;
-extern LRESULT NC_HandleNCMouseLeave( HWND hwnd ) DECLSPEC_HIDDEN;
extern LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN;
/* scrollbar */
-extern void SCROLL_DrawNCScrollBar( HWND hwnd, HDC hdc, BOOL draw_horizontal, BOOL draw_vertical ) DECLSPEC_HIDDEN;
extern void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, INT nBar, enum SCROLL_HITTEST hit_test,
const struct SCROLL_TRACKING_INFO *tracking_info, BOOL arrows,
BOOL interior ) DECLSPEC_HIDDEN;
diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c
index d29846ad623..8373aa8e797 100644
--- a/dlls/user32/defwnd.c
+++ b/dlls/user32/defwnd.c
@@ -103,20 +103,12 @@ LRESULT WINAPI DefWindowProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam
if(cs->style & (WS_HSCROLL | WS_VSCROLL))
{
SCROLLINFO si = {sizeof si, SIF_ALL, 0, 100, 0, 0, 0};
- SetScrollInfo( hwnd, SB_HORZ, &si, FALSE );
- SetScrollInfo( hwnd, SB_VERT, &si, FALSE );
+ NtUserSetScrollInfo( hwnd, SB_HORZ, &si, FALSE );
+ NtUserSetScrollInfo( hwnd, SB_VERT, &si, FALSE );
}
}
break;
- case WM_NCMOUSEMOVE:
- result = NC_HandleNCMouseMove( hwnd, wParam, lParam );
- break;
-
- case WM_NCMOUSELEAVE:
- result = NC_HandleNCMouseLeave( hwnd );
- break;
-
case WM_SYSCOMMAND:
result = NC_HandleSysCommand( hwnd, wParam, lParam );
break;
@@ -238,20 +230,12 @@ LRESULT WINAPI DefWindowProcW(
if(cs->style & (WS_HSCROLL | WS_VSCROLL))
{
SCROLLINFO si = {sizeof si, SIF_ALL, 0, 100, 0, 0, 0};
- SetScrollInfo( hwnd, SB_HORZ, &si, FALSE );
- SetScrollInfo( hwnd, SB_VERT, &si, FALSE );
+ NtUserSetScrollInfo( hwnd, SB_HORZ, &si, FALSE );
+ NtUserSetScrollInfo( hwnd, SB_VERT, &si, FALSE );
}
}
break;
- case WM_NCMOUSEMOVE:
- result = NC_HandleNCMouseMove( hwnd, wParam, lParam );
- break;
-
- case WM_NCMOUSELEAVE:
- result = NC_HandleNCMouseLeave( hwnd );
- break;
-
case WM_SYSCOMMAND:
result = NC_HandleSysCommand( hwnd, wParam, lParam );
break;
diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c
index 439e33c0b14..80758dd60ef 100644
--- a/dlls/user32/edit.c
+++ b/dlls/user32/edit.c
@@ -1639,7 +1639,7 @@ static void EDIT_UpdateScrollInfo(EDITSTATE *es)
si.nPos = es->y_offset;
TRACE("SB_VERT, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
si.nMin, si.nMax, si.nPage, si.nPos);
- SetScrollInfo(es->hwndSelf, SB_VERT, &si, TRUE);
+ NtUserSetScrollInfo(es->hwndSelf, SB_VERT, &si, TRUE);
}
if ((es->style & WS_HSCROLL) && !(es->flags & EF_HSCROLL_TRACK))
@@ -1653,7 +1653,7 @@ static void EDIT_UpdateScrollInfo(EDITSTATE *es)
si.nPos = es->x_offset;
TRACE("SB_HORZ, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
si.nMin, si.nMax, si.nPage, si.nPos);
- SetScrollInfo(es->hwndSelf, SB_HORZ, &si, TRUE);
+ NtUserSetScrollInfo(es->hwndSelf, SB_HORZ, &si, TRUE);
}
}
diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c
index b8b683e6e3c..d96fc8c219d 100644
--- a/dlls/user32/listbox.c
+++ b/dlls/user32/listbox.c
@@ -329,7 +329,7 @@ static void LISTBOX_UpdateScroll( LB_DESCR *descr )
SCROLLINFO info;
/* Check the listbox scroll bar flags individually before we call
- SetScrollInfo otherwise when the listbox style is WS_HSCROLL and
+ NtUserSetScrollInfo otherwise when the listbox style is WS_HSCROLL and
no WS_VSCROLL, we end up with an uninitialized, visible horizontal
scroll bar when we do not need one.
if (!(descr->style & WS_VSCROLL)) return;
@@ -357,11 +357,11 @@ static void LISTBOX_UpdateScroll( LB_DESCR *descr )
if (descr->style & LBS_DISABLENOSCROLL)
info.fMask |= SIF_DISABLENOSCROLL;
if (descr->style & WS_HSCROLL)
- SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+ NtUserSetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
info.nMax = 0;
info.fMask = SIF_RANGE;
if (descr->style & WS_VSCROLL)
- SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
+ NtUserSetScrollInfo( descr->self, SB_VERT, &info, TRUE );
}
else
{
@@ -373,7 +373,7 @@ static void LISTBOX_UpdateScroll( LB_DESCR *descr )
if (descr->style & LBS_DISABLENOSCROLL)
info.fMask |= SIF_DISABLENOSCROLL;
if (descr->style & WS_VSCROLL)
- SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
+ NtUserSetScrollInfo( descr->self, SB_VERT, &info, TRUE );
if ((descr->style & WS_HSCROLL) && descr->horz_extent)
{
@@ -382,7 +382,7 @@ static void LISTBOX_UpdateScroll( LB_DESCR *descr )
info.fMask = SIF_POS | SIF_PAGE;
if (descr->style & LBS_DISABLENOSCROLL)
info.fMask |= SIF_DISABLENOSCROLL;
- SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+ NtUserSetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
}
else
{
@@ -391,7 +391,7 @@ static void LISTBOX_UpdateScroll( LB_DESCR *descr )
info.nMin = 0;
info.nMax = 0;
info.fMask = SIF_RANGE | SIF_DISABLENOSCROLL;
- SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+ NtUserSetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
}
else
{
@@ -1366,7 +1366,7 @@ static LRESULT LISTBOX_SetHorizontalExtent( LB_DESCR *descr, INT extent )
info.fMask = SIF_RANGE;
if (descr->style & LBS_DISABLENOSCROLL)
info.fMask |= SIF_DISABLENOSCROLL;
- SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+ NtUserSetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
}
if (descr->horz_pos > extent - descr->width)
LISTBOX_SetHorizontalPos( descr, extent - descr->width );
diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c
index fbac63dd881..11ba1382804 100644
--- a/dlls/user32/mdi.c
+++ b/dlls/user32/mdi.c
@@ -1730,7 +1730,7 @@ void WINAPI CalcChildScroll( HWND hwnd, INT scroll )
info.nMin = childRect.left;
info.nMax = childRect.right - clientRect.right;
info.nPos = clientRect.left - childRect.left;
- SetScrollInfo(hwnd, SB_HORZ, &info, TRUE);
+ NtUserSetScrollInfo(hwnd, SB_HORZ, &info, TRUE);
}
if (scroll == SB_HORZ) break;
/* fall through */
@@ -1740,7 +1740,7 @@ void WINAPI CalcChildScroll( HWND hwnd, INT scroll )
info.nMin = childRect.top;
info.nMax = childRect.bottom - clientRect.bottom;
info.nPos = clientRect.top - childRect.top;
- SetScrollInfo(hwnd, SB_VERT, &info, TRUE);
+ NtUserSetScrollInfo(hwnd, SB_VERT, &info, TRUE);
}
break;
}
diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c
index 3eb7ce7883b..095bcb3e24d 100644
--- a/dlls/user32/nonclient.c
+++ b/dlls/user32/nonclient.c
@@ -142,65 +142,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH AdjustWindowRectExForDpi( LPRECT rect, DWORD style
}
-LRESULT NC_HandleNCMouseMove(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
- RECT rect;
- POINT pt;
-
- TRACE("hwnd=%p wparam=%#Ix lparam=%#Ix\n", hwnd, wParam, lParam);
-
- if (wParam != HTHSCROLL && wParam != HTVSCROLL)
- return 0;
-
- WIN_GetRectangles(hwnd, COORDS_CLIENT, &rect, NULL);
-
- pt.x = (short)LOWORD(lParam);
- pt.y = (short)HIWORD(lParam);
- ScreenToClient(hwnd, &pt);
- pt.x -= rect.left;
- pt.y -= rect.top;
- SCROLL_HandleScrollEvent(hwnd, wParam == HTHSCROLL ? SB_HORZ : SB_VERT, WM_NCMOUSEMOVE, pt);
- return 0;
-}
-
-LRESULT NC_HandleNCMouseLeave(HWND hwnd)
-{
- LONG style = GetWindowLongW(hwnd, GWL_STYLE);
- POINT pt = {0, 0};
-
- TRACE("hwnd=%p\n", hwnd);
-
- if (style & WS_HSCROLL)
- SCROLL_HandleScrollEvent(hwnd, SB_HORZ, WM_NCMOUSELEAVE, pt);
- if (style & WS_VSCROLL)
- SCROLL_HandleScrollEvent(hwnd, SB_VERT, WM_NCMOUSELEAVE, pt);
-
- return 0;
-}
-
-
-/***********************************************************************
- * NC_TrackScrollBar
- *
- * Track a mouse button press on the horizontal or vertical scroll-bar.
- */
-static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
-{
- INT scrollbar;
-
- if ((wParam & 0xfff0) == SC_HSCROLL)
- {
- if ((wParam & 0x0f) != HTHSCROLL) return;
- scrollbar = SB_HORZ;
- }
- else /* SC_VSCROLL */
- {
- if ((wParam & 0x0f) != HTVSCROLL) return;
- scrollbar = SB_VERT;
- }
- SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
-}
-
/***********************************************************************
* NC_HandleSysCommand
@@ -214,16 +155,6 @@ LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
switch (wParam & 0xfff0)
{
- case SC_VSCROLL:
- case SC_HSCROLL:
- {
- POINT pt;
- pt.x = (short)LOWORD(lParam);
- pt.y = (short)HIWORD(lParam);
- NC_TrackScrollBar( hwnd, wParam, pt );
- }
- break;
-
case SC_TASKLIST:
WinExec( "taskman.exe", SW_SHOWNORMAL );
break;
diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c
index 01f7f3b88ae..bf0a7d3350a 100644
--- a/dlls/user32/scroll.c
+++ b/dlls/user32/scroll.c
@@ -43,42 +43,9 @@ typedef struct
#define SCROLLBAR_MAGIC 0x5c6011ba
- /* Minimum size of the rectangle between the arrows */
-#define SCROLL_MIN_RECT 4
-
- /* Minimum size of the thumb in pixels */
-#define SCROLL_MIN_THUMB 8
-
/* Overlap between arrows and thumb */
#define SCROLL_ARROW_THUMB_OVERLAP 0
- /* Delay (in ms) before first repetition when holding the button down */
-#define SCROLL_FIRST_DELAY 200
-
- /* Delay (in ms) between scroll repetitions */
-#define SCROLL_REPEAT_DELAY 50
-
- /* Scroll timer id */
-#define SCROLL_TIMER 0
-
- /* What to do after SCROLL_SetScrollInfo() */
-#define SA_SSI_HIDE 0x0001
-#define SA_SSI_SHOW 0x0002
-#define SA_SSI_REFRESH 0x0004
-#define SA_SSI_REPAINT_ARROWS 0x0008
-
-/* Scroll Bar tracking information */
-static struct SCROLL_TRACKING_INFO g_tracking_info;
-
- /* Is the moving thumb being displayed? */
-static BOOL SCROLL_MovingThumb = FALSE;
-
- /* Local functions */
-static BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar,
- BOOL fShowH, BOOL fShowV );
-static INT SCROLL_SetScrollInfo( HWND hwnd, INT nBar,
- const SCROLLINFO *info, BOOL bRedraw );
-
/*********************************************************************
* scrollbar class descriptor
*/
@@ -92,20 +59,6 @@ const struct builtin_class_descr SCROLL_builtin_class =
0 /* brush */
};
-/***********************************************************************
- * SCROLL_ScrollInfoValid
- *
- * Determine if the supplied SCROLLINFO struct is valid.
- * info [in] The SCROLLINFO struct to be tested
- */
-static inline BOOL SCROLL_ScrollInfoValid( LPCSCROLLINFO info )
-{
- return !(info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)
- || (info->cbSize != sizeof(*info)
- && info->cbSize != sizeof(*info) - sizeof(info->nTrackPos)));
-}
-
-
/***********************************************************************
* SCROLL_GetInternalInfo
@@ -167,270 +120,6 @@ SCROLLBAR_INFO *SCROLL_GetInternalInfo( HWND hwnd, INT nBar, BOOL alloc )
}
-/***********************************************************************
- * SCROLL_GetScrollBarRect
- *
- * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
- * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
- * 'arrowSize' returns the width or height of an arrow (depending on
- * the orientation of the scrollbar), 'thumbSize' returns the size of
- * the thumb, and 'thumbPos' returns the position of the thumb
- * relative to the left or to the top.
- * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
- */
-static BOOL SCROLL_GetScrollBarRect( HWND hwnd, INT nBar, RECT *lprect,
- INT *arrowSize, INT *thumbSize,
- INT *thumbPos )
-{
- INT pixels, min_thumb_size;
- BOOL vertical;
- WND *wndPtr = WIN_GetPtr( hwnd );
-
- if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
-
- switch(nBar)
- {
- case SB_HORZ:
- WIN_GetRectangles( hwnd, COORDS_WINDOW, NULL, lprect );
- lprect->top = lprect->bottom;
- lprect->bottom += GetSystemMetrics(SM_CYHSCROLL);
- if(wndPtr->dwStyle & WS_VSCROLL)
- lprect->right++;
- vertical = FALSE;
- break;
-
- case SB_VERT:
- WIN_GetRectangles( hwnd, COORDS_WINDOW, NULL, lprect );
- if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
- {
- lprect->right = lprect->left;
- lprect->left -= GetSystemMetrics(SM_CXVSCROLL);
- }
- else
- {
- lprect->left = lprect->right;
- lprect->right += GetSystemMetrics(SM_CXVSCROLL);
- }
- if(wndPtr->dwStyle & WS_HSCROLL)
- lprect->bottom++;
- vertical = TRUE;
- break;
-
- case SB_CTL:
- GetClientRect( hwnd, lprect );
- vertical = ((wndPtr->dwStyle & SBS_VERT) != 0);
- break;
-
- default:
- WIN_ReleasePtr( wndPtr );
- return FALSE;
- }
-
- if (vertical) pixels = lprect->bottom - lprect->top;
- else pixels = lprect->right - lprect->left;
-
- if (pixels <= 2*GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT)
- {
- if (pixels > SCROLL_MIN_RECT)
- *arrowSize = (pixels - SCROLL_MIN_RECT) / 2;
- else
- *arrowSize = 0;
- *thumbPos = *thumbSize = 0;
- }
- else
- {
- SCROLLBAR_INFO *info = SCROLL_GetInternalInfo( hwnd, nBar, TRUE );
- if (!info)
- {
- WARN("called for missing scroll bar\n");
- WIN_ReleasePtr( wndPtr );
- return FALSE;
- }
- *arrowSize = GetSystemMetrics(SM_CXVSCROLL);
- pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
-
- if (info->page)
- {
- *thumbSize = MulDiv(pixels,info->page,(info->maxVal-info->minVal+1));
- min_thumb_size = MulDiv(SCROLL_MIN_THUMB, GetDpiForWindow(hwnd), 96);
- if (*thumbSize < min_thumb_size) *thumbSize = min_thumb_size;
- }
- else *thumbSize = GetSystemMetrics(SM_CXVSCROLL);
-
- if (((pixels -= *thumbSize ) < 0) ||
- ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
- {
- /* Rectangle too small or scrollbar disabled -> no thumb */
- *thumbPos = *thumbSize = 0;
- }
- else
- {
- INT max = info->maxVal - max( info->page-1, 0 );
- if (info->minVal >= max)
- *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
- else
- *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
- + MulDiv(pixels, (info->curVal-info->minVal),(max - info->minVal));
- }
- }
- WIN_ReleasePtr( wndPtr );
- return vertical;
-}
-
-static void SCROLL_GetScrollBarDrawInfo( HWND hwnd, INT bar,
- const struct SCROLL_TRACKING_INFO *tracking_info,
- RECT *rect, INT *arrow_size, INT *thumb_size,
- INT *thumb_pos, BOOL *vertical )
-{
- INT pos, max_size;
-
- if (bar == SB_CTL && GetWindowLongW( hwnd, GWL_STYLE ) & (SBS_SIZEGRIP | SBS_SIZEBOX))
- {
- GetClientRect( hwnd, rect );
- *arrow_size = 0;
- *thumb_pos = 0;
- *thumb_size = 0;
- *vertical = FALSE;
- return;
- }
-
- *vertical = SCROLL_GetScrollBarRect( hwnd, bar, rect, arrow_size, thumb_size, thumb_pos );
-
- if (SCROLL_MovingThumb && tracking_info->win == hwnd && tracking_info->bar == bar)
- {
- max_size = *vertical ? rect->bottom - rect->top : rect->right - rect->left;
- max_size -= *arrow_size - SCROLL_ARROW_THUMB_OVERLAP + *thumb_size;
-
- pos = tracking_info->thumb_pos;
- if (pos < *arrow_size - SCROLL_ARROW_THUMB_OVERLAP)
- pos = *arrow_size - SCROLL_ARROW_THUMB_OVERLAP;
- else if (pos > max_size)
- pos = max_size;
-
- *thumb_pos = pos;
- }
-}
-
-/***********************************************************************
- * SCROLL_GetThumbVal
- *
- * Compute the current scroll position based on the thumb position in pixels
- * from the top of the scroll-bar.
- */
-static UINT SCROLL_GetThumbVal( HWND hwnd, SCROLLBAR_INFO *infoPtr, RECT *rect, BOOL vertical,
- INT pos )
-{
- INT thumbSize, minThumbSize;
- INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
- INT range;
-
- if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
- return infoPtr->minVal;
-
- if (infoPtr->page)
- {
- thumbSize = MulDiv(pixels,infoPtr->page,(infoPtr->maxVal-infoPtr->minVal+1));
- minThumbSize = MulDiv(SCROLL_MIN_THUMB, GetDpiForWindow(hwnd), 96);
- if (thumbSize < minThumbSize) thumbSize = minThumbSize;
- }
- else thumbSize = GetSystemMetrics(SM_CXVSCROLL);
-
- if ((pixels -= thumbSize) <= 0) return infoPtr->minVal;
-
- pos = max( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) );
- if (pos > pixels) pos = pixels;
-
- if (!infoPtr->page)
- range = infoPtr->maxVal - infoPtr->minVal;
- else
- range = infoPtr->maxVal - infoPtr->minVal - infoPtr->page + 1;
-
- return infoPtr->minVal + MulDiv(pos, range, pixels);
-}
-
-/***********************************************************************
- * SCROLL_PtInRectEx
- */
-static BOOL SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical )
-{
- RECT rect = *lpRect;
- int scrollbarWidth;
-
- /* Pad hit rect to allow mouse to be dragged outside of scrollbar and
- * still be considered in the scrollbar. */
- if (vertical)
- {
- scrollbarWidth = lpRect->right - lpRect->left;
- InflateRect(&rect, scrollbarWidth * 8, scrollbarWidth * 2);
- }
- else
- {
- scrollbarWidth = lpRect->bottom - lpRect->top;
- InflateRect(&rect, scrollbarWidth * 2, scrollbarWidth * 8);
- }
- return PtInRect( &rect, pt );
-}
-
-/***********************************************************************
- * SCROLL_ClipPos
- */
-static POINT SCROLL_ClipPos( LPRECT lpRect, POINT pt )
-{
- if( pt.x < lpRect->left )
- pt.x = lpRect->left;
- else
- if( pt.x > lpRect->right )
- pt.x = lpRect->right;
-
- if( pt.y < lpRect->top )
- pt.y = lpRect->top;
- else
- if( pt.y > lpRect->bottom )
- pt.y = lpRect->bottom;
-
- return pt;
-}
-
-
-/***********************************************************************
- * SCROLL_HitTest
- *
- * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
- */
-static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, INT nBar,
- POINT pt, BOOL bDragging )
-{
- INT arrowSize, thumbSize, thumbPos;
- RECT rect;
-
- BOOL vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
- &arrowSize, &thumbSize, &thumbPos );
-
- if ( (bDragging && !SCROLL_PtInRectEx( &rect, pt, vertical )) ||
- (!PtInRect( &rect, pt )) ) return SCROLL_NOWHERE;
-
- if (vertical)
- {
- if (pt.y < rect.top + arrowSize) return SCROLL_TOP_ARROW;
- if (pt.y >= rect.bottom - arrowSize) return SCROLL_BOTTOM_ARROW;
- if (!thumbPos) return SCROLL_TOP_RECT;
- pt.y -= rect.top;
- if (pt.y < thumbPos) return SCROLL_TOP_RECT;
- if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
- }
- else /* horizontal */
- {
- if (pt.x < rect.left + arrowSize) return SCROLL_TOP_ARROW;
- if (pt.x >= rect.right - arrowSize) return SCROLL_BOTTOM_ARROW;
- if (!thumbPos) return SCROLL_TOP_RECT;
- pt.x -= rect.left;
- if (pt.x < thumbPos) return SCROLL_TOP_RECT;
- if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
- }
- return SCROLL_THUMB;
-}
-
-
/***********************************************************************
* SCROLL_DrawArrows
*
@@ -630,102 +319,6 @@ void WINAPI USER_ScrollBarDraw( HWND hwnd, HDC hdc, INT nBar, enum SCROLL_HITTES
}
}
-void WINAPI SCROLL_SetStandardScrollPainted( HWND hwnd, INT bar, BOOL painted )
-{
- LPSCROLLBAR_INFO info;
-
- if (bar != SB_HORZ && bar != SB_VERT)
- return;
-
- info = SCROLL_GetInternalInfo( hwnd, bar, FALSE );
- if (info)
- info->painted = painted;
-}
-
-static BOOL SCROLL_IsStandardScrollPainted( HWND hwnd, INT bar )
-{
- LPSCROLLBAR_INFO info;
-
- if (bar != SB_HORZ && bar != SB_VERT)
- return FALSE;
-
- info = SCROLL_GetInternalInfo( hwnd, bar, FALSE );
- return info ? info->painted : FALSE;
-}
-
-/***********************************************************************
- * SCROLL_DrawScrollBar
- *
- * Redraw the whole scrollbar.
- */
-void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, INT bar, enum SCROLL_HITTEST hit_test,
- const struct SCROLL_TRACKING_INFO *tracking_info, BOOL draw_arrows,
- BOOL draw_interior )
-{
- INT arrow_size, thumb_size, thumb_pos;
- RECT rect, clip_box, intersect;
- BOOL vertical;
- DWORD style;
-
- if (!(hwnd = WIN_GetFullHandle( hwnd )))
- return;
-
- style = GetWindowLongW( hwnd, GWL_STYLE );
- if ((bar == SB_VERT && !(style & WS_VSCROLL)) || (bar == SB_HORZ && !(style & WS_HSCROLL)))
- return;
-
- if (!WIN_IsWindowDrawable( hwnd, FALSE ))
- return;
-
- SCROLL_GetScrollBarDrawInfo( hwnd, bar, tracking_info, &rect, &arrow_size, &thumb_size,
- &thumb_pos, &vertical );
- /* do not draw if the scrollbar rectangle is empty */
- if (IsRectEmpty( &rect ))
- return;
-
- TRACE("hwnd %p, hdc %p, bar %d, hit_test %d, tracking_info(win %p, bar %d, thumb_pos %d, "
- "track_pos %d, vertical %d, hit_test %d), draw_arrows %d, draw_interior %d, rect %s, "
- "arrow_size %d, thumb_pos %d, thumb_val %d, vertical %d, captured window %p\n", hwnd, hdc,
- bar, hit_test, tracking_info->win, tracking_info->bar, tracking_info->thumb_pos,
- tracking_info->thumb_val, tracking_info->vertical, tracking_info->hit_test, draw_arrows,
- draw_interior, wine_dbgstr_rect(&rect), arrow_size, thumb_pos, thumb_size, vertical,
- GetCapture());
- user_api->pScrollBarDraw( hwnd, hdc, bar, hit_test, tracking_info, draw_arrows, draw_interior,
- &rect, arrow_size, thumb_pos, thumb_size, vertical );
-
- if (bar == SB_HORZ || bar == SB_VERT)
- {
- GetClipBox( hdc, &clip_box );
- if (IntersectRect(&intersect, &rect, &clip_box))
- SCROLL_SetStandardScrollPainted( hwnd, bar, TRUE );
- }
-}
-
-void SCROLL_DrawNCScrollBar( HWND hwnd, HDC hdc, BOOL draw_horizontal, BOOL draw_vertical )
-{
- if (draw_horizontal)
- SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, g_tracking_info.hit_test, &g_tracking_info, TRUE, TRUE );
- if (draw_vertical)
- SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, g_tracking_info.hit_test, &g_tracking_info, TRUE, TRUE );
-}
-
-/***********************************************************************
- * SCROLL_RefreshScrollBar
- *
- * Repaint the scroll bar interior after a SetScrollRange() or
- * SetScrollPos() call.
- */
-static void SCROLL_RefreshScrollBar( HWND hwnd, INT nBar,
- BOOL arrows, BOOL interior )
-{
- HDC hdc = NtUserGetDCEx( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW) );
- if (!hdc) return;
-
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, g_tracking_info.hit_test, &g_tracking_info, arrows, interior );
- NtUserReleaseDC( hwnd, hdc );
-}
-
-
/***********************************************************************
* SCROLL_HandleKbdEvent
*
@@ -762,507 +355,6 @@ static void SCROLL_HandleKbdEvent(HWND hwnd, WPARAM wParam, LPARAM lParam)
}
-/***********************************************************************
- * SCROLL_HandleScrollEvent
- *
- * Handle a mouse or timer event for the scrollbar.
- * 'pt' is the location of the mouse event in client (for SB_CTL) or
- * windows coordinates.
- */
-void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
-{
- /* Previous mouse position for timer events */
- static POINT prevPt;
- /* Thumb position when tracking started. */
- static UINT trackThumbPos;
- /* Position in the scroll-bar of the last button-down event. */
- static INT lastClickPos;
- /* Position in the scroll-bar of the last mouse event. */
- static INT lastMousePos;
-
- enum SCROLL_HITTEST hittest;
- HWND hwndOwner, hwndCtl;
- TRACKMOUSEEVENT tme;
- BOOL vertical;
- INT arrowSize, thumbSize, thumbPos;
- RECT rect;
- HDC hdc;
-
- SCROLLBAR_INFO *infoPtr = SCROLL_GetInternalInfo( hwnd, nBar, FALSE );
- if (!infoPtr) return;
- if ((g_tracking_info.hit_test == SCROLL_NOWHERE)
- && (msg != WM_LBUTTONDOWN && msg != WM_MOUSEMOVE && msg != WM_MOUSELEAVE
- && msg != WM_NCMOUSEMOVE && msg != WM_NCMOUSELEAVE))
- return;
-
- if (nBar == SB_CTL && (GetWindowLongW( hwnd, GWL_STYLE ) & (SBS_SIZEGRIP | SBS_SIZEBOX)))
- {
- switch(msg)
- {
- case WM_LBUTTONDOWN: /* Initialise mouse tracking */
- NtUserHideCaret( hwnd ); /* hide caret while holding down LBUTTON */
- NtUserSetCapture( hwnd );
- prevPt = pt;
- g_tracking_info.hit_test = hittest = SCROLL_THUMB;
- break;
- case WM_MOUSEMOVE:
- GetClientRect(GetParent(GetParent(hwnd)),&rect);
- prevPt = pt;
- break;
- case WM_LBUTTONUP:
- ReleaseCapture();
- g_tracking_info.hit_test = hittest = SCROLL_NOWHERE;
- if (hwnd == GetFocus()) NtUserShowCaret( hwnd );
- break;
- case WM_SYSTIMER:
- pt = prevPt;
- break;
- }
- return;
- }
-
- hdc = NtUserGetDCEx( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
- vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
- &arrowSize, &thumbSize, &thumbPos );
- hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd) : hwnd;
- hwndCtl = (nBar == SB_CTL) ? hwnd : 0;
-
- switch(msg)
- {
- case WM_LBUTTONDOWN: /* Initialise mouse tracking */
- NtUserHideCaret( hwnd ); /* hide caret while holding down LBUTTON */
- g_tracking_info.vertical = vertical;
- g_tracking_info.hit_test = hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
- lastClickPos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
- lastMousePos = lastClickPos;
- trackThumbPos = thumbPos;
- prevPt = pt;
- if (nBar == SB_CTL && (GetWindowLongW(hwnd, GWL_STYLE) & WS_TABSTOP)) NtUserSetFocus( hwnd );
- NtUserSetCapture( hwnd );
- break;
-
- case WM_MOUSEMOVE:
- hittest = SCROLL_HitTest( hwnd, nBar, pt, vertical == g_tracking_info.vertical && GetCapture() == hwnd );
- prevPt = pt;
-
- if (nBar != SB_CTL)
- break;
-
- tme.cbSize = sizeof(tme);
- tme.dwFlags = TME_QUERY;
- NtUserTrackMouseEvent( &tme );
- if (!(tme.dwFlags & TME_LEAVE) || tme.hwndTrack != hwnd)
- {
- tme.dwFlags = TME_LEAVE;
- tme.hwndTrack = hwnd;
- NtUserTrackMouseEvent( &tme );
- }
-
- break;
-
- case WM_NCMOUSEMOVE:
- hittest = SCROLL_HitTest( hwnd, nBar, pt, vertical == g_tracking_info.vertical && GetCapture() == hwnd );
- prevPt = pt;
-
- if (nBar == SB_CTL)
- break;
-
- tme.cbSize = sizeof(tme);
- tme.dwFlags = TME_QUERY;
- NtUserTrackMouseEvent( &tme );
- if (((tme.dwFlags & (TME_NONCLIENT | TME_LEAVE)) != (TME_NONCLIENT | TME_LEAVE)) || tme.hwndTrack != hwnd)
- {
- tme.dwFlags = TME_NONCLIENT | TME_LEAVE;
- tme.hwndTrack = hwnd;
- NtUserTrackMouseEvent( &tme );
- }
-
- break;
-
- case WM_NCMOUSELEAVE:
- if (nBar == SB_CTL)
- return;
-
- hittest = SCROLL_NOWHERE;
- break;
-
- case WM_MOUSELEAVE:
- if (nBar != SB_CTL)
- return;
-
- hittest = SCROLL_NOWHERE;
- break;
-
- case WM_LBUTTONUP:
- hittest = SCROLL_NOWHERE;
- ReleaseCapture();
- /* if scrollbar has focus, show back caret */
- if (hwnd == GetFocus()) NtUserShowCaret( hwnd );
- break;
-
- case WM_SYSTIMER:
- pt = prevPt;
- hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
- break;
-
- default:
- return; /* Should never happen */
- }
-
- TRACE("Event: hwnd=%p bar=%d msg=%s pt=%ld,%ld hit=%d\n",
- hwnd, nBar, SPY_GetMsgName(msg,hwnd), pt.x, pt.y, hittest );
-
- switch (g_tracking_info.hit_test)
- {
- case SCROLL_NOWHERE: /* No tracking in progress */
- /* For standard scroll bars, hovered state gets painted only when the scroll bar was
- * previously painted by DefWinProc(). If an application handles WM_NCPAINT by itself, then
- * the scrollbar shouldn't be repainted here to avoid overwriting the application painted
- * content */
- if (msg == WM_MOUSEMOVE || msg == WM_MOUSELEAVE
- || ((msg == WM_NCMOUSEMOVE || msg == WM_NCMOUSELEAVE)
- && SCROLL_IsStandardScrollPainted( hwnd, nBar)))
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, TRUE, TRUE );
- break;
-
- case SCROLL_TOP_ARROW:
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, TRUE, FALSE );
- if (hittest == g_tracking_info.hit_test)
- {
- if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
- {
- SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
- SB_LINEUP, (LPARAM)hwndCtl );
- }
-
- NtUserSetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
- SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY );
- }
- else KillSystemTimer( hwnd, SCROLL_TIMER );
- break;
-
- case SCROLL_TOP_RECT:
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, FALSE, TRUE );
- if (hittest == g_tracking_info.hit_test)
- {
- if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
- {
- SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
- SB_PAGEUP, (LPARAM)hwndCtl );
- }
- NtUserSetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
- SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY );
- }
- else KillSystemTimer( hwnd, SCROLL_TIMER );
- break;
-
- case SCROLL_THUMB:
- if (msg == WM_LBUTTONDOWN)
- {
- g_tracking_info.win = hwnd;
- g_tracking_info.bar = nBar;
- g_tracking_info.thumb_pos = trackThumbPos + lastMousePos - lastClickPos;
- g_tracking_info.thumb_val = SCROLL_GetThumbVal( hwnd, infoPtr, &rect, vertical,
- g_tracking_info.thumb_pos );
- if (!SCROLL_MovingThumb)
- {
- SCROLL_MovingThumb = TRUE;
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, FALSE, TRUE );
- }
- }
- else if (msg == WM_LBUTTONUP)
- {
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, SCROLL_NOWHERE, &g_tracking_info, FALSE, TRUE );
- }
- else if (msg == WM_MOUSEMOVE)
- {
- INT pos;
-
- if (!SCROLL_PtInRectEx( &rect, pt, vertical )) pos = lastClickPos;
- else
- {
- pt = SCROLL_ClipPos( &rect, pt );
- pos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
- }
- if ( (pos != lastMousePos) || (!SCROLL_MovingThumb) )
- {
- lastMousePos = pos;
- g_tracking_info.thumb_pos = trackThumbPos + pos - lastClickPos;
- g_tracking_info.thumb_val = SCROLL_GetThumbVal( hwnd, infoPtr, &rect, vertical,
- g_tracking_info.thumb_pos );
- SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
- MAKEWPARAM( SB_THUMBTRACK, g_tracking_info.thumb_val ),
- (LPARAM)hwndCtl );
- SCROLL_MovingThumb = TRUE;
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, FALSE, TRUE );
- }
- }
- break;
-
- case SCROLL_BOTTOM_RECT:
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, FALSE, TRUE );
- if (hittest == g_tracking_info.hit_test)
- {
- if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
- {
- SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
- SB_PAGEDOWN, (LPARAM)hwndCtl );
- }
- NtUserSetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
- SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY );
- }
- else KillSystemTimer( hwnd, SCROLL_TIMER );
- break;
-
- case SCROLL_BOTTOM_ARROW:
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, TRUE, FALSE );
- if (hittest == g_tracking_info.hit_test)
- {
- if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
- {
- SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
- SB_LINEDOWN, (LPARAM)hwndCtl );
- }
-
- NtUserSetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
- SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY );
- }
- else KillSystemTimer( hwnd, SCROLL_TIMER );
- break;
- }
-
- if (msg == WM_LBUTTONDOWN)
- {
-
- if (hittest == SCROLL_THUMB)
- {
- UINT val = SCROLL_GetThumbVal( hwnd, infoPtr, &rect, vertical,
- trackThumbPos + lastMousePos - lastClickPos );
- SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
- MAKEWPARAM( SB_THUMBTRACK, val ), (LPARAM)hwndCtl );
- }
- }
-
- if (msg == WM_LBUTTONUP)
- {
- hittest = g_tracking_info.hit_test;
- g_tracking_info.hit_test = SCROLL_NOWHERE; /* Terminate tracking */
-
- if (hittest == SCROLL_THUMB)
- {
- UINT val = SCROLL_GetThumbVal( hwnd, infoPtr, &rect, vertical,
- trackThumbPos + lastMousePos - lastClickPos );
- SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
- MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)hwndCtl );
- }
- /* SB_ENDSCROLL doesn't report thumb position */
- SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
- SB_ENDSCROLL, (LPARAM)hwndCtl );
-
- /* Terminate tracking */
- g_tracking_info.win = 0;
- SCROLL_MovingThumb = FALSE;
- hittest = SCROLL_NOWHERE;
- SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, TRUE, TRUE );
- }
-
- NtUserReleaseDC( hwnd, hdc );
-}
-
-
-/***********************************************************************
- * SCROLL_TrackScrollBar
- *
- * Track a mouse button press on a scroll-bar.
- * pt is in screen-coordinates for non-client scroll bars.
- */
-void SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt )
-{
- MSG msg;
- RECT rect;
-
- if (scrollbar != SB_CTL)
- {
- WIN_GetRectangles( hwnd, COORDS_CLIENT, &rect, NULL );
- ScreenToClient( hwnd, &pt );
- pt.x -= rect.left;
- pt.y -= rect.top;
- }
- else
- rect.left = rect.top = 0;
-
- SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
-
- do
- {
- if (!GetMessageW( &msg, 0, 0, 0 )) break;
- if (NtUserCallMsgFilter( &msg, MSGF_SCROLLBAR )) continue;
- if (msg.message == WM_LBUTTONUP ||
- msg.message == WM_MOUSEMOVE ||
- msg.message == WM_MOUSELEAVE ||
- msg.message == WM_NCMOUSEMOVE ||
- msg.message == WM_NCMOUSELEAVE ||
- (msg.message == WM_SYSTIMER && msg.wParam == SCROLL_TIMER))
- {
- pt.x = (short)LOWORD(msg.lParam) - rect.left;
- pt.y = (short)HIWORD(msg.lParam) - rect.top;
- SCROLL_HandleScrollEvent( hwnd, scrollbar, msg.message, pt );
- }
- else
- {
- TranslateMessage( &msg );
- DispatchMessageW( &msg );
- }
- if (!IsWindow( hwnd ))
- {
- ReleaseCapture();
- break;
- }
- } while (msg.message != WM_LBUTTONUP && GetCapture() == hwnd);
-}
-
-
-/*************************************************************************
- * SCROLL_GetScrollInfo
- *
- * Internal helper for the API function
- *
- * PARAMS
- * hwnd [I] Handle of window with scrollbar(s)
- * nBar [I] One of SB_HORZ, SB_VERT, or SB_CTL
- * info [IO] fMask specifies which values to retrieve
- *
- * RETURNS
- * FALSE if requested field not filled (f.i. scroll bar does not exist)
- */
-static BOOL SCROLL_GetScrollInfo(HWND hwnd, INT nBar, LPSCROLLINFO info)
-{
- LPSCROLLBAR_INFO infoPtr;
-
- /* handle invalid data structure */
- if (!SCROLL_ScrollInfoValid(info)
- || !(infoPtr = SCROLL_GetInternalInfo(hwnd, nBar, FALSE)))
- return FALSE;
-
- /* fill in the desired scroll info structure */
- if (info->fMask & SIF_PAGE) info->nPage = infoPtr->page;
- if (info->fMask & SIF_POS) info->nPos = infoPtr->curVal;
- if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info)))
- info->nTrackPos = (g_tracking_info.win == WIN_GetFullHandle(hwnd)) ? g_tracking_info.thumb_val : infoPtr->curVal;
- if (info->fMask & SIF_RANGE)
- {
- info->nMin = infoPtr->minVal;
- info->nMax = infoPtr->maxVal;
- }
-
- TRACE("cbSize %02x fMask %04x nMin %d nMax %d nPage %u nPos %d nTrackPos %d\n",
- info->cbSize, info->fMask, info->nMin, info->nMax, info->nPage,
- info->nPos, info->nTrackPos);
-
- return (info->fMask & SIF_ALL) != 0;
-}
-
-
-/*************************************************************************
- * SCROLL_GetScrollBarInfo
- *
- * Internal helper for the API function
- *
- * PARAMS
- * hwnd [I] Handle of window with scrollbar(s)
- * idObject [I] One of OBJID_CLIENT, OBJID_HSCROLL, or OBJID_VSCROLL
- * info [IO] cbSize specifies the size of the structure
- *
- * RETURNS
- * FALSE if failed
- */
-static BOOL SCROLL_GetScrollBarInfo(HWND hwnd, LONG idObject, LPSCROLLBARINFO info)
-{
- LPSCROLLBAR_INFO infoPtr;
- INT nBar;
- INT nDummy;
- DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
- BOOL pressed;
- RECT rect;
-
- switch (idObject)
- {
- case OBJID_CLIENT: nBar = SB_CTL; break;
- case OBJID_HSCROLL: nBar = SB_HORZ; break;
- case OBJID_VSCROLL: nBar = SB_VERT; break;
- default: return FALSE;
- }
-
- /* handle invalid data structure */
- if (info->cbSize != sizeof(*info))
- return FALSE;
-
- SCROLL_GetScrollBarRect(hwnd, nBar, &info->rcScrollBar, &nDummy,
- &info->dxyLineButton, &info->xyThumbTop);
- /* rcScrollBar needs to be in screen coordinates */
- GetWindowRect(hwnd, &rect);
- OffsetRect(&info->rcScrollBar, rect.left, rect.top);
-
- info->xyThumbBottom = info->xyThumbTop + info->dxyLineButton;
-
- infoPtr = SCROLL_GetInternalInfo(hwnd, nBar, TRUE);
- if (!infoPtr)
- return FALSE;
-
- /* Scroll bar state */
- info->rgstate[0] = 0;
- if ((nBar == SB_HORZ && !(style & WS_HSCROLL))
- || (nBar == SB_VERT && !(style & WS_VSCROLL)))
- info->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
- if (infoPtr->minVal >= infoPtr->maxVal - max(infoPtr->page - 1, 0))
- {
- if (!(info->rgstate[0] & STATE_SYSTEM_INVISIBLE))
- info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE;
- else
- info->rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
- }
- if (nBar == SB_CTL && !IsWindowEnabled(hwnd))
- info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE;
-
- pressed = ((nBar == SB_VERT) == g_tracking_info.vertical && GetCapture() == hwnd);
-
- /* Top/left arrow button state. MSDN says top/right, but I don't believe it */
- info->rgstate[1] = 0;
- if (pressed && g_tracking_info.hit_test == SCROLL_TOP_ARROW)
- info->rgstate[1] |= STATE_SYSTEM_PRESSED;
- if (infoPtr->flags & ESB_DISABLE_LTUP)
- info->rgstate[1] |= STATE_SYSTEM_UNAVAILABLE;
-
- /* Page up/left region state. MSDN says up/right, but I don't believe it */
- info->rgstate[2] = 0;
- if (infoPtr->curVal == infoPtr->minVal)
- info->rgstate[2] |= STATE_SYSTEM_INVISIBLE;
- if (pressed && g_tracking_info.hit_test == SCROLL_TOP_RECT)
- info->rgstate[2] |= STATE_SYSTEM_PRESSED;
-
- /* Thumb state */
- info->rgstate[3] = 0;
- if (pressed && g_tracking_info.hit_test == SCROLL_THUMB)
- info->rgstate[3] |= STATE_SYSTEM_PRESSED;
-
- /* Page down/right region state. MSDN says down/left, but I don't believe it */
- info->rgstate[4] = 0;
- if (infoPtr->curVal >= infoPtr->maxVal - 1)
- info->rgstate[4] |= STATE_SYSTEM_INVISIBLE;
- if (pressed && g_tracking_info.hit_test == SCROLL_BOTTOM_RECT)
- info->rgstate[4] |= STATE_SYSTEM_PRESSED;
-
- /* Bottom/right arrow button state. MSDN says bottom/left, but I don't believe it */
- info->rgstate[5] = 0;
- if (pressed && g_tracking_info.hit_test == SCROLL_BOTTOM_ARROW)
- info->rgstate[5] |= STATE_SYSTEM_PRESSED;
- if (infoPtr->flags & ESB_DISABLE_RTDN)
- info->rgstate[5] |= STATE_SYSTEM_UNAVAILABLE;
-
- return TRUE;
-}
-
-
/*************************************************************************
* SCROLL_GetScrollPos
*
@@ -1305,77 +397,12 @@ static BOOL SCROLL_GetScrollRange(HWND hwnd, INT nBar, LPINT lpMin, LPINT lpMax)
}
-/*************************************************************************
- * SCROLL_SetScrollRange
- *
- * PARAMS
- * hwnd [I] Handle of window with scrollbar(s)
- * nBar [I] One of SB_HORZ, SB_VERT, or SB_CTL
- * lpMin [I] Minimum value
- * lpMax [I] Maximum value
- *
- */
-static BOOL SCROLL_SetScrollRange(HWND hwnd, INT nBar, INT minVal, INT maxVal)
-{
- LPSCROLLBAR_INFO infoPtr = SCROLL_GetInternalInfo(hwnd, nBar, FALSE);
-
- TRACE("hwnd=%p nBar=%d min=%d max=%d\n", hwnd, nBar, minVal, maxVal);
-
- if (infoPtr)
- {
- infoPtr->minVal = minVal;
- infoPtr->maxVal = maxVal;
- }
- return TRUE;
-}
-
LRESULT WINAPI USER_ScrollBarProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, BOOL unicode )
{
if (!IsWindow( hwnd )) return 0;
switch(message)
{
- case WM_ENABLE:
- {
- SCROLLBAR_INFO *infoPtr;
- if ((infoPtr = SCROLL_GetInternalInfo( hwnd, SB_CTL, FALSE )))
- {
- infoPtr->flags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
- SCROLL_RefreshScrollBar(hwnd, SB_CTL, TRUE, TRUE);
- }
- }
- return 0;
-
- case WM_LBUTTONDBLCLK:
- case WM_LBUTTONDOWN:
- if (GetWindowLongW( hwnd, GWL_STYLE ) & SBS_SIZEGRIP)
- {
- SendMessageW( GetParent(hwnd), WM_SYSCOMMAND,
- SC_SIZE + ((GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) ?
- WMSZ_BOTTOMLEFT : WMSZ_BOTTOMRIGHT), lParam );
- }
- else
- {
- POINT pt;
- pt.x = (short)LOWORD(lParam);
- pt.y = (short)HIWORD(lParam);
- SCROLL_TrackScrollBar( hwnd, SB_CTL, pt );
- }
- break;
- case WM_LBUTTONUP:
- case WM_NCMOUSEMOVE:
- case WM_NCMOUSELEAVE:
- case WM_MOUSEMOVE:
- case WM_MOUSELEAVE:
- case WM_SYSTIMER:
- {
- POINT pt;
- pt.x = (short)LOWORD(lParam);
- pt.y = (short)HIWORD(lParam);
- SCROLL_HandleScrollEvent( hwnd, SB_CTL, message, pt );
- }
- break;
-
case WM_KEYDOWN:
SCROLL_HandleKbdEvent(hwnd, wParam, lParam);
break;
@@ -1384,21 +411,19 @@ LRESULT WINAPI USER_ScrollBarProc( HWND hwnd, UINT message, WPARAM wParam, LPARA
NtUserShowCaret( hwnd );
break;
+ case WM_ENABLE:
case WM_SETFOCUS:
case WM_KILLFOCUS:
case WM_CREATE:
case WM_ERASEBKGND:
case WM_GETDLGCODE:
- return NtUserMessageCall( hwnd, message, wParam, lParam, 0, NtUserScrollBarWndProc, !unicode );
-
case WM_PAINT:
- {
- PAINTSTRUCT ps;
- HDC hdc = wParam ? (HDC)wParam : NtUserBeginPaint( hwnd, &ps );
- SCROLL_DrawScrollBar( hwnd, hdc, SB_CTL, g_tracking_info.hit_test, &g_tracking_info, TRUE, TRUE );
- if (!wParam) NtUserEndPaint( hwnd, &ps );
- }
- break;
+ case SBM_SETRANGEREDRAW:
+ case SBM_SETRANGE:
+ case SBM_GETSCROLLINFO:
+ case SBM_GETSCROLLBARINFO:
+ case SBM_SETSCROLLINFO:
+ return NtUserMessageCall( hwnd, message, wParam, lParam, 0, NtUserScrollBarWndProc, !unicode );
case WM_SETCURSOR:
if (GetWindowLongW( hwnd, GWL_STYLE ) & SBS_SIZEGRIP)
@@ -1414,31 +439,11 @@ LRESULT WINAPI USER_ScrollBarProc( HWND hwnd, UINT message, WPARAM wParam, LPARA
case SBM_GETPOS:
return SCROLL_GetScrollPos(hwnd, SB_CTL);
- case SBM_SETRANGEREDRAW:
- case SBM_SETRANGE:
- {
- INT oldPos = SCROLL_GetScrollPos( hwnd, SB_CTL );
- SCROLL_SetScrollRange( hwnd, SB_CTL, wParam, lParam );
- if (message == SBM_SETRANGEREDRAW)
- SCROLL_RefreshScrollBar( hwnd, SB_CTL, TRUE, TRUE );
- if (oldPos != SCROLL_GetScrollPos( hwnd, SB_CTL )) return oldPos;
- }
- return 0;
-
case SBM_GETRANGE:
return SCROLL_GetScrollRange(hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam);
case SBM_ENABLE_ARROWS:
- return EnableScrollBar( hwnd, SB_CTL, wParam );
-
- case SBM_SETSCROLLINFO:
- return SCROLL_SetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam, wParam );
-
- case SBM_GETSCROLLINFO:
- return SCROLL_GetScrollInfo(hwnd, SB_CTL, (SCROLLINFO *)lParam);
-
- case SBM_GETSCROLLBARINFO:
- return SCROLL_GetScrollBarInfo(hwnd, OBJID_CLIENT, (SCROLLBARINFO *)lParam);
+ return NtUserEnableScrollBar( hwnd, SB_CTL, wParam );
case 0x00e5:
case 0x00e7:
@@ -1471,186 +476,6 @@ LRESULT ScrollBarWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPar
return user_api->pScrollBarWndProc( hwnd, msg, wParam, lParam, unicode );
}
-/*************************************************************************
- * SetScrollInfo (USER32.@)
- *
- * SetScrollInfo can be used to set the position, upper bound,
- * lower bound, and page size of a scrollbar control.
- *
- * PARAMS
- * hwnd [I] Handle of window with scrollbar(s)
- * nBar [I] One of SB_HORZ, SB_VERT, or SB_CTL
- * info [I] Specifies what to change and new values
- * bRedraw [I] Should scrollbar be redrawn afterwards?
- *
- * RETURNS
- * Scrollbar position
- *
- * NOTE
- * For 100 lines of text to be displayed in a window of 25 lines,
- * one would for instance use info->nMin=0, info->nMax=75
- * (corresponding to the 76 different positions of the window on
- * the text), and info->nPage=25.
- */
-INT WINAPI DECLSPEC_HOTPATCH SetScrollInfo(HWND hwnd, INT nBar, const SCROLLINFO *info, BOOL bRedraw)
-{
- TRACE("hwnd=%p nBar=%d info=%p, bRedraw=%d\n", hwnd, nBar, info, bRedraw);
-
- /* Refer SB_CTL requests to the window */
- if (nBar == SB_CTL)
- return SendMessageW(hwnd, SBM_SETSCROLLINFO, bRedraw, (LPARAM)info);
- else
- return SCROLL_SetScrollInfo( hwnd, nBar, info, bRedraw );
-}
-
-static INT SCROLL_SetScrollInfo( HWND hwnd, INT nBar, LPCSCROLLINFO info, BOOL bRedraw )
-{
- /* Update the scrollbar state and set action flags according to
- * what has to be done graphics wise. */
-
- SCROLLBAR_INFO *infoPtr;
- UINT new_flags;
- INT action = 0;
-
- /* handle invalid data structure */
- if (!SCROLL_ScrollInfoValid(info)
- || !(infoPtr = SCROLL_GetInternalInfo(hwnd, nBar, TRUE)))
- return 0;
-
- if (TRACE_ON(scroll))
- {
- TRACE("hwnd=%p bar=%d", hwnd, nBar);
- if (info->fMask & SIF_PAGE) TRACE( " page=%d", info->nPage );
- if (info->fMask & SIF_POS) TRACE( " pos=%d", info->nPos );
- if (info->fMask & SIF_RANGE) TRACE( " min=%d max=%d", info->nMin, info->nMax );
- TRACE("\n");
- }
-
- /* Set the page size */
-
- if (info->fMask & SIF_PAGE)
- {
- if( infoPtr->page != info->nPage )
- {
- infoPtr->page = info->nPage;
- action |= SA_SSI_REFRESH;
- }
- }
-
- /* Set the scroll pos */
-
- if (info->fMask & SIF_POS)
- {
- if( infoPtr->curVal != info->nPos )
- {
- infoPtr->curVal = info->nPos;
- action |= SA_SSI_REFRESH;
- }
- }
-
- /* Set the scroll range */
-
- if (info->fMask & SIF_RANGE)
- {
- /* Invalid range -> range is set to (0,0) */
- if ((info->nMin > info->nMax) ||
- ((UINT)(info->nMax - info->nMin) >= 0x80000000))
- {
- action |= SA_SSI_REFRESH;
- infoPtr->minVal = 0;
- infoPtr->maxVal = 0;
- }
- else
- {
- if( infoPtr->minVal != info->nMin ||
- infoPtr->maxVal != info->nMax )
- {
- action |= SA_SSI_REFRESH;
- infoPtr->minVal = info->nMin;
- infoPtr->maxVal = info->nMax;
- }
- }
- }
-
- /* Make sure the page size is valid */
- if (infoPtr->page < 0) infoPtr->page = 0;
- else if (infoPtr->page > infoPtr->maxVal - infoPtr->minVal + 1 )
- infoPtr->page = infoPtr->maxVal - infoPtr->minVal + 1;
-
- /* Make sure the pos is inside the range */
-
- if (infoPtr->curVal < infoPtr->minVal)
- infoPtr->curVal = infoPtr->minVal;
- else if (infoPtr->curVal > infoPtr->maxVal - max( infoPtr->page-1, 0 ))
- infoPtr->curVal = infoPtr->maxVal - max( infoPtr->page-1, 0 );
-
- TRACE(" new values: page=%d pos=%d min=%d max=%d\n",
- infoPtr->page, infoPtr->curVal,
- infoPtr->minVal, infoPtr->maxVal );
-
- /* don't change the scrollbar state if SetScrollInfo
- * is just called with SIF_DISABLENOSCROLL
- */
- if(!(info->fMask & SIF_ALL)) goto done;
-
- /* Check if the scrollbar should be hidden or disabled */
-
- if (info->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
- {
- new_flags = infoPtr->flags;
- if (infoPtr->minVal >= infoPtr->maxVal - max( infoPtr->page-1, 0 ))
- {
- /* Hide or disable scroll-bar */
- if (info->fMask & SIF_DISABLENOSCROLL)
- {
- new_flags = ESB_DISABLE_BOTH;
- action |= SA_SSI_REFRESH;
- }
- else if ((nBar != SB_CTL) && (action & SA_SSI_REFRESH))
- {
- action = SA_SSI_HIDE;
- }
- }
- else /* Show and enable scroll-bar only if no page only changed. */
- if (info->fMask != SIF_PAGE)
- {
- new_flags = ESB_ENABLE_BOTH;
- if ((nBar != SB_CTL) && ( (action & SA_SSI_REFRESH) ))
- action |= SA_SSI_SHOW;
- }
-
- if (nBar == SB_CTL && bRedraw && IsWindowVisible(hwnd) &&
- (new_flags == ESB_ENABLE_BOTH || new_flags == ESB_DISABLE_BOTH))
- {
- EnableWindow(hwnd, new_flags == ESB_ENABLE_BOTH);
- }
-
- if (infoPtr->flags != new_flags) /* check arrow flags */
- {
- infoPtr->flags = new_flags;
- action |= SA_SSI_REPAINT_ARROWS;
- }
- }
-
-done:
- if( action & SA_SSI_HIDE )
- SCROLL_ShowScrollBar( hwnd, nBar, FALSE, FALSE );
- else
- {
- if( action & SA_SSI_SHOW )
- if( SCROLL_ShowScrollBar( hwnd, nBar, TRUE, TRUE ) )
- return infoPtr->curVal; /* SetWindowPos() already did the painting */
-
- if( bRedraw )
- SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
- else if( action & SA_SSI_REPAINT_ARROWS )
- SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, FALSE );
- }
-
- /* Return current position */
- return infoPtr->curVal;
-}
-
/*************************************************************************
* GetScrollInfo (USER32.@)
@@ -1678,33 +503,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetScrollInfo(HWND hwnd, INT nBar, LPSCROLLINFO in
SendMessageW(hwnd, SBM_GETSCROLLINFO, 0, (LPARAM)info);
return TRUE;
}
- return SCROLL_GetScrollInfo(hwnd, nBar, info);
-}
-
-
-/*************************************************************************
- * GetScrollBarInfo (USER32.@)
- *
- * GetScrollBarInfo can be used to retrieve information about a scrollbar
- * control.
- *
- * PARAMS
- * hwnd [I] Handle of window with scrollbar(s)
- * idObject [I] One of OBJID_CLIENT, OBJID_HSCROLL, or OBJID_VSCROLL
- * info [IO] cbSize specifies the size of SCROLLBARINFO
- *
- * RETURNS
- * TRUE if success
- */
-BOOL WINAPI GetScrollBarInfo(HWND hwnd, LONG idObject, LPSCROLLBARINFO info)
-{
- TRACE("hwnd=%p idObject=%ld info=%p\n", hwnd, idObject, info);
-
- /* Refer OBJID_CLIENT requests to the window */
- if (idObject == OBJID_CLIENT)
- return SendMessageW(hwnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)info);
- else
- return SCROLL_GetScrollBarInfo(hwnd, idObject, info);
+ return NtUserGetScrollInfo( hwnd, nBar, info );
}
@@ -1737,7 +536,7 @@ INT WINAPI DECLSPEC_HOTPATCH SetScrollPos( HWND hwnd, INT nBar, INT nPos, BOOL b
info.cbSize = sizeof(info);
info.nPos = nPos;
info.fMask = SIF_POS;
- SetScrollInfo( hwnd, nBar, &info, bRedraw );
+ NtUserSetScrollInfo( hwnd, nBar, &info, bRedraw );
return oldPos;
}
@@ -1799,7 +598,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetScrollRange(HWND hwnd, INT nBar, INT minVal, IN
info.fMask = SIF_RANGE;
info.nMin = minVal;
info.nMax = maxVal;
- SetScrollInfo( hwnd, nBar, &info, bRedraw );
+ NtUserSetScrollInfo( hwnd, nBar, &info, bRedraw );
return TRUE;
}
@@ -1830,84 +629,3 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetScrollRange(HWND hwnd, INT nBar, LPINT lpMin, L
return TRUE;
}
-
-
-/*************************************************************************
- * SCROLL_ShowScrollBar()
- *
- * Back-end for ShowScrollBar(). Returns FALSE if no action was taken.
- */
-static BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, BOOL fShowH, BOOL fShowV )
-{
- ULONG old_style, set_bits = 0, clear_bits = 0;
-
- TRACE("hwnd=%p bar=%d horz=%d, vert=%d\n", hwnd, nBar, fShowH, fShowV );
-
- switch(nBar)
- {
- case SB_CTL:
- NtUserShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE );
- return TRUE;
-
- case SB_BOTH:
- case SB_HORZ:
- if (fShowH) set_bits |= WS_HSCROLL;
- else clear_bits |= WS_HSCROLL;
- if( nBar == SB_HORZ ) break;
- /* fall through */
- case SB_VERT:
- if (fShowV) set_bits |= WS_VSCROLL;
- else clear_bits |= WS_VSCROLL;
- break;
-
- default:
- return FALSE; /* Nothing to do! */
- }
-
- old_style = WIN_SetStyle( hwnd, set_bits, clear_bits );
- if ((old_style & clear_bits) != 0 || (old_style & set_bits) != set_bits)
- {
- /* frame has been changed, let the window redraw itself */
- NtUserSetWindowPos( hwnd, 0, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
- return TRUE;
- }
- return FALSE; /* no frame changes */
-}
-
-
-/*************************************************************************
- * EnableScrollBar (USER32.@)
- *
- * Enables or disables the scroll bars.
- */
-BOOL WINAPI DECLSPEC_HOTPATCH EnableScrollBar( HWND hwnd, UINT nBar, UINT flags )
-{
- BOOL bFineWithMe;
- SCROLLBAR_INFO *infoPtr;
-
- flags &= ESB_DISABLE_BOTH;
-
- if (nBar == SB_BOTH)
- {
- if (!(infoPtr = SCROLL_GetInternalInfo( hwnd, SB_VERT, TRUE ))) return FALSE;
- if (!(bFineWithMe = (infoPtr->flags == flags)) )
- {
- infoPtr->flags = flags;
- SCROLL_RefreshScrollBar( hwnd, SB_VERT, TRUE, TRUE );
- }
- nBar = SB_HORZ;
- }
- else
- bFineWithMe = nBar != SB_CTL;
-
- if (!(infoPtr = SCROLL_GetInternalInfo( hwnd, nBar, TRUE ))) return FALSE;
- if (bFineWithMe && infoPtr->flags == flags) return FALSE;
- infoPtr->flags = flags;
-
- if (nBar == SB_CTL && (flags == ESB_DISABLE_BOTH || flags == ESB_ENABLE_BOTH))
- EnableWindow(hwnd, flags == ESB_ENABLE_BOTH);
-
- SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
- return TRUE;
-}
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index ce8365b1336..800dc4a9240 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -206,7 +206,7 @@
@ stdcall EnableMenuItem(long long long) NtUserEnableMenuItem
@ stdcall EnableMouseInPointer(long)
@ stdcall EnableNonClientDpiScaling(long)
-@ stdcall EnableScrollBar(long long long)
+@ stdcall -import EnableScrollBar(long long long) NtUserEnableScrollBar
@ stdcall EnableWindow(long long)
@ stdcall EndDeferWindowPos(long)
@ stdcall EndDialog(long long)
@@ -373,7 +373,7 @@
@ stdcall GetRawInputDeviceList(ptr ptr long) NtUserGetRawInputDeviceList
# @ stub GetReasonTitleFromReasonCode
@ stdcall GetRegisteredRawInputDevices(ptr ptr long) NtUserGetRegisteredRawInputDevices
-@ stdcall GetScrollBarInfo(long long ptr)
+@ stdcall GetScrollBarInfo(long long ptr) NtUserGetScrollBarInfo
@ stdcall GetScrollInfo(long long ptr)
@ stdcall GetScrollPos(long long)
@ stdcall GetScrollRange(long long ptr ptr)
@@ -699,7 +699,7 @@
@ stdcall SetPropW(long wstr long)
@ stdcall SetRect(ptr long long long long)
@ stdcall SetRectEmpty(ptr)
-@ stdcall SetScrollInfo(long long ptr long)
+@ stdcall -import SetScrollInfo(long long ptr long) NtUserSetScrollInfo
@ stdcall SetScrollPos(long long long long)
@ stdcall SetScrollRange(long long long long long)
@ stdcall SetShellWindow(long)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 7a85a86d786..b6c8f26cec6 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -157,7 +157,6 @@ static const struct user_callbacks user_funcs =
ImmProcessKey,
ImmTranslateMessage,
NtWaitForMultipleObjects,
- SCROLL_DrawNCScrollBar,
free_win_ptr,
SCROLL_GetInternalInfo,
notify_ime,
@@ -174,6 +173,16 @@ static NTSTATUS WINAPI User32CopyImage( const struct copy_image_params *params,
return HandleToUlong( ret );
}
+static NTSTATUS WINAPI User32DrawScrollBar( const struct draw_scroll_bar_params *params, ULONG size )
+{
+ RECT rect = params->rect;
+ user_api->pScrollBarDraw( params->hwnd, params->hdc, params->bar, params->hit_test,
+ ¶ms->tracking_info, params->arrows, params->interior,
+ &rect, params->arrow_size, params->thumb_pos,
+ params->thumb_size, params->vertical );
+ return 0;
+}
+
static NTSTATUS WINAPI User32DrawText( const struct draw_text_params *params, ULONG size )
{
size -= FIELD_OFFSET( struct draw_text_params, str );
@@ -220,6 +229,7 @@ static const void *kernel_callback_table[NtUserCallCount] =
User32CallWindowProc,
User32CallWindowsHook,
User32CopyImage,
+ User32DrawScrollBar,
User32DrawText,
User32FreeCachedClipboardData,
User32LoadDriver,
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index d1b25da0e68..8b5033ad821 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -1182,20 +1182,6 @@ BOOL WINAPI IsWindowVisible( HWND hwnd )
}
-/***********************************************************************
- * WIN_IsWindowDrawable
- *
- * hwnd is drawable when it is visible, all parents are not
- * minimized, and it is itself not minimized unless we are
- * trying to draw its default class icon.
- */
-BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
-{
- /* FIXME: move callers to win32u */
- return NtUserCallHwndParam( hwnd, icon, NtUserIsWindowDrawable );
-}
-
-
/*******************************************************************
* GetTopWindow (USER32.@)
*/
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
index 59a7e0e2e38..8ef090fe983 100644
--- a/dlls/user32/win.h
+++ b/dlls/user32/win.h
@@ -44,7 +44,6 @@ extern HWND WIN_IsCurrentThread( HWND hwnd ) DECLSPEC_HIDDEN;
extern ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPEC_HIDDEN;
extern BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient ) DECLSPEC_HIDDEN;
extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN;
-extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN;
extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN;
extern void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id ) DECLSPEC_HIDDEN;
extern HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c
index af51b933d49..702673e0cdd 100644
--- a/dlls/win32u/defwnd.c
+++ b/dlls/win32u/defwnd.c
@@ -922,6 +922,28 @@ static void sys_command_size_move( HWND hwnd, WPARAM wparam )
}
}
+/***********************************************************************
+ * track_nc_scroll_bar
+ *
+ * Track a mouse button press on the horizontal or vertical scroll-bar.
+ */
+static void track_nc_scroll_bar( HWND hwnd, WPARAM wparam, POINT pt )
+{
+ int scrollbar;
+
+ if ((wparam & 0xfff0) == SC_HSCROLL)
+ {
+ if ((wparam & 0x0f) != HTHSCROLL) return;
+ scrollbar = SB_HORZ;
+ }
+ else /* SC_VSCROLL */
+ {
+ if ((wparam & 0x0f) != HTVSCROLL) return;
+ scrollbar = SB_VERT;
+ }
+ track_scroll_bar( hwnd, scrollbar, pt );
+}
+
static LRESULT handle_sys_command( HWND hwnd, WPARAM wparam, LPARAM lparam )
{
TRACE( "hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wparam, lparam );
@@ -956,7 +978,13 @@ static LRESULT handle_sys_command( HWND hwnd, WPARAM wparam, LPARAM lparam )
case SC_VSCROLL:
case SC_HSCROLL:
- return 1; /* FIXME: handle on client side */
+ {
+ POINT pt;
+ pt.x = (short)LOWORD( lparam );
+ pt.y = (short)HIWORD( lparam );
+ track_nc_scroll_bar( hwnd, wparam, pt );
+ }
+ break;
case SC_MOUSEMENU:
track_mouse_menu_bar( hwnd, wparam & 0x000F, (short)LOWORD(lparam), (short)HIWORD(lparam) );
@@ -1736,8 +1764,7 @@ static void nc_paint( HWND hwnd, HRGN clip )
draw_rect_edge( hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST, 1 );
/* Draw the scroll-bars */
- if (user_callbacks)
- user_callbacks->draw_nc_scrollbar( hwnd, hdc, style & WS_HSCROLL, style & WS_VSCROLL );
+ draw_nc_scrollbar( hwnd, hdc, style & WS_HSCROLL, style & WS_VSCROLL );
/* Draw the "size-box" */
if ((style & WS_VSCROLL) && (style & WS_HSCROLL))
@@ -2295,6 +2322,42 @@ static HBRUSH handle_control_color( HDC hdc, UINT type )
return get_sys_color_brush( COLOR_WINDOW );
}
+static LRESULT handle_nc_mouse_move( HWND hwnd, WPARAM wparam, LPARAM lparam )
+{
+ RECT rect;
+ POINT pt;
+
+ TRACE( "hwnd=%p wparam=%#lx lparam=%#lx\n", hwnd, wparam, lparam );
+
+ if (wparam != HTHSCROLL && wparam != HTVSCROLL)
+ return 0;
+
+ get_window_rects( hwnd, COORDS_CLIENT, &rect, NULL, get_thread_dpi() );
+
+ pt.x = (short)LOWORD( lparam );
+ pt.y = (short)HIWORD( lparam );
+ screen_to_client( hwnd, &pt );
+ pt.x -= rect.left;
+ pt.y -= rect.top;
+ handle_scroll_event( hwnd, wparam == HTHSCROLL ? SB_HORZ : SB_VERT, WM_NCMOUSEMOVE, pt );
+ return 0;
+}
+
+static LRESULT handle_nc_mouse_leave( HWND hwnd )
+{
+ LONG style = get_window_long( hwnd, GWL_STYLE );
+ POINT pt = {0, 0};
+
+ TRACE( "hwnd=%p\n", hwnd );
+
+ if (style & WS_HSCROLL)
+ handle_scroll_event( hwnd, SB_HORZ, WM_NCMOUSELEAVE, pt );
+ if (style & WS_VSCROLL)
+ handle_scroll_event( hwnd, SB_VERT, WM_NCMOUSELEAVE, pt );
+ return 0;
+}
+
+
LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi )
{
LRESULT result = 0;
@@ -2352,6 +2415,14 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
case WM_NCLBUTTONDBLCLK:
return handle_nc_button_dbl_click( hwnd, wparam, lparam );
+ case WM_NCMOUSEMOVE:
+ result = handle_nc_mouse_move( hwnd, wparam, lparam );
+ break;
+
+ case WM_NCMOUSELEAVE:
+ result = handle_nc_mouse_leave( hwnd );
+ break;
+
case WM_RBUTTONUP:
{
POINT pt;
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index d843716e4c0..9aab651e551 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1164,6 +1164,7 @@ static struct unix_funcs unix_funcs =
NtUserDrawMenuBarTemp,
NtUserEmptyClipboard,
NtUserEnableMenuItem,
+ NtUserEnableScrollBar,
NtUserEndDeferWindowPosEx,
NtUserEndPaint,
NtUserEnumDisplayDevices,
@@ -1184,6 +1185,7 @@ static struct unix_funcs unix_funcs =
NtUserGetMessage,
NtUserGetPriorityClipboardFormat,
NtUserGetQueueStatus,
+ NtUserGetScrollBarInfo,
NtUserGetSystemMenu,
NtUserGetUpdateRect,
NtUserGetUpdateRgn,
@@ -1226,6 +1228,7 @@ static struct unix_funcs unix_funcs =
NtUserSetLayeredWindowAttributes,
NtUserSetMenu,
NtUserSetParent,
+ NtUserSetScrollInfo,
NtUserSetSysColors,
NtUserSetSystemMenu,
NtUserSetWindowLong,
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index 36c11a49c4e..b2765a70a3d 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -35,7 +35,6 @@ struct user_callbacks
BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD);
BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM);
NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
- void (CDECL *draw_nc_scrollbar)( HWND hwnd, HDC hdc, BOOL draw_horizontal, BOOL draw_vertical );
void (CDECL *free_win_ptr)( struct tagWND *win );
struct scroll_info *(CDECL *get_scroll_info)( HWND hwnd, INT nBar, BOOL alloc );
void (CDECL *notify_ime)( HWND hwnd, UINT param );
diff --git a/dlls/win32u/scroll.c b/dlls/win32u/scroll.c
index 14bec1e3b83..a51c7d3cf93 100644
--- a/dlls/win32u/scroll.c
+++ b/dlls/win32u/scroll.c
@@ -23,7 +23,7 @@
#pragma makedep unix
#endif
-#include "win32u_private.h"
+#include "ntgdi_private.h"
#include "ntuser_private.h"
#include "wine/debug.h"
@@ -41,6 +41,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(scroll);
/* Overlap between arrows and thumb */
#define SCROLL_ARROW_THUMB_OVERLAP 0
+/* Delay (in ms) before first repetition when holding the button down */
+#define SCROLL_FIRST_DELAY 200
+
+/* Delay (in ms) between scroll repetitions */
+#define SCROLL_REPEAT_DELAY 50
+
+/* Scroll timer id */
+#define SCROLL_TIMER 0
+
+/* What to do after set_scroll_info() */
+#define SA_SSI_HIDE 0x0001
+#define SA_SSI_SHOW 0x0002
+#define SA_SSI_REFRESH 0x0004
+#define SA_SSI_REPAINT_ARROWS 0x0008
+
+/* Scroll Bar tracking information */
+static struct SCROLL_TRACKING_INFO g_tracking_info;
+
+/* Is the moving thumb being displayed? */
+static BOOL scroll_moving_thumb = FALSE;
+
static struct scroll_info *get_scroll_info_ptr( HWND hwnd, int bar, BOOL alloc )
{
struct scroll_info *ret = NULL;
@@ -200,6 +221,856 @@ static BOOL get_scroll_bar_rect( HWND hwnd, int bar, RECT *rect, int *arrow_size
return vertical;
}
+/***********************************************************************
+ * draw_scroll_bar
+ *
+ * Redraw the whole scrollbar.
+ */
+void draw_scroll_bar( HWND hwnd, HDC hdc, int bar, enum SCROLL_HITTEST hit_test,
+ const struct SCROLL_TRACKING_INFO *tracking_info, BOOL draw_arrows,
+ BOOL draw_interior )
+{
+ struct draw_scroll_bar_params params;
+ struct scroll_info *info;
+ RECT clip_box, intersect;
+ DWORD style;
+ void *ret_ptr;
+ ULONG ret_len;
+
+ if (!(hwnd = get_full_window_handle( hwnd )))
+ return;
+
+ style = get_window_long( hwnd, GWL_STYLE );
+ if ((bar == SB_VERT && !(style & WS_VSCROLL)) || (bar == SB_HORZ && !(style & WS_HSCROLL)))
+ return;
+
+ if (!is_window_drawable( hwnd, FALSE ))
+ return;
+
+ if (!(info = get_scroll_info_ptr( hwnd, bar, TRUE ))) return;
+ params.enable_flags = info->flags;
+ release_scroll_info_ptr( info );
+
+ if (bar == SB_CTL && get_window_long( hwnd, GWL_STYLE ) & (SBS_SIZEGRIP | SBS_SIZEBOX))
+ {
+ get_client_rect( hwnd, ¶ms.rect );
+ params.arrow_size = 0;
+ params.thumb_pos = 0;
+ params.thumb_size = 0;
+ params.vertical = FALSE;
+ }
+ else
+ {
+ int pos, max_size;
+
+ params.vertical = get_scroll_bar_rect( hwnd, bar, ¶ms.rect, ¶ms.arrow_size,
+ ¶ms.thumb_size, ¶ms.thumb_pos );
+
+ if (scroll_moving_thumb && tracking_info->win == hwnd && tracking_info->bar == bar)
+ {
+ max_size = params.vertical ?
+ params.rect.bottom - params.rect.top : params.rect.right - params.rect.left;
+ max_size -= params.arrow_size - SCROLL_ARROW_THUMB_OVERLAP + params.thumb_size;
+
+ pos = tracking_info->thumb_pos;
+ if (pos < params.arrow_size - SCROLL_ARROW_THUMB_OVERLAP)
+ pos = params.arrow_size - SCROLL_ARROW_THUMB_OVERLAP;
+ else if (pos > max_size)
+ pos = max_size;
+
+ params.thumb_pos = pos;
+ }
+ }
+
+ /* do not draw if the scrollbar rectangle is empty */
+ if (IsRectEmpty( ¶ms.rect ))
+ return;
+
+ TRACE( "hwnd %p, hdc %p, bar %d, hit_test %d, tracking_info(win %p, bar %d, thumb_pos %d, "
+ "track_pos %d, vertical %d, hit_test %d), draw_arrows %d, draw_interior %d, rect %s, "
+ "arrow_size %d, thumb_pos %d, thumb_val %d, vertical %d, captured window %p\n", hwnd, hdc,
+ bar, hit_test, tracking_info->win, tracking_info->bar, tracking_info->thumb_pos,
+ tracking_info->thumb_val, tracking_info->vertical, tracking_info->hit_test, draw_arrows,
+ draw_interior, wine_dbgstr_rect(¶ms.rect), params.arrow_size, params.thumb_pos,
+ params.thumb_size, params.vertical, get_capture() );
+
+ params.hwnd = hwnd;
+ params.hdc = hdc;
+ params.bar = bar;
+ params.hit_test = hit_test;
+ params.arrows = draw_arrows;
+ params.interior = draw_interior;
+ KeUserModeCallback( NtUserDrawScrollBar, ¶ms, sizeof(params), &ret_ptr, &ret_len );
+
+ if (bar == SB_HORZ || bar == SB_VERT)
+ {
+ NtGdiGetAppClipBox( hdc, &clip_box );
+ if (intersect_rect( &intersect, ¶ms.rect, &clip_box ))
+ set_standard_scroll_painted( hwnd, bar, TRUE );
+ }
+}
+
+void draw_nc_scrollbar( HWND hwnd, HDC hdc, BOOL draw_horizontal, BOOL draw_vertical )
+{
+ if (draw_horizontal)
+ draw_scroll_bar( hwnd, hdc, SB_HORZ, g_tracking_info.hit_test, &g_tracking_info, TRUE, TRUE );
+ if (draw_vertical)
+ draw_scroll_bar( hwnd, hdc, SB_VERT, g_tracking_info.hit_test, &g_tracking_info, TRUE, TRUE );
+}
+
+static void refresh_scroll_bar( HWND hwnd, int nBar, BOOL arrows, BOOL interior )
+{
+ HDC hdc = NtUserGetDCEx( hwnd, 0, DCX_CACHE | (nBar == SB_CTL ? 0 : DCX_WINDOW) );
+ if (!hdc) return;
+
+ draw_scroll_bar( hwnd, hdc, nBar, g_tracking_info.hit_test, &g_tracking_info, arrows, interior );
+ NtUserReleaseDC( hwnd, hdc );
+}
+
+static BOOL point_in_scroll_rect( RECT *r, POINT pt, BOOL vertical )
+{
+ RECT rect = *r;
+ int width;
+
+ /* Pad hit rect to allow mouse to be dragged outside of scrollbar and
+ * still be considered in the scrollbar. */
+ if (vertical)
+ {
+ width = r->right - r->left;
+ InflateRect( &rect, width * 8, width * 2 );
+ }
+ else
+ {
+ width = r->bottom - r->top;
+ InflateRect( &rect, width * 2, width * 8 );
+ }
+ return PtInRect( &rect, pt );
+}
+
+/***********************************************************************
+ * scroll_hit_test
+ *
+ * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
+ */
+static enum SCROLL_HITTEST scroll_hit_test( HWND hwnd, int bar, POINT pt, BOOL dragging )
+{
+ int arrow_size, thumb_size, thumb_pos;
+ BOOL vertical;
+ RECT rect;
+
+ vertical = get_scroll_bar_rect( hwnd, bar, &rect, &arrow_size, &thumb_size, &thumb_pos );
+
+ if ((dragging && !point_in_scroll_rect( &rect, pt, vertical )) || !PtInRect( &rect, pt ))
+ return SCROLL_NOWHERE;
+
+ if (vertical)
+ {
+ if (pt.y < rect.top + arrow_size) return SCROLL_TOP_ARROW;
+ if (pt.y >= rect.bottom - arrow_size) return SCROLL_BOTTOM_ARROW;
+ if (!thumb_pos) return SCROLL_TOP_RECT;
+ pt.y -= rect.top;
+ if (pt.y < thumb_pos) return SCROLL_TOP_RECT;
+ if (pt.y >= thumb_pos + thumb_size) return SCROLL_BOTTOM_RECT;
+ }
+ else /* horizontal */
+ {
+ if (pt.x < rect.left + arrow_size) return SCROLL_TOP_ARROW;
+ if (pt.x >= rect.right - arrow_size) return SCROLL_BOTTOM_ARROW;
+ if (!thumb_pos) return SCROLL_TOP_RECT;
+ pt.x -= rect.left;
+ if (pt.x < thumb_pos) return SCROLL_TOP_RECT;
+ if (pt.x >= thumb_pos + thumb_size) return SCROLL_BOTTOM_RECT;
+ }
+ return SCROLL_THUMB;
+}
+
+static BOOL is_standard_scroll_painted( HWND hwnd, int bar )
+{
+ struct scroll_info *info;
+ BOOL ret;
+
+ if (bar != SB_HORZ && bar != SB_VERT) return FALSE;
+ if (!(info = get_scroll_info_ptr( hwnd, bar, FALSE ))) return FALSE;
+ ret = info->painted;
+ release_scroll_info_ptr( info );
+ return ret;
+}
+
+/***********************************************************************
+ * get_thumb_val
+ *
+ * Compute the current scroll position based on the thumb position in pixels
+ * from the top of the scroll-bar.
+ */
+static UINT get_thumb_val( HWND hwnd, int bar, RECT *rect, BOOL vertical, int pos )
+{
+ int thumb_size, min_thumb_size, pixels, range;
+ struct scroll_info *info;
+ UINT ret;
+
+ pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
+ pixels -= 2 * (get_system_metrics( SM_CXVSCROLL ) - SCROLL_ARROW_THUMB_OVERLAP);
+ if (!(info = get_scroll_info_ptr( hwnd, bar, FALSE ))) return 0;
+ ret = info->minVal;
+ if (pixels > 0)
+ {
+ if (info->page)
+ {
+ thumb_size = muldiv( pixels, info->page, info->maxVal - info->minVal + 1 );
+ min_thumb_size = muldiv( SCROLL_MIN_THUMB, get_dpi_for_window( hwnd ), 96 );
+ if (thumb_size < min_thumb_size) thumb_size = min_thumb_size;
+ }
+ else thumb_size = get_system_metrics( SM_CXVSCROLL );
+
+ if ((pixels -= thumb_size) > 0)
+ {
+ pos = max( 0, pos - (get_system_metrics( SM_CXVSCROLL ) - SCROLL_ARROW_THUMB_OVERLAP ));
+ if (pos > pixels) pos = pixels;
+
+ if (!info->page)
+ range = info->maxVal - info->minVal;
+ else
+ range = info->maxVal - info->minVal - info->page + 1;
+
+ ret = info->minVal + muldiv( pos, range, pixels );
+ }
+ }
+
+ release_scroll_info_ptr( info );
+ return ret;
+}
+
+static POINT clip_scroll_pos( RECT *rect, POINT pt )
+{
+ if (pt.x < rect->left)
+ pt.x = rect->left;
+ else if (pt.x > rect->right)
+ pt.x = rect->right;
+
+ if (pt.y < rect->top)
+ pt.y = rect->top;
+ else if (pt.y > rect->bottom)
+ pt.y = rect->bottom;
+
+ return pt;
+}
+
+/***********************************************************************
+ * handle_scroll_event
+ *
+ * Handle a mouse or timer event for the scrollbar.
+ * 'pt' is the location of the mouse event in client (for SB_CTL) or
+ * windows coordinates.
+ */
+void handle_scroll_event( HWND hwnd, int bar, UINT msg, POINT pt )
+{
+ /* Previous mouse position for timer events. */
+ static POINT prev_pt;
+ /* Thumb position when tracking started. */
+ static UINT track_thumb_pos;
+ /* Position in the scroll-bar of the last button-down event. */
+ static int last_click_pos;
+ /* Position in the scroll-bar of the last mouse event. */
+ static int last_mouse_pos;
+
+ int arrow_size, thumb_size, thumb_pos;
+ enum SCROLL_HITTEST hittest;
+ HWND owner_hwnd, ctl_hwnd;
+ struct scroll_info *info;
+ TRACKMOUSEEVENT tme;
+ BOOL vertical;
+ RECT rect;
+ HDC hdc;
+
+ if (!(info = get_scroll_info_ptr( hwnd, bar, FALSE ))) return;
+ release_scroll_info_ptr( info );
+
+ if (g_tracking_info.hit_test == SCROLL_NOWHERE &&
+ (msg != WM_LBUTTONDOWN && msg != WM_MOUSEMOVE && msg != WM_MOUSELEAVE &&
+ msg != WM_NCMOUSEMOVE && msg != WM_NCMOUSELEAVE))
+ return;
+
+ if (bar == SB_CTL && (get_window_long( hwnd, GWL_STYLE ) & (SBS_SIZEGRIP | SBS_SIZEBOX)))
+ {
+ switch (msg)
+ {
+ case WM_LBUTTONDOWN: /* Initialise mouse tracking */
+ NtUserHideCaret( hwnd ); /* hide caret while holding down LBUTTON */
+ NtUserSetCapture( hwnd );
+ prev_pt = pt;
+ g_tracking_info.hit_test = hittest = SCROLL_THUMB;
+ break;
+ case WM_MOUSEMOVE:
+ get_client_rect( get_parent( get_parent( hwnd )), &rect );
+ prev_pt = pt;
+ break;
+ case WM_LBUTTONUP:
+ release_capture();
+ g_tracking_info.hit_test = hittest = SCROLL_NOWHERE;
+ if (hwnd == get_focus()) NtUserShowCaret( hwnd );
+ break;
+ case WM_SYSTIMER:
+ pt = prev_pt;
+ break;
+ }
+ return;
+ }
+
+ hdc = NtUserGetDCEx( hwnd, 0, DCX_CACHE | (bar == SB_CTL ? 0 : DCX_WINDOW));
+ vertical = get_scroll_bar_rect( hwnd, bar, &rect, &arrow_size, &thumb_size, &thumb_pos );
+ owner_hwnd = bar == SB_CTL ? get_parent( hwnd ) : hwnd;
+ ctl_hwnd = bar == SB_CTL ? hwnd : 0;
+
+ switch (msg)
+ {
+ case WM_LBUTTONDOWN: /* Initialise mouse tracking */
+ NtUserHideCaret( hwnd ); /* hide caret while holding down LBUTTON */
+ g_tracking_info.vertical = vertical;
+ g_tracking_info.hit_test = hittest = scroll_hit_test( hwnd, bar, pt, FALSE );
+ last_click_pos = vertical ? pt.y - rect.top : pt.x - rect.left;
+ last_mouse_pos = last_click_pos;
+ track_thumb_pos = thumb_pos;
+ prev_pt = pt;
+ if (bar == SB_CTL && (get_window_long( hwnd, GWL_STYLE ) & WS_TABSTOP))
+ NtUserSetFocus( hwnd );
+ NtUserSetCapture( hwnd );
+ break;
+
+ case WM_MOUSEMOVE:
+ hittest = scroll_hit_test( hwnd, bar, pt,
+ vertical == g_tracking_info.vertical && get_capture() == hwnd );
+ prev_pt = pt;
+
+ if (bar != SB_CTL)
+ break;
+
+ tme.cbSize = sizeof(tme);
+ tme.dwFlags = TME_QUERY;
+ NtUserTrackMouseEvent( &tme );
+ if (!(tme.dwFlags & TME_LEAVE) || tme.hwndTrack != hwnd)
+ {
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ NtUserTrackMouseEvent( &tme );
+ }
+ break;
+
+ case WM_NCMOUSEMOVE:
+ hittest = scroll_hit_test( hwnd, bar, pt,
+ vertical == g_tracking_info.vertical && get_capture() == hwnd );
+ prev_pt = pt;
+
+ if (bar == SB_CTL)
+ break;
+
+ tme.cbSize = sizeof(tme);
+ tme.dwFlags = TME_QUERY;
+ NtUserTrackMouseEvent( &tme );
+ if (((tme.dwFlags & (TME_NONCLIENT | TME_LEAVE)) != (TME_NONCLIENT | TME_LEAVE)) ||
+ tme.hwndTrack != hwnd)
+ {
+ tme.dwFlags = TME_NONCLIENT | TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ NtUserTrackMouseEvent( &tme );
+ }
+
+ break;
+
+ case WM_NCMOUSELEAVE:
+ if (bar == SB_CTL)
+ return;
+
+ hittest = SCROLL_NOWHERE;
+ break;
+
+ case WM_MOUSELEAVE:
+ if (bar != SB_CTL)
+ return;
+
+ hittest = SCROLL_NOWHERE;
+ break;
+
+ case WM_LBUTTONUP:
+ hittest = SCROLL_NOWHERE;
+ release_capture();
+ /* if scrollbar has focus, show back caret */
+ if (hwnd == get_focus()) NtUserShowCaret( hwnd );
+ break;
+
+ case WM_SYSTIMER:
+ pt = prev_pt;
+ hittest = scroll_hit_test( hwnd, bar, pt, FALSE );
+ break;
+
+ default:
+ return; /* Should never happen */
+ }
+
+ TRACE( "Event: hwnd=%p bar=%d msg=%s pt=%d,%d hit=%d\n",
+ hwnd, bar, debugstr_msg_name( msg, hwnd ), pt.x, pt.y, hittest );
+
+ switch (g_tracking_info.hit_test)
+ {
+ case SCROLL_NOWHERE: /* No tracking in progress */
+ /* For standard scroll bars, hovered state gets painted only when the scroll bar was
+ * previously painted by DefWinProc(). If an application handles WM_NCPAINT by itself, then
+ * the scrollbar shouldn't be repainted here to avoid overwriting the application painted
+ * content */
+ if (msg == WM_MOUSEMOVE || msg == WM_MOUSELEAVE ||
+ ((msg == WM_NCMOUSEMOVE || msg == WM_NCMOUSELEAVE) &&
+ is_standard_scroll_painted( hwnd, bar )))
+ draw_scroll_bar( hwnd, hdc, bar, hittest, &g_tracking_info, TRUE, TRUE );
+ break;
+
+ case SCROLL_TOP_ARROW:
+ draw_scroll_bar( hwnd, hdc, bar, hittest, &g_tracking_info, TRUE, FALSE );
+ if (hittest == g_tracking_info.hit_test)
+ {
+ if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
+ {
+ send_message( owner_hwnd, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_LINEUP, (LPARAM)ctl_hwnd );
+ }
+
+ NtUserSetSystemTimer( hwnd, SCROLL_TIMER,
+ msg == WM_LBUTTONDOWN ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY );
+ }
+ else NtUserKillSystemTimer( hwnd, SCROLL_TIMER );
+ break;
+
+ case SCROLL_TOP_RECT:
+ draw_scroll_bar( hwnd, hdc, bar, hittest, &g_tracking_info, FALSE, TRUE );
+ if (hittest == g_tracking_info.hit_test)
+ {
+ if (msg == WM_LBUTTONDOWN || msg == WM_SYSTIMER)
+ {
+ send_message( owner_hwnd, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_PAGEUP, (LPARAM)ctl_hwnd );
+ }
+ NtUserSetSystemTimer( hwnd, SCROLL_TIMER,
+ msg == WM_LBUTTONDOWN ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY );
+ }
+ else NtUserKillSystemTimer( hwnd, SCROLL_TIMER );
+ break;
+
+ case SCROLL_THUMB:
+ if (msg == WM_LBUTTONDOWN)
+ {
+ g_tracking_info.win = hwnd;
+ g_tracking_info.bar = bar;
+ g_tracking_info.thumb_pos = track_thumb_pos + last_mouse_pos - last_click_pos;
+ g_tracking_info.thumb_val = get_thumb_val( hwnd, bar, &rect, vertical,
+ g_tracking_info.thumb_pos );
+ if (!scroll_moving_thumb)
+ {
+ scroll_moving_thumb = TRUE;
+ draw_scroll_bar( hwnd, hdc, bar, hittest, &g_tracking_info, FALSE, TRUE );
+ }
+ }
+ else if (msg == WM_LBUTTONUP)
+ {
+ draw_scroll_bar( hwnd, hdc, bar, SCROLL_NOWHERE, &g_tracking_info, FALSE, TRUE );
+ }
+ else if (msg == WM_MOUSEMOVE)
+ {
+ int pos;
+
+ if (!point_in_scroll_rect( &rect, pt, vertical )) pos = last_click_pos;
+ else
+ {
+ pt = clip_scroll_pos( &rect, pt );
+ pos = vertical ? pt.y - rect.top : pt.x - rect.left;
+ }
+ if (pos != last_mouse_pos || !scroll_moving_thumb)
+ {
+ last_mouse_pos = pos;
+ g_tracking_info.thumb_pos = track_thumb_pos + pos - last_click_pos;
+ g_tracking_info.thumb_val = get_thumb_val( hwnd, bar, &rect, vertical,
+ g_tracking_info.thumb_pos );
+ send_message( owner_hwnd, vertical ? WM_VSCROLL : WM_HSCROLL,
+ MAKEWPARAM( SB_THUMBTRACK, g_tracking_info.thumb_val ),
+ (LPARAM)ctl_hwnd );
+ scroll_moving_thumb = TRUE;
+ draw_scroll_bar( hwnd, hdc, bar, hittest, &g_tracking_info, FALSE, TRUE );
+ }
+ }
+ break;
+
+ case SCROLL_BOTTOM_RECT:
+ draw_scroll_bar( hwnd, hdc, bar, hittest, &g_tracking_info, FALSE, TRUE );
+ if (hittest == g_tracking_info.hit_test)
+ {
+ if (msg == WM_LBUTTONDOWN || msg == WM_SYSTIMER)
+ {
+ send_message( owner_hwnd, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_PAGEDOWN, (LPARAM)ctl_hwnd );
+ }
+ NtUserSetSystemTimer( hwnd, SCROLL_TIMER,
+ msg == WM_LBUTTONDOWN ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY );
+ }
+ else NtUserKillSystemTimer( hwnd, SCROLL_TIMER );
+ break;
+
+ case SCROLL_BOTTOM_ARROW:
+ draw_scroll_bar( hwnd, hdc, bar, hittest, &g_tracking_info, TRUE, FALSE );
+ if (hittest == g_tracking_info.hit_test)
+ {
+ if (msg == WM_LBUTTONDOWN || msg == WM_SYSTIMER)
+ {
+ send_message( owner_hwnd, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_LINEDOWN, (LPARAM)ctl_hwnd );
+ }
+
+ NtUserSetSystemTimer( hwnd, SCROLL_TIMER,
+ msg == WM_LBUTTONDOWN ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY );
+ }
+ else NtUserKillSystemTimer( hwnd, SCROLL_TIMER );
+ break;
+ }
+
+ if (msg == WM_LBUTTONDOWN)
+ {
+
+ if (hittest == SCROLL_THUMB)
+ {
+ UINT val = get_thumb_val( hwnd, bar, &rect, vertical,
+ track_thumb_pos + last_mouse_pos - last_click_pos );
+ send_message( owner_hwnd, vertical ? WM_VSCROLL : WM_HSCROLL,
+ MAKEWPARAM( SB_THUMBTRACK, val ), (LPARAM)ctl_hwnd );
+ }
+ }
+
+ if (msg == WM_LBUTTONUP)
+ {
+ hittest = g_tracking_info.hit_test;
+ g_tracking_info.hit_test = SCROLL_NOWHERE; /* Terminate tracking */
+
+ if (hittest == SCROLL_THUMB)
+ {
+ UINT val = get_thumb_val( hwnd, bar, &rect, vertical,
+ track_thumb_pos + last_mouse_pos - last_click_pos );
+ send_message( owner_hwnd, vertical ? WM_VSCROLL : WM_HSCROLL,
+ MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)ctl_hwnd );
+ }
+ /* SB_ENDSCROLL doesn't report thumb position */
+ send_message( owner_hwnd, vertical ? WM_VSCROLL : WM_HSCROLL,
+ SB_ENDSCROLL, (LPARAM)ctl_hwnd );
+
+ /* Terminate tracking */
+ g_tracking_info.win = 0;
+ scroll_moving_thumb = FALSE;
+ hittest = SCROLL_NOWHERE;
+ draw_scroll_bar( hwnd, hdc, bar, hittest, &g_tracking_info, TRUE, TRUE );
+ }
+
+ NtUserReleaseDC( hwnd, hdc );
+}
+
+/***********************************************************************
+ * track_scroll_bar
+ *
+ * Track a mouse button press on a scroll-bar.
+ * pt is in screen-coordinates for non-client scroll bars.
+ */
+void track_scroll_bar( HWND hwnd, int scrollbar, POINT pt )
+{
+ MSG msg;
+ RECT rect;
+
+ if (scrollbar != SB_CTL)
+ {
+ get_window_rects( hwnd, COORDS_CLIENT, &rect, NULL, get_thread_dpi() );
+ screen_to_client( hwnd, &pt );
+ pt.x -= rect.left;
+ pt.y -= rect.top;
+ }
+ else
+ rect.left = rect.top = 0;
+
+ handle_scroll_event( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
+
+ do
+ {
+ if (!NtUserGetMessage( &msg, 0, 0, 0 )) break;
+ if (NtUserCallMsgFilter( &msg, MSGF_SCROLLBAR )) continue;
+ if (msg.message == WM_LBUTTONUP ||
+ msg.message == WM_MOUSEMOVE ||
+ msg.message == WM_MOUSELEAVE ||
+ msg.message == WM_NCMOUSEMOVE ||
+ msg.message == WM_NCMOUSELEAVE ||
+ (msg.message == WM_SYSTIMER && msg.wParam == SCROLL_TIMER))
+ {
+ pt.x = (short)LOWORD( msg.lParam ) - rect.left;
+ pt.y = (short)HIWORD( msg.lParam ) - rect.top;
+ handle_scroll_event( hwnd, scrollbar, msg.message, pt );
+ }
+ else
+ {
+ NtUserTranslateMessage( &msg, 0 );
+ NtUserDispatchMessage( &msg );
+ }
+ if (!is_window( hwnd ))
+ {
+ release_capture();
+ break;
+ }
+ } while (msg.message != WM_LBUTTONUP && get_capture() == hwnd);
+}
+
+/***********************************************************************
+ * validate_scroll_info
+ *
+ * Determine if the supplied SCROLLINFO struct is valid.
+ */
+static inline BOOL validate_scroll_info( const SCROLLINFO *info )
+{
+ return !(info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL) ||
+ (info->cbSize != sizeof(*info) &&
+ info->cbSize != sizeof(*info) - sizeof(info->nTrackPos)));
+}
+
+
+BOOL get_scroll_info( HWND hwnd, int bar, SCROLLINFO *info )
+{
+ struct scroll_info *scroll;
+
+ /* handle invalid data structure */
+ if (!validate_scroll_info( info ) || !(scroll = get_scroll_info_ptr( hwnd, bar, FALSE )))
+ return FALSE;
+
+ /* fill in the desired scroll info structure */
+ if (info->fMask & SIF_PAGE) info->nPage = scroll->page;
+ if (info->fMask & SIF_POS) info->nPos = scroll->curVal;
+ if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info)))
+ info->nTrackPos = g_tracking_info.win == get_full_window_handle( hwnd ) ?
+ g_tracking_info.thumb_val : scroll->curVal;
+ if (info->fMask & SIF_RANGE)
+ {
+ info->nMin = scroll->minVal;
+ info->nMax = scroll->maxVal;
+ }
+ release_scroll_info_ptr( scroll );
+
+ TRACE( "cbSize %02x fMask %04x nMin %d nMax %d nPage %u nPos %d nTrackPos %d\n",
+ info->cbSize, info->fMask, info->nMin, info->nMax, info->nPage,
+ info->nPos, info->nTrackPos );
+
+ return (info->fMask & SIF_ALL) != 0;
+}
+
+static int set_scroll_info( HWND hwnd, int bar, const SCROLLINFO *info, BOOL redraw )
+{
+ struct scroll_info *scroll;
+ UINT new_flags;
+ int action = 0, ret;
+
+ /* handle invalid data structure */
+ if (!validate_scroll_info( info ) ||
+ !(scroll = get_scroll_info_ptr( hwnd, bar, TRUE )))
+ return 0;
+
+ if (TRACE_ON(scroll))
+ {
+ TRACE( "hwnd=%p bar=%d", hwnd, bar );
+ if (info->fMask & SIF_PAGE) TRACE( " page=%d", info->nPage );
+ if (info->fMask & SIF_POS) TRACE( " pos=%d", info->nPos );
+ if (info->fMask & SIF_RANGE) TRACE( " min=%d max=%d", info->nMin, info->nMax );
+ TRACE( "\n" );
+ }
+
+ /* Set the page size */
+ if ((info->fMask & SIF_PAGE) && scroll->page != info->nPage)
+ {
+ scroll->page = info->nPage;
+ action |= SA_SSI_REFRESH;
+ }
+
+ /* Set the scroll pos */
+ if ((info->fMask & SIF_POS) && scroll->curVal != info->nPos)
+ {
+ scroll->curVal = info->nPos;
+ action |= SA_SSI_REFRESH;
+ }
+
+ /* Set the scroll range */
+ if (info->fMask & SIF_RANGE)
+ {
+ /* Invalid range -> range is set to (0,0) */
+ if (info->nMin > info->nMax || (UINT)(info->nMax - info->nMin) >= 0x80000000)
+ {
+ action |= SA_SSI_REFRESH;
+ scroll->minVal = 0;
+ scroll->maxVal = 0;
+ }
+ else
+ {
+ if (scroll->minVal != info->nMin || scroll->maxVal != info->nMax)
+ {
+ action |= SA_SSI_REFRESH;
+ scroll->minVal = info->nMin;
+ scroll->maxVal = info->nMax;
+ }
+ }
+ }
+
+ /* Make sure the page size is valid */
+ if (scroll->page < 0) scroll->page = 0;
+ else if (scroll->page > scroll->maxVal - scroll->minVal + 1)
+ scroll->page = scroll->maxVal - scroll->minVal + 1;
+
+ /* Make sure the pos is inside the range */
+ if (scroll->curVal < scroll->minVal)
+ scroll->curVal = scroll->minVal;
+ else if (scroll->curVal > scroll->maxVal - max( scroll->page - 1, 0 ))
+ scroll->curVal = scroll->maxVal - max( scroll->page - 1, 0 );
+
+ TRACE( " new values: page=%d pos=%d min=%d max=%d\n", scroll->page, scroll->curVal,
+ scroll->minVal, scroll->maxVal );
+
+ /* don't change the scrollbar state if SetScrollInfo is just called with SIF_DISABLENOSCROLL */
+ if(!(info->fMask & SIF_ALL)) goto done;
+
+ /* Check if the scrollbar should be hidden or disabled */
+ if (info->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
+ {
+ new_flags = scroll->flags;
+ if (scroll->minVal >= scroll->maxVal - max( scroll->page - 1, 0 ))
+ {
+ /* Hide or disable scroll-bar */
+ if (info->fMask & SIF_DISABLENOSCROLL)
+ {
+ new_flags = ESB_DISABLE_BOTH;
+ action |= SA_SSI_REFRESH;
+ }
+ else if (bar != SB_CTL && (action & SA_SSI_REFRESH))
+ {
+ action = SA_SSI_HIDE;
+ }
+ }
+ else if (info->fMask != SIF_PAGE)
+ {
+ /* Show and enable scroll-bar only if no page only changed. */
+ new_flags = ESB_ENABLE_BOTH;
+ if (bar != SB_CTL && (action & SA_SSI_REFRESH)) action |= SA_SSI_SHOW;
+ }
+
+ if (bar == SB_CTL && redraw && is_window_visible( hwnd ) &&
+ (new_flags == ESB_ENABLE_BOTH || new_flags == ESB_DISABLE_BOTH))
+ {
+ release_scroll_info_ptr( scroll );
+ enable_window( hwnd, new_flags == ESB_ENABLE_BOTH );
+ if (!(scroll = get_scroll_info_ptr( hwnd, bar, FALSE ))) return 0;
+ }
+
+ if (scroll->flags != new_flags) /* check arrow flags */
+ {
+ scroll->flags = new_flags;
+ action |= SA_SSI_REPAINT_ARROWS;
+ }
+ }
+
+done:
+ ret = scroll->curVal;
+ release_scroll_info_ptr( scroll );
+ if (action & SA_SSI_HIDE)
+ show_scroll_bar( hwnd, bar, FALSE, FALSE );
+ else
+ {
+ if (action & SA_SSI_SHOW && show_scroll_bar( hwnd, bar, TRUE, TRUE ))
+ return ret; /* NtUserSetWindowPos() already did the painting */
+
+ if (redraw)
+ refresh_scroll_bar( hwnd, bar, TRUE, TRUE );
+ else if (action & SA_SSI_REPAINT_ARROWS)
+ refresh_scroll_bar( hwnd, bar, TRUE, FALSE );
+ }
+
+ return ret; /* Return current position */
+}
+
+static BOOL get_scroll_bar_info( HWND hwnd, LONG id, SCROLLBARINFO *info )
+{
+ struct scroll_info *scroll;
+ int bar, dummy;
+ DWORD style = get_window_long( hwnd, GWL_STYLE );
+ BOOL pressed;
+ RECT rect;
+
+ switch (id)
+ {
+ case OBJID_CLIENT: bar = SB_CTL; break;
+ case OBJID_HSCROLL: bar = SB_HORZ; break;
+ case OBJID_VSCROLL: bar = SB_VERT; break;
+ default: return FALSE;
+ }
+
+ /* handle invalid data structure */
+ if (info->cbSize != sizeof(*info)) return FALSE;
+
+ get_scroll_bar_rect( hwnd, bar, &info->rcScrollBar, &dummy,
+ &info->dxyLineButton, &info->xyThumbTop );
+ /* rcScrollBar needs to be in screen coordinates */
+ get_window_rect( hwnd, &rect, get_thread_dpi() );
+ OffsetRect( &info->rcScrollBar, rect.left, rect.top );
+
+ info->xyThumbBottom = info->xyThumbTop + info->dxyLineButton;
+
+ if (!(scroll = get_scroll_info_ptr( hwnd, bar, TRUE ))) return FALSE;
+
+ /* Scroll bar state */
+ info->rgstate[0] = 0;
+ if ((bar == SB_HORZ && !(style & WS_HSCROLL)) ||
+ (bar == SB_VERT && !(style & WS_VSCROLL)))
+ info->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
+ if (scroll->minVal >= scroll->maxVal - max( scroll->page - 1, 0 ))
+ {
+ if (!(info->rgstate[0] & STATE_SYSTEM_INVISIBLE))
+ info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE;
+ else
+ info->rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
+ }
+ if (bar == SB_CTL && !is_window_enabled( hwnd ))
+ info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE;
+
+ pressed = (bar == SB_VERT) == g_tracking_info.vertical && get_capture() == hwnd;
+
+ /* Top/left arrow button state. MSDN says top/right, but I don't believe it */
+ info->rgstate[1] = 0;
+ if (pressed && g_tracking_info.hit_test == SCROLL_TOP_ARROW)
+ info->rgstate[1] |= STATE_SYSTEM_PRESSED;
+ if (scroll->flags & ESB_DISABLE_LTUP)
+ info->rgstate[1] |= STATE_SYSTEM_UNAVAILABLE;
+
+ /* Page up/left region state. MSDN says up/right, but I don't believe it */
+ info->rgstate[2] = 0;
+ if (scroll->curVal == scroll->minVal)
+ info->rgstate[2] |= STATE_SYSTEM_INVISIBLE;
+ if (pressed && g_tracking_info.hit_test == SCROLL_TOP_RECT)
+ info->rgstate[2] |= STATE_SYSTEM_PRESSED;
+
+ /* Thumb state */
+ info->rgstate[3] = 0;
+ if (pressed && g_tracking_info.hit_test == SCROLL_THUMB)
+ info->rgstate[3] |= STATE_SYSTEM_PRESSED;
+
+ /* Page down/right region state. MSDN says down/left, but I don't believe it */
+ info->rgstate[4] = 0;
+ if (scroll->curVal >= scroll->maxVal - 1)
+ info->rgstate[4] |= STATE_SYSTEM_INVISIBLE;
+ if (pressed && g_tracking_info.hit_test == SCROLL_BOTTOM_RECT)
+ info->rgstate[4] |= STATE_SYSTEM_PRESSED;
+
+ /* Bottom/right arrow button state. MSDN says bottom/left, but I don't believe it */
+ info->rgstate[5] = 0;
+ if (pressed && g_tracking_info.hit_test == SCROLL_BOTTOM_ARROW)
+ info->rgstate[5] |= STATE_SYSTEM_PRESSED;
+ if (scroll->flags & ESB_DISABLE_RTDN)
+ info->rgstate[5] |= STATE_SYSTEM_UNAVAILABLE;
+
+ release_scroll_info_ptr( scroll );
+ return TRUE;
+}
+
static void create_scroll_bar( HWND hwnd, CREATESTRUCTW *create )
{
struct scroll_info *info = NULL;
@@ -256,6 +1127,31 @@ static void create_scroll_bar( HWND hwnd, CREATESTRUCTW *create )
}
}
+static int get_scroll_pos(HWND hwnd, int bar)
+{
+ struct scroll_info *scroll = get_scroll_info_ptr( hwnd, bar, FALSE );
+ int ret;
+ if (!scroll) return 0;
+ ret = scroll->curVal;
+ release_scroll_info_ptr( scroll );
+ return ret;
+}
+
+static BOOL set_scroll_range( HWND hwnd, int bar, int min_val, int max_val )
+{
+ struct scroll_info *scroll = get_scroll_info_ptr( hwnd, bar, FALSE );
+
+ TRACE( "hwnd=%p bar=%d min=%d max=%d\n", hwnd, bar, min_val, max_val );
+
+ if (scroll)
+ {
+ scroll->minVal = min_val;
+ scroll->maxVal = max_val;
+ release_scroll_info_ptr( scroll );
+ }
+ return TRUE;
+}
+
LRESULT scroll_bar_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi )
{
switch (msg)
@@ -264,6 +1160,49 @@ LRESULT scroll_bar_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
create_scroll_bar( hwnd, (CREATESTRUCTW *)lparam );
return 0;
+ case WM_LBUTTONDBLCLK:
+ case WM_LBUTTONDOWN:
+ if (get_window_long( hwnd, GWL_STYLE ) & SBS_SIZEGRIP)
+ {
+ send_message( get_parent(hwnd), WM_SYSCOMMAND,
+ SC_SIZE + ((get_window_long( hwnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) ?
+ WMSZ_BOTTOMLEFT : WMSZ_BOTTOMRIGHT), lparam );
+ }
+ else
+ {
+ POINT pt;
+ pt.x = (short)LOWORD( lparam );
+ pt.y = (short)HIWORD( lparam );
+ track_scroll_bar( hwnd, SB_CTL, pt );
+ }
+ return 0;
+
+ case WM_LBUTTONUP:
+ case WM_NCMOUSEMOVE:
+ case WM_NCMOUSELEAVE:
+ case WM_MOUSEMOVE:
+ case WM_MOUSELEAVE:
+ case WM_SYSTIMER:
+ {
+ POINT pt;
+ pt.x = (short)LOWORD( lparam );
+ pt.y = (short)HIWORD( lparam );
+ handle_scroll_event( hwnd, SB_CTL, msg, pt );
+ }
+ return 0;
+
+ case WM_ENABLE:
+ {
+ struct scroll_info *scroll;
+ if ((scroll = get_scroll_info_ptr( hwnd, SB_CTL, FALSE )))
+ {
+ scroll->flags = wparam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
+ release_scroll_info_ptr( scroll );
+ refresh_scroll_bar( hwnd, SB_CTL, TRUE, TRUE );
+ }
+ }
+ return 0;
+
case WM_SETFOCUS:
{
/* Create a caret when a ScrollBar get focus */
@@ -312,6 +1251,34 @@ LRESULT scroll_bar_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
case WM_GETDLGCODE:
return DLGC_WANTARROWS; /* Windows returns this value */
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hdc = wparam ? (HDC)wparam : NtUserBeginPaint( hwnd, &ps );
+ draw_scroll_bar( hwnd, hdc, SB_CTL, g_tracking_info.hit_test, &g_tracking_info, TRUE, TRUE );
+ if (!wparam) NtUserEndPaint( hwnd, &ps );
+ }
+ return 0;
+
+ case SBM_SETRANGEREDRAW:
+ case SBM_SETRANGE:
+ {
+ int old_pos = get_scroll_pos( hwnd, SB_CTL );
+ set_scroll_range( hwnd, SB_CTL, wparam, lparam );
+ if (msg == SBM_SETRANGEREDRAW) refresh_scroll_bar( hwnd, SB_CTL, TRUE, TRUE );
+ if (old_pos != get_scroll_pos( hwnd, SB_CTL )) return old_pos;
+ }
+ return 0;
+
+ case SBM_GETSCROLLINFO:
+ return get_scroll_info( hwnd, SB_CTL, (SCROLLINFO *)lparam );
+
+ case SBM_GETSCROLLBARINFO:
+ return get_scroll_bar_info( hwnd, OBJID_CLIENT, (SCROLLBARINFO *)lparam );
+
+ case SBM_SETSCROLLINFO:
+ return set_scroll_info( hwnd, SB_CTL, (SCROLLINFO *)lparam, wparam );
+
default:
return default_window_proc( hwnd, msg, wparam, lparam, ansi );
}
@@ -341,3 +1308,66 @@ BOOL WINAPI NtUserShowScrollBar( HWND hwnd, INT bar, BOOL show )
show_scroll_bar( hwnd, bar, bar == SB_VERT ? 0 : show, bar == SB_HORZ ? 0 : show );
return TRUE;
}
+
+/*************************************************************************
+ * NtUserGetScrollBarInfo (win32u.@)
+ */
+BOOL WINAPI NtUserGetScrollBarInfo( HWND hwnd, LONG id, SCROLLBARINFO *info )
+{
+ TRACE( "hwnd=%p id=%d info=%p\n", hwnd, id, info );
+
+ /* Refer OBJID_CLIENT requests to the window */
+ if (id == OBJID_CLIENT)
+ return send_message( hwnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)info );
+ return get_scroll_bar_info( hwnd, id, info );
+}
+
+/*************************************************************************
+ * NtUserEnableScrollBar (win32u.@)
+ */
+BOOL WINAPI NtUserEnableScrollBar( HWND hwnd, UINT bar, UINT flags )
+{
+ struct scroll_info *scroll;
+ BOOL check_flags;
+
+ flags &= ESB_DISABLE_BOTH;
+
+ if (bar == SB_BOTH)
+ {
+ if (!(scroll = get_scroll_info_ptr( hwnd, SB_VERT, TRUE ))) return FALSE;
+ check_flags = scroll->flags == flags;
+ scroll->flags = flags;
+ release_scroll_info_ptr( scroll );
+ if (!check_flags) refresh_scroll_bar( hwnd, SB_VERT, TRUE, TRUE );
+ bar = SB_HORZ;
+ }
+ else
+ check_flags = bar != SB_CTL;
+
+ if (!(scroll = get_scroll_info_ptr( hwnd, bar, TRUE ))) return FALSE;
+ if (check_flags) check_flags = scroll->flags == flags;
+ scroll->flags = flags;
+ release_scroll_info_ptr( scroll );
+ if (check_flags) return FALSE;
+
+ if (bar == SB_CTL && (flags == ESB_DISABLE_BOTH || flags == ESB_ENABLE_BOTH))
+ NtUserEnableWindow( hwnd, flags == ESB_ENABLE_BOTH );
+
+ refresh_scroll_bar( hwnd, bar, TRUE, TRUE );
+ return TRUE;
+}
+
+
+/*************************************************************************
+ * NtUserSetScrollInfo (win32u.@)
+ */
+INT WINAPI NtUserSetScrollInfo( HWND hwnd, int bar, const SCROLLINFO *info, BOOL redraw )
+{
+ TRACE( "hwnd=%p bar=%d info=%p, redraw=%d\n", hwnd, bar, info, redraw );
+
+ /* Refer SB_CTL requests to the window */
+ if (bar == SB_CTL)
+ return send_message( hwnd, SBM_SETSCROLLINFO, redraw, (LPARAM)info );
+
+ return set_scroll_info( hwnd, bar, info, redraw );
+}
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 428e8aadf1c..a2369364877 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -866,7 +866,7 @@
@ stub NtUserEnableMouseInputForCursorSuppression
@ stub NtUserEnableNonClientDpiScaling
@ stub NtUserEnableResizeLayoutSynchronization
-@ stub NtUserEnableScrollBar
+@ stdcall NtUserEnableScrollBar(long long long)
@ stub NtUserEnableSoftwareCursorForScreenCapture
@ stub NtUserEnableTouchPad
@ stub NtUserEnableWindowGDIScaledDpiMessage
@@ -991,7 +991,7 @@
@ stdcall -syscall NtUserGetRegisteredRawInputDevices(ptr ptr long)
@ stub NtUserGetRequiredCursorSizes
@ stub NtUserGetResizeDCompositionSynchronizationObject
-@ stub NtUserGetScrollBarInfo
+@ stdcall NtUserGetScrollBarInfo(long long ptr)
@ stub NtUserGetSharedWindowData
@ stdcall -syscall NtUserGetSystemDpiForProcess(long)
@ stdcall NtUserGetSystemMenu(long long)
@@ -1223,7 +1223,7 @@
@ stub NtUserSetProcessUIAccessZorder
@ stdcall -syscall NtUserSetProcessWindowStation(long)
@ stdcall -syscall NtUserSetProp(long wstr ptr)
-@ stub NtUserSetScrollInfo
+@ stdcall NtUserSetScrollInfo(long long ptr long)
@ stub NtUserSetSensorPresence
@ stub NtUserSetSharedWindowData
@ stub NtUserSetShellWindowEx
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 49c81ea3bef..a690acadd8b 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -223,6 +223,7 @@ struct unix_funcs
DWORD (WINAPI *pNtUserDrawMenuBarTemp)( HWND hwnd, HDC hdc, RECT *rect, HMENU handle, HFONT font );
BOOL (WINAPI *pNtUserEmptyClipboard)(void);
BOOL (WINAPI *pNtUserEnableMenuItem)( HMENU handle, UINT id, UINT flags );
+ BOOL (WINAPI *pNtUserEnableScrollBar)( HWND hwnd, UINT bar, UINT flags );
BOOL (WINAPI *pNtUserEndDeferWindowPosEx)( HDWP hdwp, BOOL async );
BOOL (WINAPI *pNtUserEndPaint)( HWND hwnd, const PAINTSTRUCT *ps );
NTSTATUS (WINAPI *pNtUserEnumDisplayDevices)( UNICODE_STRING *device, DWORD index,
@@ -248,6 +249,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserGetMessage)( MSG *msg, HWND hwnd, UINT first, UINT last );
INT (WINAPI *pNtUserGetPriorityClipboardFormat)( UINT *list, INT count );
DWORD (WINAPI *pNtUserGetQueueStatus)( UINT flags );
+ BOOL (WINAPI *pNtUserGetScrollBarInfo)( HWND hwnd, LONG id, SCROLLBARINFO *info );
HMENU (WINAPI *pNtUserGetSystemMenu)( HWND hwnd, BOOL revert );
BOOL (WINAPI *pNtUserGetUpdateRect)( HWND hwnd, RECT *rect, BOOL erase );
INT (WINAPI *pNtUserGetUpdateRgn)( HWND hwnd, HRGN hrgn, BOOL erase );
@@ -300,6 +302,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserSetLayeredWindowAttributes)( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags );
BOOL (WINAPI *pNtUserSetMenu)( HWND hwnd, HMENU menu );
HWND (WINAPI *pNtUserSetParent)( HWND hwnd, HWND parent );
+ INT (WINAPI *pNtUserSetScrollInfo)( HWND hwnd, INT bar, const SCROLLINFO *info, BOOL redraw );
BOOL (WINAPI *pNtUserSetSysColors)( INT count, const INT *colors, const COLORREF *values );
BOOL (WINAPI *pNtUserSetSystemMenu)( HWND hwnd, HMENU menu );
LONG (WINAPI *pNtUserSetWindowLong)( HWND hwnd, INT offset, LONG newval, BOOL ansi );
@@ -441,9 +444,13 @@ extern BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardwar
extern BOOL rawinput_device_get_usages( HANDLE handle, USHORT *usage_page, USHORT *usage ) DECLSPEC_HIDDEN;
/* scroll.c */
+extern void draw_nc_scrollbar( HWND hwnd, HDC hdc, BOOL draw_horizontal, BOOL draw_vertical ) DECLSPEC_HIDDEN;
+extern BOOL get_scroll_info( HWND hwnd, INT bar, SCROLLINFO *info ) DECLSPEC_HIDDEN;
+extern void handle_scroll_event( HWND hwnd, INT bar, UINT msg, POINT pt ) DECLSPEC_HIDDEN;
extern LRESULT scroll_bar_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
BOOL ansi ) DECLSPEC_HIDDEN;
extern void set_standard_scroll_painted( HWND hwnd, int bar, BOOL painted ) DECLSPEC_HIDDEN;
+extern void track_scroll_bar( HWND hwnd, int scrollbar, POINT pt ) DECLSPEC_HIDDEN;
/* sysparams.c */
extern BOOL enable_thunk_lock DECLSPEC_HIDDEN;
@@ -484,6 +491,7 @@ extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN;
extern BOOL client_to_screen( HWND hwnd, POINT *pt ) DECLSPEC_HIDDEN;
extern void destroy_thread_windows(void) DECLSPEC_HIDDEN;
extern LRESULT destroy_window( HWND hwnd ) DECLSPEC_HIDDEN;
+extern BOOL enable_window( HWND hwnd, BOOL enable ) DECLSPEC_HIDDEN;
extern BOOL get_client_rect( HWND hwnd, RECT *rect ) DECLSPEC_HIDDEN;
extern HWND get_desktop_window(void) DECLSPEC_HIDDEN;
extern UINT get_dpi_for_window( HWND hwnd ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index 4a6b321d391..de4779aee59 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -812,7 +812,7 @@ BOOL is_window_unicode( HWND hwnd )
}
/* see EnableWindow */
-static BOOL enable_window( HWND hwnd, BOOL enable )
+BOOL enable_window( HWND hwnd, BOOL enable )
{
BOOL ret;
@@ -5442,6 +5442,12 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code )
case NtUserCallHwndParam_GetClientRect:
return get_client_rect( hwnd, (RECT *)param );
+ case NtUserCallHwndParam_GetScrollInfo:
+ {
+ struct get_scroll_info_params *params = (void *)param;
+ return get_scroll_info( hwnd, params->bar, params->info );
+ }
+
case NtUserCallHwndParam_GetWindowInfo:
return get_window_info( hwnd, (WINDOWINFO *)param );
@@ -5501,9 +5507,6 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code )
return show_owned_popups( hwnd, param );
/* temporary exports */
- case NtUserIsWindowDrawable:
- return is_window_drawable( hwnd, param );
-
case NtUserSetWindowStyle:
{
STYLESTRUCT *style = (void *)param;
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index e7ab66cadcb..ba6fa9ea0a0 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -887,6 +887,12 @@ BOOL WINAPI NtUserEnableMenuItem( HMENU handle, UINT id, UINT flags )
return unix_funcs->pNtUserEnableMenuItem( handle, id, flags );
}
+BOOL WINAPI NtUserEnableScrollBar( HWND hwnd, UINT bar, UINT flags )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserEnableScrollBar( hwnd, bar, flags );
+}
+
BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async )
{
if (!unix_funcs) return FALSE;
@@ -1048,6 +1054,12 @@ DWORD WINAPI NtUserGetQueueStatus( UINT flags )
return unix_funcs->pNtUserGetQueueStatus( flags );
}
+BOOL WINAPI NtUserGetScrollBarInfo( HWND hwnd, LONG id, SCROLLBARINFO *info )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserGetScrollBarInfo( hwnd, id, info );
+}
+
BOOL WINAPI NtUserGetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size )
{
if (!unix_funcs) return FALSE;
@@ -1274,6 +1286,12 @@ HWND WINAPI NtUserSetParent( HWND hwnd, HWND parent )
return unix_funcs->pNtUserSetParent( hwnd, parent );
}
+INT WINAPI NtUserSetScrollInfo( HWND hwnd, INT bar, const SCROLLINFO *info, BOOL redraw )
+{
+ if (!unix_funcs) return 0;
+ return unix_funcs->pNtUserSetScrollInfo( hwnd, bar, info, redraw );
+}
+
BOOL WINAPI NtUserSetSysColors( INT count, const INT *colors, const COLORREF *values )
{
if (!unix_funcs) return FALSE;
diff --git a/include/ntuser.h b/include/ntuser.h
index 08a49cbd123..fecdbbbe253 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -33,6 +33,7 @@ enum
NtUserCallWinProc,
NtUserCallWindowsHook,
NtUserCopyImage,
+ NtUserDrawScrollBar,
NtUserDrawText,
NtUserFreeCachedClipboardData,
NtUserLoadDriver,
@@ -336,6 +337,24 @@ struct set_clipboard_params
UINT seqno;
};
+/* NtUserDrawScrollBar params */
+struct draw_scroll_bar_params
+{
+ HWND hwnd;
+ HDC hdc;
+ INT bar;
+ UINT hit_test;
+ struct SCROLL_TRACKING_INFO tracking_info;
+ BOOL arrows;
+ BOOL interior;
+ RECT rect;
+ UINT enable_flags;
+ INT arrow_size;
+ INT thumb_pos;
+ INT thumb_size;
+ BOOL vertical;
+};
+
/* internal messages codes */
enum wine_internal_message
{
@@ -559,6 +578,7 @@ BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
DWORD WINAPI NtUserDrawMenuBarTemp( HWND hwnd, HDC hdc, RECT *rect, HMENU handle, HFONT font );
BOOL WINAPI NtUserEmptyClipboard(void);
BOOL WINAPI NtUserEnableMenuItem( HMENU handle, UINT id, UINT flags );
+BOOL WINAPI NtUserEnableScrollBar( HWND hwnd, UINT bar, UINT flags );
BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async );
BOOL WINAPI NtUserEndMenu(void);
BOOL WINAPI NtUserEndPaint( HWND hwnd, const PAINTSTRUCT *ps );
@@ -625,6 +645,7 @@ UINT WINAPI NtUserGetRawInputData( HRAWINPUT rawinput, UINT command, void *da
UINT WINAPI NtUserGetRawInputDeviceInfo( HANDLE handle, UINT command, void *data, UINT *data_size );
UINT WINAPI NtUserGetRawInputDeviceList( RAWINPUTDEVICELIST *devices, UINT *device_count, UINT size );
UINT WINAPI NtUserGetRegisteredRawInputDevices( RAWINPUTDEVICE *devices, UINT *device_count, UINT size );
+BOOL WINAPI NtUserGetScrollBarInfo( HWND hwnd, LONG id, SCROLLBARINFO *info );
ULONG WINAPI NtUserGetSystemDpiForProcess( HANDLE process );
HMENU WINAPI NtUserGetSystemMenu( HWND hwnd, BOOL revert );
HDESK WINAPI NtUserGetThreadDesktop( DWORD thread );
@@ -701,6 +722,7 @@ HWND WINAPI NtUserSetParent( HWND hwnd, HWND parent );
BOOL WINAPI NtUserSetProcessDpiAwarenessContext( ULONG awareness, ULONG unknown );
BOOL WINAPI NtUserSetProcessWindowStation( HWINSTA handle );
BOOL WINAPI NtUserSetProp( HWND hwnd, const WCHAR *str, HANDLE handle );
+INT WINAPI NtUserSetScrollInfo( HWND hwnd, INT bar, const SCROLLINFO *info, BOOL redraw );
BOOL WINAPI NtUserSetSysColors( INT count, const INT *colors, const COLORREF *values );
BOOL WINAPI NtUserSetSystemMenu( HWND hwnd, HMENU menu );
UINT_PTR WINAPI NtUserSetSystemTimer( HWND hwnd, UINT_PTR id, UINT timeout );
@@ -1085,6 +1107,7 @@ enum
NtUserCallHwndParam_GetClassLongPtrW,
NtUserCallHwndParam_GetClassWord,
NtUserCallHwndParam_GetClientRect,
+ NtUserCallHwndParam_GetScrollInfo,
NtUserCallHwndParam_GetWindowInfo,
NtUserCallHwndParam_GetWindowLongA,
NtUserCallHwndParam_GetWindowLongW,
@@ -1104,7 +1127,6 @@ enum
NtUserCallHwndParam_SetWindowPixelFormat,
NtUserCallHwndParam_ShowOwnedPopups,
/* temporary exports */
- NtUserIsWindowDrawable,
NtUserSetWindowStyle,
NtUserSpyGetMsgName,
};
@@ -1149,6 +1171,18 @@ static inline BOOL NtUserGetClientRect( HWND hwnd, RECT *rect )
return NtUserCallHwndParam( hwnd, (UINT_PTR)rect, NtUserCallHwndParam_GetClientRect );
}
+struct get_scroll_info_params
+{
+ int bar;
+ SCROLLINFO *info;
+};
+
+static inline BOOL NtUserGetScrollInfo( HWND hwnd, INT bar, SCROLLINFO *info )
+{
+ struct get_scroll_info_params params = { .bar = bar, .info = info };
+ return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_GetScrollInfo );
+}
+
static inline BOOL NtUserGetWindowInfo( HWND hwnd, WINDOWINFO *info )
{
return NtUserCallHwndParam( hwnd, (UINT_PTR)info, NtUserCallHwndParam_GetWindowInfo );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/368
More information about the wine-devel
mailing list