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