diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index 25ff4fe05ff..bf32097f95c 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -180,28 +180,6 @@ extern void NC_GetSysPopupPos( HWND hwnd, RECT* rect ) DECLSPEC_HIDDEN; /* scrollbar */ -/* Scroll-bar hit testing */ -enum SCROLL_HITTEST -{ - SCROLL_NOWHERE, /* Outside the scroll bar */ - SCROLL_TOP_ARROW, /* Top or left arrow */ - SCROLL_TOP_RECT, /* Rectangle between the top arrow and the thumb */ - SCROLL_THUMB, /* Thumb rectangle */ - SCROLL_BOTTOM_RECT, /* Rectangle between the thumb and the bottom arrow */ - SCROLL_BOTTOM_ARROW /* Bottom or right arrow */ -}; - -/* Scroll bar tracking information */ -struct SCROLL_TRACKING_INFO -{ - HWND win; /* Tracking window */ - INT bar; /* SB_HORZ / SB_VERT / SB_CTL */ - INT thumb_pos; /* Thumb position */ - INT thumb_val; /* Current thumb value from thumb position */ - BOOL vertical; /* Is scroll bar vertical */ - enum SCROLL_HITTEST hit_test; /* Hit Test code of the last button-down event */ -}; - 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, diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c index 7921bc3d45a..f5b4c6ab8a1 100644 --- a/dlls/user32/hook.c +++ b/dlls/user32/hook.c @@ -84,6 +84,7 @@ WINE_DECLARE_DEBUG_CHANNEL(relay); static struct user_api_hook original_user_api = { USER_DefDlgProc, + USER_ScrollBarDraw, USER_ScrollBarProc, }; static struct user_api_hook hooked_user_api; diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c index 9a22e930332..c4c06476b9c 100644 --- a/dlls/user32/scroll.c +++ b/dlls/user32/scroll.c @@ -567,10 +567,10 @@ static void SCROLL_DrawInterior( HWND hwnd, HDC hdc, INT nBar, SelectObject( hdc, hSaveBrush ); } -static void SCROLL_DoDrawScrollBar( HWND hwnd, HDC hdc, INT nBar, enum SCROLL_HITTEST hit_test, - const struct SCROLL_TRACKING_INFO *tracking_info, BOOL arrows, - BOOL interior, RECT *rect, INT arrowSize, INT thumbPos, - INT thumbSize, BOOL vertical ) +void WINAPI USER_ScrollBarDraw( HWND hwnd, HDC hdc, INT nBar, enum SCROLL_HITTEST hit_test, + const struct SCROLL_TRACKING_INFO *tracking_info, BOOL arrows, + BOOL interior, RECT *rect, INT arrowSize, INT thumbPos, + INT thumbSize, BOOL vertical ) { SCROLLBAR_INFO *infoPtr; @@ -678,8 +678,8 @@ void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, INT bar, enum SCROLL_HITTEST hit_ 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()); - SCROLL_DoDrawScrollBar( hwnd, hdc, bar, hit_test, tracking_info, draw_arrows, draw_interior, - &rect, arrow_size, thumb_pos, thumb_size, vertical ); + user_api->pScrollBarDraw( hwnd, hdc, bar, hit_test, tracking_info, draw_arrows, draw_interior, + &rect, arrow_size, thumb_pos, thumb_size, vertical ); } void SCROLL_DrawNCScrollBar( HWND hwnd, HDC hdc, BOOL draw_horizontal, BOOL draw_vertical ) @@ -764,6 +764,7 @@ static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt) enum SCROLL_HITTEST hittest; HWND hwndOwner, hwndCtl; + TRACKMOUSEEVENT tme; BOOL vertical; INT arrowSize, thumbSize, thumbPos; RECT rect; @@ -771,7 +772,8 @@ static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt) SCROLLBAR_INFO *infoPtr = SCROLL_GetInternalInfo( hwnd, nBar, FALSE ); if (!infoPtr) return; - if ((g_tracking_info.hit_test == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN)) + if ((g_tracking_info.hit_test == SCROLL_NOWHERE) + && (msg != WM_LBUTTONDOWN && msg != WM_MOUSEMOVE && msg != WM_MOUSELEAVE)) return; if (nBar == SB_CTL && (GetWindowLongW( hwnd, GWL_STYLE ) & (SBS_SIZEGRIP | SBS_SIZEBOX))) @@ -821,8 +823,29 @@ static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt) break; case WM_MOUSEMOVE: - hittest = SCROLL_HitTest( hwnd, nBar, pt, TRUE ); + 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; + TrackMouseEvent( &tme ); + if (!(tme.dwFlags & TME_LEAVE) || tme.hwndTrack != hwnd) + { + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hwnd; + TrackMouseEvent( &tme ); + } + + break; + + case WM_MOUSELEAVE: + if (nBar != SB_CTL) + return; + + hittest = SCROLL_NOWHERE; break; case WM_LBUTTONUP: @@ -847,6 +870,8 @@ static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt) switch (g_tracking_info.hit_test) { case SCROLL_NOWHERE: /* No tracking in progress */ + if (msg == WM_MOUSEMOVE || msg == WM_MOUSELEAVE) + SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, TRUE, TRUE ); break; case SCROLL_TOP_ARROW: @@ -898,7 +923,7 @@ static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt) { SCROLL_DrawScrollBar( hwnd, hdc, nBar, SCROLL_NOWHERE, &g_tracking_info, FALSE, TRUE ); } - else /* WM_MOUSEMOVE */ + else if (msg == WM_MOUSEMOVE) { INT pos; @@ -986,6 +1011,8 @@ static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt) /* Terminate tracking */ g_tracking_info.win = 0; SCROLL_MovingThumb = FALSE; + hittest = SCROLL_NOWHERE; + SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, TRUE, TRUE ); } ReleaseDC( hwnd, hdc ); @@ -1021,6 +1048,7 @@ void SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt ) if (CallMsgFilterW( &msg, MSGF_SCROLLBAR )) continue; if (msg.message == WM_LBUTTONUP || msg.message == WM_MOUSEMOVE || + msg.message == WM_MOUSELEAVE || (msg.message == WM_SYSTIMER && msg.wParam == SCROLL_TIMER)) { pt.x = (short)LOWORD(msg.lParam) - rect.left; @@ -1356,6 +1384,7 @@ LRESULT WINAPI USER_ScrollBarProc( HWND hwnd, UINT message, WPARAM wParam, LPARA break; case WM_LBUTTONUP: case WM_MOUSEMOVE: + case WM_MOUSELEAVE: case WM_SYSTIMER: { POINT pt; diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 8750008a5fb..7c4d9015976 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -389,5 +389,8 @@ struct png_funcs extern struct user_api_hook *user_api DECLSPEC_HIDDEN; LRESULT WINAPI USER_DefDlgProc(HWND, UINT, WPARAM, LPARAM, BOOL) DECLSPEC_HIDDEN; LRESULT WINAPI USER_ScrollBarProc(HWND, UINT, WPARAM, LPARAM, BOOL) DECLSPEC_HIDDEN; +void WINAPI USER_ScrollBarDraw(HWND, HDC, INT, enum SCROLL_HITTEST, + const struct SCROLL_TRACKING_INFO *, BOOL, BOOL, RECT *, INT, INT, + INT, BOOL) DECLSPEC_HIDDEN; #endif /* __WINE_USER_PRIVATE_H */ diff --git a/dlls/uxtheme/scrollbar.c b/dlls/uxtheme/scrollbar.c index 393b45a831d..40fdbf4b89a 100644 --- a/dlls/uxtheme/scrollbar.c +++ b/dlls/uxtheme/scrollbar.c @@ -20,8 +20,6 @@ */ #include -#include -#include #include "windef.h" #include "winbase.h" @@ -32,299 +30,27 @@ #include "vssym32.h" #include "wine/debug.h" -/* Minimum size of the thumb in pixels */ -#define SCROLL_MIN_THUMB 6 - -/* Minimum size of the rectangle between the arrows */ -#define SCROLL_MIN_RECT 4 - -enum SCROLL_HITTEST -{ - SCROLL_NOWHERE, /* Outside the scroll bar */ - SCROLL_TOP_ARROW, /* Top or left arrow */ - SCROLL_TOP_RECT, /* Rectangle between the top arrow and the thumb */ - SCROLL_THUMB, /* Thumb rectangle */ - SCROLL_BOTTOM_RECT, /* Rectangle between the thumb and the bottom arrow */ - SCROLL_BOTTOM_ARROW /* Bottom or right arrow */ -}; - -static HWND tracking_win = 0; -static enum SCROLL_HITTEST tracking_hot_part = SCROLL_NOWHERE; - WINE_DEFAULT_DEBUG_CHANNEL(theme_scroll); -static void calc_thumb_dimensions(unsigned int size, SCROLLINFO *si, unsigned int *thumbpos, unsigned int *thumbsize) +void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTEST hit_test, + const struct SCROLL_TRACKING_INFO *tracking_info, + BOOL draw_arrows, BOOL draw_interior, RECT *rect, INT arrowsize, + INT thumbpos, INT thumbsize, BOOL vertical) { - if (size <= SCROLL_MIN_RECT) - *thumbpos = *thumbsize = 0; - else if (si->nPage > si->nMax - si->nMin) - *thumbpos = *thumbsize = 0; - else { - if (si->nPage > 0) { - *thumbsize = MulDiv(size, si->nPage, si->nMax - si->nMin + 1); - if (*thumbsize < SCROLL_MIN_THUMB) *thumbsize = SCROLL_MIN_THUMB; - } - else *thumbsize = GetSystemMetrics(SM_CXVSCROLL); - - if (size < *thumbsize) - *thumbpos = *thumbsize = 0; - else { - int max = si->nMax - max(si->nPage - 1, 0); - size -= *thumbsize; - if (si->nMin >= max) - *thumbpos = 0; - else - *thumbpos = MulDiv(size, si->nTrackPos - si->nMin, max - si->nMin); - } - } -} - -static enum SCROLL_HITTEST hit_test(HWND hwnd, HTHEME theme, POINT pt) -{ - RECT r; - DWORD style = GetWindowLongW(hwnd, GWL_STYLE); - BOOL vertical = style & SBS_VERT; - SIZE sz; - SCROLLINFO si; - unsigned int offset, size, upsize, downsize, thumbpos, thumbsize; - - GetWindowRect(hwnd, &r); - OffsetRect(&r, -r.left, -r.top); - - if (vertical) { - offset = pt.y; - size = r.bottom; - - if (FAILED(GetThemePartSize(theme, NULL, SBP_ARROWBTN, ABS_UPNORMAL, NULL, TS_DRAW, &sz))) { - WARN("Could not get up arrow size.\n"); - upsize = 0; - } else - upsize = sz.cy; - - if (FAILED(GetThemePartSize(theme, NULL, SBP_ARROWBTN, ABS_DOWNNORMAL, NULL, TS_DRAW, &sz))) { - WARN("Could not get down arrow size.\n"); - downsize = 0; - } else - downsize = sz.cy; - } else { - offset = pt.x; - size = r.right; - - if (FAILED(GetThemePartSize(theme, NULL, SBP_ARROWBTN, ABS_LEFTNORMAL, NULL, TS_DRAW, &sz))) { - WARN("Could not get left arrow size.\n"); - upsize = 0; - } else - upsize = sz.cx; - - if (FAILED(GetThemePartSize(theme, NULL, SBP_ARROWBTN, ABS_RIGHTNORMAL, NULL, TS_DRAW, &sz))) { - WARN("Could not get right arrow size.\n"); - downsize = 0; - } else - downsize = sz.cx; - } - - if (pt.x < 0 || pt.x > r.right || pt.y < 0 || pt.y > r.bottom) - return SCROLL_NOWHERE; - - if (size < SCROLL_MIN_RECT + upsize + downsize) - upsize = downsize = (size - SCROLL_MIN_RECT)/2; - - if (offset < upsize) - return SCROLL_TOP_ARROW; - - if (offset > size - downsize) - return SCROLL_BOTTOM_ARROW; - - si.cbSize = sizeof(si); - si.fMask = SIF_ALL; - if (!GetScrollInfo(hwnd, SB_CTL, &si)) { - WARN("GetScrollInfo failed.\n"); - return SCROLL_NOWHERE; - } - - calc_thumb_dimensions(size - upsize - downsize, &si, &thumbpos, &thumbsize); - - if (offset < upsize + thumbpos) - return SCROLL_TOP_RECT; - else if (offset < upsize + thumbpos + thumbsize) - return SCROLL_THUMB; - else - return SCROLL_BOTTOM_RECT; -} - -static void redraw_part(HWND hwnd, HTHEME theme, enum SCROLL_HITTEST part) -{ - DWORD style = GetWindowLongW(hwnd, GWL_STYLE); - BOOL vertical = style & SBS_VERT; - SIZE sz; - RECT r, partrect; - unsigned int size, upsize, downsize; - - if (part == SCROLL_NOWHERE) { /* redraw everything */ - InvalidateRect(hwnd, NULL, TRUE); - return; - } - - GetWindowRect(hwnd, &r); - OffsetRect(&r, -r.left, -r.top); - - if (vertical) { - size = r.bottom; - - if (FAILED(GetThemePartSize(theme, NULL, SBP_ARROWBTN, ABS_UPNORMAL, NULL, TS_DRAW, &sz))) { - WARN("Could not get up arrow size.\n"); - upsize = 0; - } else - upsize = sz.cy; - - if (FAILED(GetThemePartSize(theme, NULL, SBP_ARROWBTN, ABS_DOWNNORMAL, NULL, TS_DRAW, &sz))) { - WARN("Could not get down arrow size.\n"); - downsize = 0; - } else - downsize = sz.cy; - } else { - size = r.right; - - if (FAILED(GetThemePartSize(theme, NULL, SBP_ARROWBTN, ABS_LEFTNORMAL, NULL, TS_DRAW, &sz))) { - WARN("Could not get left arrow size.\n"); - upsize = 0; - } else - upsize = sz.cx; - - if (FAILED(GetThemePartSize(theme, NULL, SBP_ARROWBTN, ABS_RIGHTNORMAL, NULL, TS_DRAW, &sz))) { - WARN("Could not get right arrow size.\n"); - downsize = 0; - } else - downsize = sz.cx; - } - - if (size < SCROLL_MIN_RECT + upsize + downsize) - upsize = downsize = (size - SCROLL_MIN_RECT)/2; - - partrect = r; - - if (part == SCROLL_TOP_ARROW) { - if (vertical) - partrect.bottom = partrect.top + upsize; - else - partrect.right = partrect.left + upsize; - } else if (part == SCROLL_BOTTOM_ARROW) { - if (vertical) - partrect.top = partrect.bottom - downsize; - else - partrect.left = partrect.right - downsize; - } else { - unsigned int thumbpos, thumbsize; - SCROLLINFO si; - - si.cbSize = sizeof(si); - si.fMask = SIF_ALL; - if (!GetScrollInfo(hwnd, SB_CTL, &si)) { - WARN("GetScrollInfo failed.\n"); - return; - } - - calc_thumb_dimensions(size - upsize - downsize, &si, &thumbpos, &thumbsize); - - if (part == SCROLL_TOP_RECT) { - if (vertical) { - partrect.top = r.top + upsize; - partrect.bottom = partrect.top + thumbpos; - } else { - partrect.left = r.left + upsize; - partrect.right = partrect.left + thumbpos; - } - } else if (part == SCROLL_THUMB) { - if (vertical) { - partrect.top = r.top + upsize + thumbpos; - partrect.bottom = partrect.top + thumbsize; - } else { - partrect.left = r.left + upsize + thumbpos; - partrect.right = partrect.left + thumbsize; - } - } else if (part == SCROLL_BOTTOM_RECT) { - if (vertical) { - partrect.top = r.top + upsize + thumbpos + thumbsize; - partrect.bottom = r.bottom - downsize; - } else { - partrect.left = r.left + upsize + thumbpos + thumbsize; - partrect.right = r.right - downsize; - } - } - } - - InvalidateRect(hwnd, &partrect, TRUE); -} - -static void scroll_event(HWND hwnd, HTHEME theme, UINT msg, POINT pt) -{ - enum SCROLL_HITTEST hittest; - TRACKMOUSEEVENT tme; - - if (GetWindowLongW(hwnd, GWL_STYLE) & (SBS_SIZEGRIP | SBS_SIZEBOX)) - return; - - hittest = hit_test(hwnd, theme, pt); - - switch (msg) - { - case WM_MOUSEMOVE: - hittest = hit_test(hwnd, theme, pt); - tracking_win = hwnd; - break; - - case WM_MOUSELEAVE: - if (tracking_win == hwnd) { - hittest = SCROLL_NOWHERE; - } - break; - } - - tme.cbSize = sizeof(tme); - tme.dwFlags = TME_QUERY; - TrackMouseEvent(&tme); - - if (!(tme.dwFlags & TME_LEAVE) || tme.hwndTrack != hwnd) { - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hwnd; - TrackMouseEvent(&tme); - } - - if (tracking_win != hwnd && msg == WM_MOUSELEAVE) { - redraw_part(hwnd, theme, SCROLL_NOWHERE); - return; - } - - if (tracking_win == hwnd && hittest != tracking_hot_part) { - enum SCROLL_HITTEST oldhotpart = tracking_hot_part; - - tracking_hot_part = hittest; - - if (hittest != SCROLL_NOWHERE) - redraw_part(hwnd, theme, hittest); - else - tracking_win = 0; - - if (oldhotpart != SCROLL_NOWHERE) - redraw_part(hwnd, theme, oldhotpart); - } -} - -static void paint_scrollbar(HWND hwnd, HTHEME theme) -{ - HDC dc; - PAINTSTRUCT ps; - RECT r; - DWORD style = GetWindowLongW(hwnd, GWL_STYLE); - BOOL vertical = style & SBS_VERT; BOOL disabled = !IsWindowEnabled(hwnd); + HTHEME theme; + DWORD style; - GetWindowRect(hwnd, &r); - OffsetRect(&r, -r.left, -r.top); + theme = bar == SB_CTL ? GetWindowTheme(hwnd) : OpenThemeData(NULL, WC_SCROLLBARW); + if (!theme) + { + user_api.pScrollBarDraw(hwnd, dc, bar, hit_test, tracking_info, draw_arrows, draw_interior, + rect, arrowsize, thumbpos, thumbsize, vertical); + return; + } - dc = BeginPaint(hwnd, &ps); - - if (style & SBS_SIZEBOX || style & SBS_SIZEGRIP) { + style = GetWindowLongW(hwnd, GWL_STYLE); + if (bar == SB_CTL && (style & SBS_SIZEBOX || style & SBS_SIZEGRIP)) { int state; if (style & SBS_SIZEBOXTOPLEFTALIGN) @@ -334,20 +60,12 @@ static void paint_scrollbar(HWND hwnd, HTHEME theme) if (IsThemeBackgroundPartiallyTransparent(theme, SBP_SIZEBOX, state)) DrawThemeParentBackground(hwnd, dc, NULL); - DrawThemeBackground(theme, dc, SBP_SIZEBOX, state, &r, NULL); + DrawThemeBackground(theme, dc, SBP_SIZEBOX, state, rect, NULL); } else { - SCROLLINFO si; - unsigned int thumbpos, thumbsize; int uppertrackstate, lowertrackstate, thumbstate; - RECT partrect, trackrect; + RECT partrect; SIZE grippersize; - si.cbSize = sizeof(si); - si.fMask = SIF_ALL; - GetScrollInfo(hwnd, SB_CTL, &si); - - trackrect = r; - if (disabled) { uppertrackstate = SCRBS_DISABLED; lowertrackstate = SCRBS_DISABLED; @@ -357,20 +75,18 @@ static void paint_scrollbar(HWND hwnd, HTHEME theme) lowertrackstate = SCRBS_NORMAL; thumbstate = SCRBS_NORMAL; - if (tracking_win == hwnd) { - if (tracking_hot_part == SCROLL_TOP_RECT) - uppertrackstate = SCRBS_HOT; - else if (tracking_hot_part == SCROLL_BOTTOM_RECT) - lowertrackstate = SCRBS_HOT; - else if (tracking_hot_part == SCROLL_THUMB) - thumbstate = SCRBS_HOT; - } + if (hit_test == SCROLL_TOP_RECT) + uppertrackstate = SCRBS_HOT; + else if (hit_test == SCROLL_BOTTOM_RECT) + lowertrackstate = SCRBS_HOT; + else if (hit_test == SCROLL_THUMB) + thumbstate = SCRBS_HOT; } - DrawThemeParentBackground(hwnd, dc, NULL); + if (bar == SB_CTL) + DrawThemeParentBackground(hwnd, dc, NULL); if (vertical) { - SIZE upsize, downsize; int uparrowstate, downarrowstate; if (disabled) { @@ -380,50 +96,29 @@ static void paint_scrollbar(HWND hwnd, HTHEME theme) uparrowstate = ABS_UPNORMAL; downarrowstate = ABS_DOWNNORMAL; - if (tracking_win == hwnd) { - if (tracking_hot_part == SCROLL_TOP_ARROW) - uparrowstate = ABS_UPHOT; - else if (tracking_hot_part == SCROLL_BOTTOM_ARROW) - downarrowstate = ABS_DOWNHOT; - } + if (hit_test == SCROLL_TOP_ARROW) + uparrowstate = ABS_UPHOT; + else if (hit_test == SCROLL_BOTTOM_ARROW) + downarrowstate = ABS_DOWNHOT; } - if (FAILED(GetThemePartSize(theme, dc, SBP_ARROWBTN, uparrowstate, NULL, TS_DRAW, &upsize))) { - WARN("Could not get up arrow size.\n"); - return; - } - - if (FAILED(GetThemePartSize(theme, dc, SBP_ARROWBTN, downarrowstate, NULL, TS_DRAW, &downsize))) { - WARN("Could not get down arrow size.\n"); - return; - } - - if (r.bottom - r.top - upsize.cy - downsize.cy < SCROLL_MIN_RECT) - upsize.cy = downsize.cy = (r.bottom - r.top - SCROLL_MIN_RECT)/2; - - partrect = r; - partrect.bottom = partrect.top + upsize.cy; + partrect = *rect; + partrect.bottom = partrect.top + arrowsize; DrawThemeBackground(theme, dc, SBP_ARROWBTN, uparrowstate, &partrect, NULL); - trackrect.top = partrect.bottom; - - partrect.bottom = r.bottom; - partrect.top = partrect.bottom - downsize.cy; + partrect.bottom = rect->bottom; + partrect.top = partrect.bottom - arrowsize; DrawThemeBackground(theme, dc, SBP_ARROWBTN, downarrowstate, &partrect, NULL); - trackrect.bottom = partrect.top; - - calc_thumb_dimensions(trackrect.bottom - trackrect.top, &si, &thumbpos, &thumbsize); - if (thumbpos > 0) { - partrect.top = trackrect.top; - partrect.bottom = partrect.top + thumbpos; + partrect.top = rect->top + arrowsize; + partrect.bottom = rect->top + thumbpos; DrawThemeBackground(theme, dc, SBP_UPPERTRACKVERT, uppertrackstate, &partrect, NULL); } if (thumbsize > 0) { - partrect.top = trackrect.top + thumbpos; + partrect.top = rect->top + thumbpos; partrect.bottom = partrect.top + thumbsize; DrawThemeBackground(theme, dc, SBP_THUMBBTNVERT, thumbstate, &partrect, NULL); @@ -438,14 +133,14 @@ static void paint_scrollbar(HWND hwnd, HTHEME theme) } } - if (thumbpos + thumbsize < trackrect.bottom - trackrect.top) { - partrect.bottom = trackrect.bottom; - partrect.top = trackrect.top + thumbsize + thumbpos; - + partrect.bottom = rect->bottom - arrowsize; + if (thumbsize > 0) + partrect.top = rect->top + thumbpos + thumbsize; + else + partrect.top = rect->top + arrowsize; + if (partrect.bottom > partrect.top) DrawThemeBackground(theme, dc, SBP_LOWERTRACKVERT, lowertrackstate, &partrect, NULL); - } } else { - SIZE leftsize, rightsize; int leftarrowstate, rightarrowstate; if (disabled) { @@ -455,50 +150,29 @@ static void paint_scrollbar(HWND hwnd, HTHEME theme) leftarrowstate = ABS_LEFTNORMAL; rightarrowstate = ABS_RIGHTNORMAL; - if (tracking_win == hwnd) { - if (tracking_hot_part == SCROLL_TOP_ARROW) - leftarrowstate = ABS_LEFTHOT; - else if (tracking_hot_part == SCROLL_BOTTOM_ARROW) - rightarrowstate = ABS_RIGHTHOT; - } + if (hit_test == SCROLL_TOP_ARROW) + leftarrowstate = ABS_LEFTHOT; + else if (hit_test == SCROLL_BOTTOM_ARROW) + rightarrowstate = ABS_RIGHTHOT; } - if (FAILED(GetThemePartSize(theme, dc, SBP_ARROWBTN, leftarrowstate, NULL, TS_DRAW, &leftsize))) { - WARN("Could not get left arrow size.\n"); - return; - } - - if (FAILED(GetThemePartSize(theme, dc, SBP_ARROWBTN, rightarrowstate, NULL, TS_DRAW, &rightsize))) { - WARN("Could not get right arrow size.\n"); - return; - } - - if (r.right - r.left - leftsize.cx - rightsize.cx < SCROLL_MIN_RECT) - leftsize.cx = rightsize.cx = (r.right - r.left - SCROLL_MIN_RECT)/2; - - partrect = r; - partrect.right = partrect.left + leftsize.cx; + partrect = *rect; + partrect.right = partrect.left + arrowsize; DrawThemeBackground(theme, dc, SBP_ARROWBTN, leftarrowstate, &partrect, NULL); - trackrect.left = partrect.right; - - partrect.right = r.right; - partrect.left = partrect.right - rightsize.cx; + partrect.right = rect->right; + partrect.left = partrect.right - arrowsize; DrawThemeBackground(theme, dc, SBP_ARROWBTN, rightarrowstate, &partrect, NULL); - trackrect.right = partrect.left; - - calc_thumb_dimensions(trackrect.right - trackrect.left, &si, &thumbpos, &thumbsize); - if (thumbpos > 0) { - partrect.left = trackrect.left; - partrect.right = partrect.left + thumbpos; + partrect.left = rect->left + arrowsize; + partrect.right = rect->left + thumbpos; DrawThemeBackground(theme, dc, SBP_UPPERTRACKHORZ, uppertrackstate, &partrect, NULL); } if (thumbsize > 0) { - partrect.left = trackrect.left + thumbpos; + partrect.left = rect->left + thumbpos; partrect.right = partrect.left + thumbsize; DrawThemeBackground(theme, dc, SBP_THUMBBTNHORZ, thumbstate, &partrect, NULL); @@ -513,16 +187,18 @@ static void paint_scrollbar(HWND hwnd, HTHEME theme) } } - if (thumbpos + thumbsize < trackrect.right - trackrect.left) { - partrect.right = trackrect.right; - partrect.left = trackrect.left + thumbsize + thumbpos; - + partrect.right = rect->right - arrowsize; + if (thumbsize > 0) + partrect.left = rect->left + thumbpos + thumbsize; + else + partrect.left = rect->left + arrowsize; + if (partrect.right > partrect.left) DrawThemeBackground(theme, dc, SBP_LOWERTRACKHORZ, lowertrackstate, &partrect, NULL); - } } } - EndPaint(hwnd, &ps); + if (bar != SB_CTL) + CloseThemeData(theme); } LRESULT WINAPI UXTHEME_ScrollbarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, @@ -531,7 +207,6 @@ LRESULT WINAPI UXTHEME_ScrollbarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR const WCHAR* themeClass = WC_SCROLLBARW; HTHEME theme; LRESULT result; - POINT pt; TRACE("(%p, 0x%x, %lu, %lu, %d)\n", hwnd, msg, wParam, lParam, unicode); @@ -560,23 +235,6 @@ LRESULT WINAPI UXTHEME_ScrollbarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR * which will do the repaint. */ break; - case WM_PAINT: - theme = GetWindowTheme(hwnd); - if (!theme) return user_api.pScrollBarWndProc(hwnd, msg, wParam, lParam, unicode); - - paint_scrollbar(hwnd, theme); - break; - - case WM_MOUSEMOVE: - case WM_MOUSELEAVE: - theme = GetWindowTheme(hwnd); - if (!theme) return user_api.pScrollBarWndProc(hwnd, msg, wParam, lParam, unicode); - - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - scroll_event(hwnd, theme, msg, pt); - break; - default: return user_api.pScrollBarWndProc(hwnd, msg, wParam, lParam, unicode); } diff --git a/dlls/uxtheme/system.c b/dlls/uxtheme/system.c index 83eda58c460..afae1e23f2b 100644 --- a/dlls/uxtheme/system.c +++ b/dlls/uxtheme/system.c @@ -1230,6 +1230,7 @@ BOOL WINAPI ThemeHooksInstall(void) struct user_api_hook hooks; hooks.pDefDlgProc = UXTHEME_DefDlgProc; + hooks.pScrollBarDraw = UXTHEME_ScrollBarDraw; hooks.pScrollBarWndProc = UXTHEME_ScrollbarWndProc; return RegisterUserApiHook(&hooks, &user_api); } diff --git a/dlls/uxtheme/uxthemedll.h b/dlls/uxtheme/uxthemedll.h index 67932f22f88..4b8f95764d6 100644 --- a/dlls/uxtheme/uxthemedll.h +++ b/dlls/uxtheme/uxthemedll.h @@ -103,6 +103,10 @@ extern void UXTHEME_UninitSystem(void) DECLSPEC_HIDDEN; extern struct user_api_hook user_api DECLSPEC_HIDDEN; LRESULT WINAPI UXTHEME_DefDlgProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL unicode) DECLSPEC_HIDDEN; +void WINAPI UXTHEME_ScrollBarDraw(HWND hwnd, HDC dc, INT bar, enum SCROLL_HITTEST hit_test, + const struct SCROLL_TRACKING_INFO *tracking_info, + BOOL draw_arrows, BOOL draw_interior, RECT *rect, INT arrowsize, + INT thumbpos, INT thumbsize, BOOL vertical) DECLSPEC_HIDDEN; LRESULT WINAPI UXTHEME_ScrollbarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode) DECLSPEC_HIDDEN; diff --git a/include/winuser.h b/include/winuser.h index c738e345fab..260024d7e91 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -4409,9 +4409,35 @@ WORD WINAPI SYSTEM_KillSystemTimer( WORD ); WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput ); /* Uxtheme hook functions and struct */ + +/* Scroll bar hit testing */ +enum SCROLL_HITTEST +{ + SCROLL_NOWHERE, /* Outside the scroll bar */ + SCROLL_TOP_ARROW, /* Top or left arrow */ + SCROLL_TOP_RECT, /* Rectangle between the top arrow and the thumb */ + SCROLL_THUMB, /* Thumb rectangle */ + SCROLL_BOTTOM_RECT, /* Rectangle between the thumb and the bottom arrow */ + SCROLL_BOTTOM_ARROW /* Bottom or right arrow */ +}; + +/* Scroll bar tracking information */ +struct SCROLL_TRACKING_INFO +{ + HWND win; /* Tracking window */ + INT bar; /* SB_HORZ/SB_VERT/SB_CTL */ + INT thumb_pos; /* Thumb position */ + INT thumb_val; /* Current thumb value from thumb position */ + BOOL vertical; /* Is scroll bar vertical */ + enum SCROLL_HITTEST hit_test; /* Hit Test code of the last button-down event */ +}; + struct user_api_hook { LRESULT (WINAPI *pDefDlgProc)(HWND, UINT, WPARAM, LPARAM, BOOL); + void (WINAPI *pScrollBarDraw)(HWND, HDC, INT, enum SCROLL_HITTEST, + const struct SCROLL_TRACKING_INFO *, BOOL, BOOL, RECT *, INT, INT, + INT, BOOL); LRESULT (WINAPI *pScrollBarWndProc)(HWND, UINT, WPARAM, LPARAM, BOOL); };