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