Mark Harmstone : comctl32: Draw hot parts of themed scrollbars.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Mar 5 09:53:24 CST 2015
Module: wine
Branch: master
Commit: a20c920bbdd31394220370c8aac695cb189b4cc0
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a20c920bbdd31394220370c8aac695cb189b4cc0
Author: Mark Harmstone <hellas at burntcomma.com>
Date: Tue Mar 3 21:56:37 2015 +0000
comctl32: Draw hot parts of themed scrollbars.
---
dlls/comctl32/theme_scrollbar.c | 195 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 195 insertions(+)
diff --git a/dlls/comctl32/theme_scrollbar.c b/dlls/comctl32/theme_scrollbar.c
index 5a44994..bb42267 100644
--- a/dlls/comctl32/theme_scrollbar.c
+++ b/dlls/comctl32/theme_scrollbar.c
@@ -48,6 +48,9 @@ enum SCROLL_HITTEST
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)
@@ -149,6 +152,164 @@ static enum SCROLL_HITTEST hit_test(HWND hwnd, HTHEME theme, POINT pt)
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;
@@ -197,6 +358,15 @@ static void paint_scrollbar(HWND hwnd, HTHEME theme)
uppertrackstate = SCRBS_NORMAL;
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 (vertical) {
@@ -209,6 +379,13 @@ static void paint_scrollbar(HWND hwnd, HTHEME theme)
} else {
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 (FAILED(GetThemePartSize(theme, dc, SBP_ARROWBTN, uparrowstate, NULL, TS_DRAW, &upsize))) {
@@ -277,6 +454,13 @@ static void paint_scrollbar(HWND hwnd, HTHEME theme)
} else {
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 (FAILED(GetThemePartSize(theme, dc, SBP_ARROWBTN, leftarrowstate, NULL, TS_DRAW, &leftsize))) {
@@ -348,6 +532,7 @@ LRESULT CALLBACK THEMING_ScrollbarSubclassProc (HWND hwnd, UINT msg,
const WCHAR* themeClass = WC_SCROLLBARW;
HTHEME theme;
LRESULT result;
+ POINT pt;
TRACE("(%p, 0x%x, %lu, %lu, %lu)\n", hwnd, msg, wParam, lParam, dwRefData);
@@ -382,6 +567,16 @@ LRESULT CALLBACK THEMING_ScrollbarSubclassProc (HWND hwnd, UINT msg,
paint_scrollbar(hwnd, theme);
break;
+ case WM_MOUSEMOVE:
+ case WM_MOUSELEAVE:
+ theme = GetWindowTheme(hwnd);
+ if (!theme) return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam);
+
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ scroll_event(hwnd, theme, msg, pt);
+ break;
+
default:
return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam);
}
More information about the wine-cvs
mailing list