Mark Harmstone : comctl32: Paint themed scrollbars.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Mar 3 09:42:11 CST 2015


Module: wine
Branch: master
Commit: d7c206972175f8b2eee90358e8c3f12c9973285b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d7c206972175f8b2eee90358e8c3f12c9973285b

Author: Mark Harmstone <hellas at burntcomma.com>
Date:   Tue Mar  3 07:44:42 2015 +0000

comctl32: Paint themed scrollbars.

---

 dlls/comctl32/theme_scrollbar.c | 231 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 231 insertions(+)

diff --git a/dlls/comctl32/theme_scrollbar.c b/dlls/comctl32/theme_scrollbar.c
index ed2c051..9be8384 100644
--- a/dlls/comctl32/theme_scrollbar.c
+++ b/dlls/comctl32/theme_scrollbar.c
@@ -32,8 +32,232 @@
 #include "comctl32.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
+
 WINE_DEFAULT_DEBUG_CHANNEL(theme_scroll);
 
+static void calc_thumb_dimensions(unsigned int size, SCROLLINFO *si, unsigned int *thumbpos, unsigned int *thumbsize)
+{
+    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 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);
+
+    GetWindowRect(hwnd, &r);
+    OffsetRect(&r, -r.left, -r.top);
+
+    dc = BeginPaint(hwnd, &ps);
+
+    if (style & SBS_SIZEBOX || style & SBS_SIZEGRIP) {
+        int state;
+
+        if (style & SBS_SIZEBOXTOPLEFTALIGN)
+            state = SZB_TOPLEFTALIGN;
+        else
+            state = SZB_RIGHTALIGN;
+
+        DrawThemeBackground(theme, dc, SBP_SIZEBOX, state, &r, NULL);
+    } else {
+        SCROLLBARINFO sbi;
+        SCROLLINFO si;
+        unsigned int thumbpos, thumbsize;
+        int uppertrackstate, lowertrackstate, thumbstate;
+        RECT partrect, trackrect;
+        SIZE grippersize;
+
+        sbi.cbSize = sizeof(sbi);
+        GetScrollBarInfo(hwnd, OBJID_CLIENT, &sbi);
+
+        si.cbSize = sizeof(si);
+        si.fMask = SIF_ALL;
+        GetScrollInfo(hwnd, SB_CTL, &si);
+
+        trackrect = r;
+
+        if (disabled) {
+            uppertrackstate = SCRBS_DISABLED;
+            lowertrackstate = SCRBS_DISABLED;
+            thumbstate = SCRBS_DISABLED;
+        } else {
+            uppertrackstate = SCRBS_NORMAL;
+            lowertrackstate = SCRBS_NORMAL;
+            thumbstate = SCRBS_NORMAL;
+        }
+
+        if (vertical) {
+            SIZE upsize, downsize;
+            int uparrowstate, downarrowstate;
+
+            if (disabled) {
+                uparrowstate = ABS_UPDISABLED;
+                downarrowstate = ABS_DOWNDISABLED;
+            } else {
+                uparrowstate = ABS_UPNORMAL;
+                downarrowstate = ABS_DOWNNORMAL;
+            }
+
+            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;
+            DrawThemeBackground(theme, dc, SBP_ARROWBTN, uparrowstate, &partrect, NULL);
+
+            trackrect.top = partrect.bottom;
+
+            partrect.bottom = r.bottom;
+            partrect.top = partrect.bottom - downsize.cy;
+            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;
+
+                DrawThemeBackground(theme, dc, SBP_UPPERTRACKVERT, uppertrackstate, &partrect, NULL);
+            }
+
+            if (thumbsize > 0) {
+                partrect.top = trackrect.top + thumbpos;
+                partrect.bottom = partrect.top + thumbsize;
+
+                DrawThemeBackground(theme, dc, SBP_THUMBBTNVERT, thumbstate, &partrect, NULL);
+
+                if (SUCCEEDED(GetThemePartSize(theme, dc, SBP_GRIPPERVERT, thumbstate, NULL, TS_DRAW, &grippersize))) {
+                    MARGINS margins;
+
+                    if (SUCCEEDED(GetThemeMargins(theme, dc, SBP_THUMBBTNVERT, thumbstate, TMT_CONTENTMARGINS, &partrect, &margins))) {
+                        if (grippersize.cy <= (thumbsize - margins.cyTopHeight - margins.cyBottomHeight))
+                            DrawThemeBackground(theme, dc, SBP_GRIPPERVERT, thumbstate, &partrect, NULL);
+                    }
+                }
+            }
+
+            if (thumbpos + thumbsize < trackrect.bottom - trackrect.top) {
+                partrect.bottom = trackrect.bottom;
+                partrect.top = trackrect.top + thumbsize + thumbpos;
+
+                DrawThemeBackground(theme, dc, SBP_LOWERTRACKVERT, lowertrackstate, &partrect, NULL);
+            }
+        } else {
+            SIZE leftsize, rightsize;
+            int leftarrowstate, rightarrowstate;
+
+            if (disabled) {
+                leftarrowstate = ABS_LEFTDISABLED;
+                rightarrowstate = ABS_RIGHTDISABLED;
+            } else {
+                leftarrowstate = ABS_LEFTNORMAL;
+                rightarrowstate = ABS_RIGHTNORMAL;
+            }
+
+            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;
+            DrawThemeBackground(theme, dc, SBP_ARROWBTN, leftarrowstate, &partrect, NULL);
+
+            trackrect.left = partrect.right;
+
+            partrect.right = r.right;
+            partrect.left = partrect.right - rightsize.cx;
+            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;
+
+                DrawThemeBackground(theme, dc, SBP_UPPERTRACKHORZ, uppertrackstate, &partrect, NULL);
+            }
+
+            if (thumbsize > 0) {
+                partrect.left = trackrect.left + thumbpos;
+                partrect.right = partrect.left + thumbsize;
+
+                DrawThemeBackground(theme, dc, SBP_THUMBBTNHORZ, thumbstate, &partrect, NULL);
+
+                if (SUCCEEDED(GetThemePartSize(theme, dc, SBP_GRIPPERHORZ, thumbstate, NULL, TS_DRAW, &grippersize))) {
+                    MARGINS margins;
+
+                    if (SUCCEEDED(GetThemeMargins(theme, dc, SBP_THUMBBTNHORZ, thumbstate, TMT_CONTENTMARGINS, &partrect, &margins))) {
+                        if (grippersize.cx <= (thumbsize - margins.cxLeftWidth - margins.cxRightWidth))
+                            DrawThemeBackground(theme, dc, SBP_GRIPPERHORZ, thumbstate, &partrect, NULL);
+                    }
+                }
+            }
+
+            if (thumbpos + thumbsize < trackrect.right - trackrect.left) {
+                partrect.right = trackrect.right;
+                partrect.left = trackrect.left + thumbsize + thumbpos;
+
+                DrawThemeBackground(theme, dc, SBP_LOWERTRACKHORZ, lowertrackstate, &partrect, NULL);
+            }
+        }
+    }
+
+    EndPaint(hwnd, &ps);
+}
+
 LRESULT CALLBACK THEMING_ScrollbarSubclassProc (HWND hwnd, UINT msg,
                                                 WPARAM wParam, LPARAM lParam,
                                                 ULONG_PTR dwRefData)
@@ -68,6 +292,13 @@ LRESULT CALLBACK THEMING_ScrollbarSubclassProc (HWND hwnd, UINT msg,
              * which will do the repaint. */
             break;
 
+        case WM_PAINT:
+            theme = GetWindowTheme(hwnd);
+            if (!theme) return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam);
+
+            paint_scrollbar(hwnd, theme);
+            break;
+
         default:
             return THEMING_CallOriginalClass(hwnd, msg, wParam, lParam);
     }




More information about the wine-cvs mailing list