Changelog: controls.h - improve the scroll bar nonclient separation nonclient.c - remove NC_TrackScrollBar and use scrollbar WINAPI routine scrollbar.c - unified drawing code - simpler event processing logic - minimized drawing - better conformance to windows on LINEUP and LINEDOWN events The patch was developed without CVS access use patch -p1 from within the top level wine directory to apply Requires previous scroll patches license: X11 Andrew --- wine-20020804/dlls/user/controls.h Sun Mar 10 07:44:30 2002 +++ wine/dlls/user/controls.h Thu Sep 19 18:22:23 2002 @@ -63,10 +63,8 @@ extern UINT MENU_FindSubMenu( HMENU *hmenu, HMENU hSubTarget ); /* scrollbar */ -extern void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, INT nBar, BOOL arrows, BOOL interior ); -extern void SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt ); -extern INT SCROLL_SetNCSbState( HWND hwnd, int vMin, int vMax, int vPos, - int hMin, int hMax, int hPos ); +extern void SCROLL_PaintScrollBar(HWND hwnd, INT nBar); +extern void SCROLL_HandleScrollEvent(HWND hwnd, INT nBar, UINT msg, LPARAM lParam); /* combo box */ --- wine-20020804/windows/nonclient.c Sat Jun 1 07:06:54 2002 +++ wine/windows/nonclient.c Fri Sep 20 12:22:16 2002 @@ -1459,9 +1459,9 @@ /* Draw the scroll-bars */ if (dwStyle & WS_VSCROLL) - SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE ); + SCROLL_PaintScrollBar(hwnd, SB_VERT); if (dwStyle & WS_HSCROLL) - SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE ); + SCROLL_PaintScrollBar(hwnd, SB_HORZ); /* Draw the "size-box" */ @@ -1613,12 +1613,9 @@ DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); /* Draw the scroll-bars */ - - if (dwStyle & WS_VSCROLL) - SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE ); - if (dwStyle & WS_HSCROLL) - SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE ); - + if (dwStyle & WS_VSCROLL) SCROLL_PaintScrollBar(hwnd, SB_VERT); + if (dwStyle & WS_HSCROLL) SCROLL_PaintScrollBar(hwnd, SB_HORZ); + /* Draw the "size-box" */ if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL)) { @@ -1649,7 +1646,7 @@ WINPOS_RedrawIconTitle( hwnd ); else if (TWEAK_WineLook == WIN31_LOOK) NC_DoNCPaint( hwnd, clip, FALSE ); - else + else NC_DoNCPaint95( hwnd, clip, FALSE ); } return 0; @@ -1962,29 +1959,6 @@ /*********************************************************************** - * NC_TrackScrollBar - * - * Track a mouse button press on the horizontal or vertical scroll-bar. - */ -static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt ) -{ - INT scrollbar; - - if ((wParam & 0xfff0) == SC_HSCROLL) - { - if ((wParam & 0x0f) != HTHSCROLL) return; - scrollbar = SB_HORZ; - } - else /* SC_VSCROLL */ - { - if ((wParam & 0x0f) != HTVSCROLL) return; - scrollbar = SB_VERT; - } - SCROLL_TrackScrollBar( hwnd, scrollbar, pt ); -} - - -/*********************************************************************** * NC_HandleNCLButtonDown * * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc(). @@ -2146,14 +2120,14 @@ return SendMessageA( hwnd, WM_CLOSE, 0, 0 ); case SC_VSCROLL: + if ((wParam & 0x0f) == HTVSCROLL) + SCROLL_HandleScrollEvent(hwnd, SB_VERT, WM_LBUTTONDOWN, lParam); + break; + case SC_HSCROLL: - { - POINT pt; - pt.x = SLOWORD(lParam); - pt.y = SHIWORD(lParam); - NC_TrackScrollBar( hwnd, wParam, pt ); - } - break; + if ((wParam & 0x0f) == HTHSCROLL) + SCROLL_HandleScrollEvent(hwnd, SB_HORZ, WM_LBUTTONDOWN, lParam); + break; case SC_MOUSEMENU: { --- wine-20020904/controls/scroll.c Tue Oct 8 19:22:47 2002 +++ wine/controls/scroll.c Tue Oct 8 19:13:57 2002 @@ -57,15 +57,72 @@ HBITMAP disabled; /* arrow for disabled state */ } SCROLL_ARROWS, *LPSCROLL_ARROWS; + +/********************************************************************* + * scrollbar extermity parameters (one arrow) + * + * Contains the arrow and its pressed state and the associated + * limiting cordinate + */ +typedef struct +{ + INT *coord; /* coordinate of the limiting extremity */ + INT flags; /* pressed state of the extermity */ + LPSCROLL_ARROWS arrow; /* arrows collection */ +} SCROLL_EXTEMITY, *LPSCROLL_EXTREMITY; + + +/********************************************************************* + * scrollbar (display information for drawing a single scroll bar) + * + * Lives as long as a scroll draw operation + */ +typedef struct +{ + RECT rect; /* the bounding rectangle of the control */ + RECT extended; /* the bounding rectangle thumb movement */ + UINT hit; /* windows message for bar position */ + INT arrow; /* the arrow size */ + INT thumb; /* the thumb size */ + INT pos; /* the thumb postion */ + INT pixels; /* length of the long dimension of the bar */ + INT direction; /* windows message for bar direction */ + BOOL drawable; /* scroll bar is a non empty rect */ + BOOL inside; /* event was inside scroll bar */ + BOOL lastInside; /* last event was inside scroll bar */ + POINT offset; /* offset of the scrollbar in the client window */ + SCROLL_EXTEMITY start; /* the start of the long extent of the bar */ + SCROLL_EXTEMITY end; /* the end of the long extent of the bar */ + LPSCROLLBAR_INFO info; /* the info for the scroll bar */ +} SCROLL_BAR, *LPSCROLL_BAR; + #define SCROLL_MIN_RECT 4 /* Minimum size of rectangle between arrows */ #define SCROLL_MIN_THUMB 6 /* Minimum size of the thumb in pixels */ #define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition */ #define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */ #define SCROLL_TIMER 0 /* Scroll timer id */ +#define SCROLL_NO_POS (1 << 30) /* Dummy value for unkown thumb position */ -#define GET_ARROW(arrow, inactive, press) \ - ((inactive) ? (arrow)->disabled : ((press) ? (arrow)->pressed: (arrow)->normal)) - +/* Determine if the whole bar is disabled */ +#define SCROLL_DISABLED(info) \ + ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) + +/* Determine if the bar has been hit inside and in the given position */ +#define SCROLL_HIT(bar, position) \ + ((bar->inside) && (bar->hit == position)) + +/* Determine the correct pattern for the fill based on pressed state */ +#define SCROLL_PATTERN(bar, position) \ + ((SCROLL_HIT(bar, position)) ? 0x0f0000 : PATCOPY) + +/* Determine if the scroll bar has changed */ +#define SCROLL_CHANGED(bar) ((bar)->inside != (bar)->lastInside) + +/* Determine if the arrow should be drawn and call to draw it */ +#define SCROLL_DRAW_ARROW(hdc, bar, arr, current, other) \ + if (bar->arrow && SCROLL_CHANGED(bar) && \ + ((bar->inside && bar->hit != other) || (bar->hit == current))) \ + SCROLL_DrawArrow(hdc, &(bar->rect), arr, SCROLL_HIT(bar, current)); /* Determine if the info is valid */ #define SCROLL_INFO_INVALID(info) \ @@ -73,9 +130,6 @@ ((info->cbSize != sizeof(*info)) && \ (info->cbSize != sizeof(*info) - sizeof(info->nTrackPos)))) - /* Overlap between arrows and thumb */ -#define SCROLL_ARROW_THUMB_OVERLAP ((TWEAK_WineLook == WIN31_LOOK) ? 1 : 0) - /********************************************************************* * scrollbar arrow collections (used by Win 31 only) */ @@ -84,42 +138,8 @@ static SCROLL_ARROWS hLeft; /* Arrow images for left arrow */ static SCROLL_ARROWS hRight; /* Arrow images for right arrow */ +static SCROLL_BAR trackBar; /* The bar structure used during tracking */ - /* 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 */ -}; - - /* What to do after SCROLL_SetScrollInfo() */ -#define SA_SSI_HIDE 0x0001 -#define SA_SSI_SHOW 0x0002 -#define SA_SSI_REFRESH 0x0004 -#define SA_SSI_REPAINT_ARROWS 0x0008 - - /* Thumb-tracking info */ -static HWND SCROLL_TrackingWin = 0; -static INT SCROLL_TrackingBar = 0; -static INT SCROLL_TrackingPos = 0; -static INT SCROLL_TrackingVal = 0; - /* Hit test code of the last button-down event */ -static enum SCROLL_HITTEST SCROLL_trackHitTest; -static BOOL SCROLL_trackVertical; - - /* Is the moving thumb being displayed? */ -static BOOL SCROLL_MovingThumb = FALSE; - - /* Local functions */ -static void SCROLL_DrawInterior_9x( HWND hwnd, HDC hdc, INT nBar, - RECT *rect, INT arrowSize, - INT thumbSize, INT thumbPos, - UINT flags, BOOL vertical, - BOOL top_selected, BOOL bottom_selected ); static LRESULT WINAPI ScrollBarWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); @@ -221,686 +241,181 @@ return info; } -/*********************************************************************** - * SCROLL_GetScrollBarRect - * - * Compute the scroll bar rectangle, in drawing coordinates (i.e. client - * coords for SB_CTL, window coords for SB_VERT and SB_HORZ). - * 'arrowSize' returns the width or height of an arrow (depending on - * the orientation of the scrollbar), 'thumbSize' returns the size of - * the thumb, and 'thumbPos' returns the position of the thumb - * relative to the left or to the top. - * Return TRUE if the scrollbar is vertical, FALSE if horizontal. - */ -static BOOL SCROLL_GetScrollBarRect( HWND hwnd, INT nBar, RECT *lprect, - INT *arrowSize, INT *thumbSize, - INT *thumbPos ) -{ - INT pixels; - BOOL vertical; - WND *wndPtr = WIN_FindWndPtr( hwnd ); - - switch(nBar) - { - case SB_HORZ: - lprect->left = wndPtr->rectClient.left - wndPtr->rectWindow.left; - lprect->top = wndPtr->rectClient.bottom - wndPtr->rectWindow.top; - lprect->right = wndPtr->rectClient.right - wndPtr->rectWindow.left; - lprect->bottom = lprect->top + GetSystemMetrics(SM_CYHSCROLL); - if(wndPtr->dwStyle & WS_BORDER) { - lprect->left--; - lprect->right++; - } else if(wndPtr->dwStyle & WS_VSCROLL) - lprect->right++; - vertical = FALSE; - break; - - case SB_VERT: - lprect->left = wndPtr->rectClient.right - wndPtr->rectWindow.left; - lprect->top = wndPtr->rectClient.top - wndPtr->rectWindow.top; - lprect->right = lprect->left + GetSystemMetrics(SM_CXVSCROLL); - lprect->bottom = wndPtr->rectClient.bottom - wndPtr->rectWindow.top; - if(wndPtr->dwStyle & WS_BORDER) { - lprect->top--; - lprect->bottom++; - } else if(wndPtr->dwStyle & WS_HSCROLL) - lprect->bottom++; - vertical = TRUE; - break; - - case SB_CTL: - GetClientRect( hwnd, lprect ); - vertical = ((wndPtr->dwStyle & SBS_VERT) != 0); - break; - - default: - WIN_ReleaseWndPtr(wndPtr); - return FALSE; - } - - if (vertical) pixels = lprect->bottom - lprect->top; - else pixels = lprect->right - lprect->left; - - if (pixels <= 2*GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT) - { - if (pixels > SCROLL_MIN_RECT) - *arrowSize = (pixels - SCROLL_MIN_RECT) / 2; - else - *arrowSize = 0; - *thumbPos = *thumbSize = 0; - } - else - { - SCROLLBAR_INFO *info = SCROLL_GetScrollInfo( hwnd, nBar ); - - *arrowSize = GetSystemMetrics(SM_CXVSCROLL); - pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)); - - if (info->page) - { - *thumbSize = MulDiv(pixels,info->page,(info->maxVal-info->minVal+1)); - if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB; - } - else *thumbSize = GetSystemMetrics(SM_CXVSCROLL); - - if (((pixels -= *thumbSize ) < 0) || - ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)) - { - /* Rectangle too small or scrollbar disabled -> no thumb */ - *thumbPos = *thumbSize = 0; - } - else - { - INT max = info->maxVal - max( info->page-1, 0 ); - if (info->minVal >= max) - *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP; - else - *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP - + MulDiv(pixels, (info->curVal-info->minVal),(max - info->minVal)); - } - } - WIN_ReleaseWndPtr(wndPtr); - return vertical; -} /*********************************************************************** - * SCROLL_GetThumbVal + * SCROLL_GetThumb * - * Compute the current scroll position based on the thumb position in pixels - * from the top of the scroll-bar. - */ -static UINT SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT *rect, - BOOL vertical, INT pos ) -{ - INT thumbSize; - INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left; - - if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0) - return infoPtr->minVal; - - if (infoPtr->page) - { - thumbSize = MulDiv(pixels,infoPtr->page,(infoPtr->maxVal-infoPtr->minVal+1)); - if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB; - } - else thumbSize = GetSystemMetrics(SM_CXVSCROLL); - - if ((pixels -= thumbSize) <= 0) return infoPtr->minVal; - - pos = max( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) ); - if (pos > pixels) pos = pixels; - - if (!infoPtr->page) pos *= infoPtr->maxVal - infoPtr->minVal; - else pos *= infoPtr->maxVal - infoPtr->minVal - infoPtr->page + 1; - return infoPtr->minVal + ((pos + pixels / 2) / pixels); -} - -/*********************************************************************** - * SCROLL_PtInRectEx - */ -static BOOL SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical ) -{ - RECT rect = *lpRect; - - if (vertical) - { - rect.left -= lpRect->right - lpRect->left; - rect.right += lpRect->right - lpRect->left; - } - else - { - rect.top -= lpRect->bottom - lpRect->top; - rect.bottom += lpRect->bottom - lpRect->top; - } - return PtInRect( &rect, pt ); -} - -/*********************************************************************** - * SCROLL_ClipPos - */ -static POINT SCROLL_ClipPos( LPRECT lpRect, POINT pt ) -{ - if( pt.x < lpRect->left ) - pt.x = lpRect->left; - else - if( pt.x > lpRect->right ) - pt.x = lpRect->right; - - if( pt.y < lpRect->top ) - pt.y = lpRect->top; - else - if( pt.y > lpRect->bottom ) - pt.y = lpRect->bottom; - - return pt; -} + * Determine the critical sizes and positions of arrows and thumb given + * the bar properties including sizes desired places etc + * + * RETURNS + * bar->arrow size the arrow (width or height depending on orientation) + * bar->thumb size of the thumb + * bar->pos position of the thumb (relative to the left or top arrow) + * and + * return the proposed new curVal for the scroll bar + */ +static UINT SCROLL_GetThumb( +INT scrollPos /* [in] current or desired scroll position */, +LPSCROLL_BAR bar /* [in/out] size and position of the bar components */) +{ + INT range = bar->info->maxVal - bar->info->minVal; + INT pixels = bar->pixels; + UINT curVal = 0; + + /* set the default return values */ + bar->pos = bar->arrow = bar->thumb = 0; + + if (pixels > SCROLL_MIN_RECT + GetSystemMetrics(SM_CYHSCROLL) * 2) + { + /* set bar display properties */ + bar->arrow = GetSystemMetrics(SM_CYHSCROLL); + /* using only the non arrow pixels */ + pixels -= 2 * bar->arrow; -/*********************************************************************** - * SCROLL_HitTest - * - * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!). - */ -static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, INT nBar, - POINT pt, BOOL bDragging ) -{ - INT arrowSize, thumbSize, thumbPos; - RECT rect; - - BOOL vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect, - &arrowSize, &thumbSize, &thumbPos ); - - if ( (bDragging && !SCROLL_PtInRectEx( &rect, pt, vertical )) || - (!PtInRect( &rect, pt )) ) return SCROLL_NOWHERE; - - if (vertical) - { - if (pt.y < rect.top + arrowSize) return SCROLL_TOP_ARROW; - if (pt.y >= rect.bottom - arrowSize) return SCROLL_BOTTOM_ARROW; - if (!thumbPos) return SCROLL_TOP_RECT; - pt.y -= rect.top; - if (pt.y < thumbPos) return SCROLL_TOP_RECT; - if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT; - } - else /* horizontal */ - { - if (pt.x < rect.left + arrowSize) return SCROLL_TOP_ARROW; - if (pt.x >= rect.right - arrowSize) return SCROLL_BOTTOM_ARROW; - if (!thumbPos) return SCROLL_TOP_RECT; - pt.x -= rect.left; - if (pt.x < thumbPos) return SCROLL_TOP_RECT; - if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT; - } - return SCROLL_THUMB; -} + /* set thumb size */ + if (bar->info->page) + bar->thumb = MulDiv(pixels, bar->info->page, range + 1); + else + bar->thumb = GetSystemMetrics(SM_CXVSCROLL); + + /* check thumb not too small */ + if (bar->thumb < SCROLL_MIN_THUMB) + bar->thumb = SCROLL_MIN_THUMB; + + /* scroll bar size ok and enabled */ + range -= bar->info->page - 1; + pixels -= bar->thumb; + + /* move thumb */ + if ((pixels <= 0) || SCROLL_DISABLED(bar->info)) + bar->thumb = 0; + else if (scrollPos != SCROLL_NO_POS) + { + /* make the pos reasonable then calculate curVal */ + if (scrollPos < 0) scrollPos = 0; + else if (scrollPos > pixels) scrollPos = pixels; + bar->pos = scrollPos; + curVal = MulDiv(range, scrollPos, pixels); + } + else if (range > 0) + { + /* use curVal to determine bar position */ + curVal = bar->info->curVal - bar->info->minVal; + bar->pos = MulDiv(pixels, curVal, range); + } + } + else if (pixels > SCROLL_MIN_RECT) + bar->arrow = (pixels - SCROLL_MIN_RECT) / 2; + curVal += bar->info->minVal; + TRACE("pixels=%d pos=%d thumb=%d curVal=%d range=%d\n", + bar->pixels, bar->pos, bar->thumb, curVal, range); -/*********************************************************************** - * SCROLL_DrawArrows - * - * Draw the scroll bar arrows. - */ -static void SCROLL_DrawArrows_9x( HDC hdc, SCROLLBAR_INFO *infoPtr, - RECT *rect, INT arrowSize, BOOL vertical, - BOOL top_pressed, BOOL bottom_pressed ) -{ - RECT r; - - r = *rect; - if( vertical ) - r.bottom = r.top + arrowSize; - else - r.right = r.left + arrowSize; - - DrawFrameControl( hdc, &r, DFC_SCROLL, - (vertical ? DFCS_SCROLLUP : DFCS_SCROLLLEFT) - | (top_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0 ) - | (infoPtr->flags&ESB_DISABLE_LTUP ? DFCS_INACTIVE : 0 ) ); - - r = *rect; - if( vertical ) - r.top = r.bottom-arrowSize; - else - r.left = r.right-arrowSize; - - DrawFrameControl( hdc, &r, DFC_SCROLL, - (vertical ? DFCS_SCROLLDOWN : DFCS_SCROLLRIGHT) - | (bottom_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0 ) - | (infoPtr->flags&ESB_DISABLE_RTDN ? DFCS_INACTIVE : 0) ); -} - -static void SCROLL_DrawArrows_31( HDC hdc, SCROLLBAR_INFO *infoPtr, - RECT *rect, INT arrowSize, BOOL vertical, - BOOL top_pressed, BOOL bottom_pressed ) -{ - HDC hdcMem = CreateCompatibleDC( hdc ); - HBITMAP hbmpPrev = SelectObject( hdcMem, GET_ARROW(vertical ? &hUp : &hLeft, - infoPtr->flags & ESB_DISABLE_UP, top_pressed)); - - if (!hUp.normal) SCROLL_LoadBitmaps(); - SetStretchBltMode( hdc, STRETCH_DELETESCANS ); - StretchBlt( hdc, rect->left, rect->top, - vertical ? rect->right-rect->left : arrowSize, - vertical ? arrowSize : rect->bottom-rect->top, - hdcMem, 0, 0, - GetSystemMetrics(SM_CXVSCROLL),GetSystemMetrics(SM_CYHSCROLL), - SRCCOPY ); - - SelectObject( hdcMem, GET_ARROW(vertical ? &hDown : &hRight, - infoPtr->flags & ESB_DISABLE_DOWN, bottom_pressed)); - - if (vertical) - StretchBlt( hdc, rect->left, rect->bottom - arrowSize, - rect->right - rect->left, arrowSize, - hdcMem, 0, 0, - GetSystemMetrics(SM_CXVSCROLL),GetSystemMetrics(SM_CYHSCROLL), - SRCCOPY ); - else - StretchBlt( hdc, rect->right - arrowSize, rect->top, - arrowSize, rect->bottom - rect->top, - hdcMem, 0, 0, - GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL), - SRCCOPY ); - SelectObject( hdcMem, hbmpPrev ); - DeleteDC( hdcMem ); -} - -static void SCROLL_DrawArrows( HDC hdc, SCROLLBAR_INFO *infoPtr, - RECT *rect, INT arrowSize, BOOL vertical, - BOOL top_pressed, BOOL bottom_pressed ) -{ - if( TWEAK_WineLook == WIN31_LOOK ) - SCROLL_DrawArrows_31( hdc, infoPtr, rect, arrowSize, - vertical, top_pressed,bottom_pressed ); - else - SCROLL_DrawArrows_9x( hdc, infoPtr, rect, arrowSize, - vertical, top_pressed,bottom_pressed ); + return curVal; } /*********************************************************************** - * SCROLL_DrawMovingThumb + * SCROLL_GetScrollBar * - * Draw the moving thumb rectangle. + * Compute the scroll bar rectangle, in drawing coordinates (i.e. client + * coords for SB_CTL, window coords for SB_VERT and SB_HORZ). + * + * RETURNS + * The scroll bar structure */ -static void SCROLL_DrawMovingThumb_31( HDC hdc, RECT *rect, BOOL vertical, - INT arrowSize, INT thumbSize ) +static BOOL SCROLL_GetScrollBar( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */, +LPSCROLLBAR_INFO info /* [in] The place of the thumb */, +LPSCROLL_BAR bar /* [out] The bar positions and charactersistics */) { - RECT r = *rect; - if (vertical) - { - r.top += SCROLL_TrackingPos; - if (r.top < rect->top + arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - r.top = rect->top + arrowSize - SCROLL_ARROW_THUMB_OVERLAP; - if (r.top + thumbSize > - rect->bottom - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP)) - r.top = rect->bottom - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - - thumbSize; - r.bottom = r.top + thumbSize; - } - else - { - r.left += SCROLL_TrackingPos; - if (r.left < rect->left + arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - r.left = rect->left + arrowSize - SCROLL_ARROW_THUMB_OVERLAP; - if (r.left + thumbSize > - rect->right - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP)) - r.left = rect->right - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - - thumbSize; - r.right = r.left + thumbSize; - } - - DrawFocusRect( hdc, &r ); - SCROLL_MovingThumb = !SCROLL_MovingThumb; -} - -static void SCROLL_DrawMovingThumb_9x( HDC hdc, RECT *rect, BOOL vertical, - INT arrowSize, INT thumbSize ) -{ - INT pos = SCROLL_TrackingPos; - INT max_size; - - if( vertical ) - max_size = rect->bottom - rect->top; - else - max_size = rect->right - rect->left; - - max_size -= (arrowSize-SCROLL_ARROW_THUMB_OVERLAP) + thumbSize; - - if( pos < (arrowSize-SCROLL_ARROW_THUMB_OVERLAP) ) - pos = (arrowSize-SCROLL_ARROW_THUMB_OVERLAP); - else if( pos > max_size ) - pos = max_size; - - SCROLL_DrawInterior_9x( SCROLL_TrackingWin, hdc, SCROLL_TrackingBar, - rect, arrowSize, thumbSize, pos, - 0, vertical, FALSE, FALSE ); - - SCROLL_MovingThumb = !SCROLL_MovingThumb; -} - -static void SCROLL_DrawMovingThumb( HDC hdc, RECT *rect, BOOL vertical, - INT arrowSize, INT thumbSize ) -{ - if( TWEAK_WineLook == WIN31_LOOK ) - SCROLL_DrawMovingThumb_31( hdc, rect, vertical, arrowSize, thumbSize ); - else - SCROLL_DrawMovingThumb_9x( hdc, rect, vertical, arrowSize, thumbSize ); -} - -/*********************************************************************** - * SCROLL_DrawInterior - * - * Draw the scroll bar interior (everything except the arrows). - */ -static void SCROLL_DrawInterior_9x( HWND hwnd, HDC hdc, INT nBar, - RECT *rect, INT arrowSize, - INT thumbSize, INT thumbPos, - UINT flags, BOOL vertical, - BOOL top_selected, BOOL bottom_selected ) -{ - RECT r; - HPEN hSavePen; - HBRUSH hSaveBrush,hBrush; - - /* Only scrollbar controls send WM_CTLCOLORSCROLLBAR. - * The window-owned scrollbars need to call DEFWND_ControlColor - * to correctly setup default scrollbar colors - */ - if (nBar == SB_CTL) - { - hBrush = (HBRUSH)SendMessageA( GetParent(hwnd), WM_CTLCOLORSCROLLBAR, - (WPARAM)hdc,(LPARAM)hwnd); - } - else - { - hBrush = DEFWND_ControlColor( hdc, CTLCOLOR_SCROLLBAR ); - } - - hSavePen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) ); - hSaveBrush = SelectObject( hdc, hBrush ); - - /* Calculate the scroll rectangle */ - r = *rect; - if (vertical) - { - r.top += arrowSize - SCROLL_ARROW_THUMB_OVERLAP; - r.bottom -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP); - } - else - { - r.left += arrowSize - SCROLL_ARROW_THUMB_OVERLAP; - r.right -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP); - } - - /* Draw the scroll rectangles and thumb */ - if (!thumbPos) /* No thumb to draw */ - { - PatBlt( hdc, r.left, r.top, - r.right - r.left, r.bottom - r.top, - PATCOPY ); - - /* cleanup and return */ - SelectObject( hdc, hSavePen ); - SelectObject( hdc, hSaveBrush ); - return; - } - - if (vertical) - { - PatBlt( hdc, r.left, r.top, - r.right - r.left, - thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP), - top_selected ? 0x0f0000 : PATCOPY ); - r.top += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP); - PatBlt( hdc, r.left, r.top + thumbSize, - r.right - r.left, - r.bottom - r.top - thumbSize, - bottom_selected ? 0x0f0000 : PATCOPY ); - r.bottom = r.top + thumbSize; - } - else /* horizontal */ - { - PatBlt( hdc, r.left, r.top, - thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP), - r.bottom - r.top, - top_selected ? 0x0f0000 : PATCOPY ); - r.left += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP); - PatBlt( hdc, r.left + thumbSize, r.top, - r.right - r.left - thumbSize, - r.bottom - r.top, - bottom_selected ? 0x0f0000 : PATCOPY ); - r.right = r.left + thumbSize; - } - - /* Draw the thumb */ - DrawEdge( hdc, &r, EDGE_RAISED, BF_RECT | BF_MIDDLE ); - - /* cleanup */ - SelectObject( hdc, hSavePen ); - SelectObject( hdc, hSaveBrush ); -} - - -static void SCROLL_DrawInterior( HWND hwnd, HDC hdc, INT nBar, - RECT *rect, INT arrowSize, - INT thumbSize, INT thumbPos, - UINT flags, BOOL vertical, - BOOL top_selected, BOOL bottom_selected ) -{ - RECT r; - HPEN hSavePen; - HBRUSH hSaveBrush,hBrush; - BOOL Save_SCROLL_MovingThumb = SCROLL_MovingThumb; - - if (Save_SCROLL_MovingThumb && - (SCROLL_TrackingWin == hwnd) && - (SCROLL_TrackingBar == nBar)) - SCROLL_DrawMovingThumb( hdc, rect, vertical, arrowSize, thumbSize ); - - /* Select the correct brush and pen */ - - if (TWEAK_WineLook == WIN31_LOOK && (flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) - { - /* This ought to be the color of the parent window */ - hBrush = GetSysColorBrush(COLOR_WINDOW); - } - else - { - /* Only scrollbar controls send WM_CTLCOLORSCROLLBAR. - * The window-owned scrollbars need to call DEFWND_ControlColor - * to correctly setup default scrollbar colors - */ - if (nBar == SB_CTL) { - hBrush = (HBRUSH)SendMessageA( GetParent(hwnd), WM_CTLCOLORSCROLLBAR, - (WPARAM)hdc,(LPARAM)hwnd); - } else { - hBrush = DEFWND_ControlColor( hdc, CTLCOLOR_SCROLLBAR ); - } - } - hSavePen = SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) ); - hSaveBrush = SelectObject( hdc, hBrush ); - - /* Calculate the scroll rectangle */ - - r = *rect; - if (vertical) - { - r.top += arrowSize - SCROLL_ARROW_THUMB_OVERLAP; - r.bottom -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP); - } - else - { - r.left += arrowSize - SCROLL_ARROW_THUMB_OVERLAP; - r.right -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP); - } - - /* Draw the scroll bar frame */ - - /* Only draw outline if Win 3.1. Mar 24, 1999 - Ronald B. Cemer */ - if (TWEAK_WineLook == WIN31_LOOK) - Rectangle( hdc, r.left, r.top, r.right, r.bottom ); - - /* Draw the scroll rectangles and thumb */ - - if (!thumbPos) /* No thumb to draw */ - { - INT offset = (TWEAK_WineLook > WIN31_LOOK) ? 0 : 1; - - PatBlt( hdc, r.left+offset, r.top+offset, - r.right - r.left - 2*offset, r.bottom - r.top - 2*offset, - PATCOPY ); - - /* cleanup and return */ - SelectObject( hdc, hSavePen ); - SelectObject( hdc, hSaveBrush ); - return; - } - - if (vertical) - { - INT offset = (TWEAK_WineLook == WIN31_LOOK) ? 1 : 0; - - PatBlt( hdc, r.left + offset, r.top + offset, - r.right - r.left - offset*2, - thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - offset, - top_selected ? 0x0f0000 : PATCOPY ); - r.top += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP); - PatBlt( hdc, r.left + offset, r.top + thumbSize, - r.right - r.left - offset*2, - r.bottom - r.top - thumbSize - offset, - bottom_selected ? 0x0f0000 : PATCOPY ); - r.bottom = r.top + thumbSize; - } - else /* horizontal */ - { - INT offset = (TWEAK_WineLook == WIN31_LOOK) ? 1 : 0; - - PatBlt( hdc, r.left + offset, r.top + offset, - thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP), - r.bottom - r.top - offset*2, - top_selected ? 0x0f0000 : PATCOPY ); - r.left += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP); - PatBlt( hdc, r.left + thumbSize, r.top + offset, - r.right - r.left - thumbSize - offset, - r.bottom - r.top - offset*2, - bottom_selected ? 0x0f0000 : PATCOPY ); - r.right = r.left + thumbSize; - } - - /* Draw the thumb */ - - SelectObject( hdc, GetSysColorBrush(COLOR_BTNFACE) ); - if (TWEAK_WineLook == WIN31_LOOK) - { - Rectangle( hdc, r.left, r.top, r.right, r.bottom ); - r.top++, r.left++; - } - else - { - Rectangle( hdc, r.left+1, r.top+1, r.right-1, r.bottom-1 ); - } - DrawEdge( hdc, &r, EDGE_RAISED, BF_RECT ); - - if (Save_SCROLL_MovingThumb && - (SCROLL_TrackingWin == hwnd) && - (SCROLL_TrackingBar == nBar)) - SCROLL_DrawMovingThumb( hdc, rect, vertical, arrowSize, thumbSize ); - - /* cleanup */ - SelectObject( hdc, hSavePen ); - SelectObject( hdc, hSaveBrush ); -} + INT *from, *to; + BOOL vertical = FALSE; + WND *wnd = WIN_FindWndPtr(hwnd); + TRACE("hwnd=%04x nBar=%d info=%p bar=%p\n", hwnd, nBar, info, bar); -/*********************************************************************** - * SCROLL_DrawScrollBar - * - * Redraw the whole scrollbar. - */ -void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, INT nBar, - BOOL arrows, BOOL interior ) -{ - INT arrowSize, thumbSize, thumbPos; - RECT rect; - BOOL vertical; - WND *wndPtr = WIN_FindWndPtr( hwnd ); - SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ); - BOOL Save_SCROLL_MovingThumb = SCROLL_MovingThumb; - - if (!wndPtr || !infoPtr || - ((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) || - ((nBar == SB_HORZ) && !(wndPtr->dwStyle & WS_HSCROLL))) goto END; - if (!WIN_IsWindowDrawable( hwnd, FALSE )) goto END; - hwnd = wndPtr->hwndSelf; /* make it a full handle */ - - vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect, - &arrowSize, &thumbSize, &thumbPos ); - - /* do not draw if the scrollbar rectangle is empty */ - if(IsRectEmpty(&rect)) - goto END; - - if (Save_SCROLL_MovingThumb && - (SCROLL_TrackingWin == hwnd) && - (SCROLL_TrackingBar == nBar)) - SCROLL_DrawMovingThumb( hdc, &rect, vertical, arrowSize, thumbSize ); - - /* Draw the arrows */ - - if (arrows && arrowSize) - { - if( vertical == SCROLL_trackVertical && GetCapture() == hwnd ) - SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical, - (SCROLL_trackHitTest == SCROLL_TOP_ARROW), - (SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW) ); + /* set common state */ + bar->info = info; + bar->inside = TRUE; + bar->lastInside = FALSE; + bar->hit = SB_THUMBPOSITION; + bar->extended = wnd->rectClient; + bar->offset.x = bar->offset.y = 0; + bar->start.flags = (info->flags & ESB_DISABLE_LTUP) ? DFCS_INACTIVE : 0; + bar->end.flags = (info->flags & ESB_DISABLE_RTDN) ? DFCS_INACTIVE : 0; + + /* Set the orientation */ + if (!wnd) return vertical; + vertical = (nBar == SB_VERT) || + ((nBar == SB_CTL) && (wnd->dwStyle & SBS_VERT)); + if (vertical) + { + /* Fill in the bar properites for vertical scroll bars */ + bar->drawable = wnd->dwStyle & WS_VSCROLL; + bar->direction = WM_VSCROLL; + bar->start.coord = &(bar->rect.top); + bar->start.flags |= DFCS_SCROLLUP; + bar->start.arrow = &hUp; + bar->end.coord = &(bar->rect.bottom); + bar->end.flags |= DFCS_SCROLLDOWN; + bar->end.arrow = &hDown; + from = &(bar->extended.left); + to = &(bar->extended.right); + } else - SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical, - FALSE, FALSE ); - } - if( interior ) - SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize, - thumbPos, infoPtr->flags, vertical, FALSE, FALSE ); - - if (Save_SCROLL_MovingThumb && - (SCROLL_TrackingWin == hwnd) && - (SCROLL_TrackingBar == nBar)) - SCROLL_DrawMovingThumb( hdc, &rect, vertical, arrowSize, thumbSize ); - - /* if scroll bar has focus, reposition the caret */ - if(hwnd==GetFocus() && (nBar==SB_CTL)) - { - if (!vertical) - { - SetCaretPos(thumbPos+1, rect.top+1); - } - else - { - SetCaretPos(rect.top+1, thumbPos+1); - } - } - -END: - WIN_ReleaseWndPtr(wndPtr); -} + { + /* Fill in the bar properites for horizontal scroll bars */ + bar->drawable = wnd->dwStyle & WS_HSCROLL; + bar->direction = WM_HSCROLL; + bar->start.coord = &(bar->rect.left); + bar->start.flags |= DFCS_SCROLLLEFT; + bar->start.arrow = &hLeft; + bar->end.coord = &(bar->rect.right); + bar->end.flags |= DFCS_SCROLLRIGHT; + bar->end.arrow = &hRight; + from = &(bar->extended.top); + to = &(bar->extended.bottom); + } + /* Get the client rect */ + if (nBar != SB_CTL) + { + /* Set the offset used convert tracking to client coordinates */ + OffsetRect(&(bar->extended), -wnd->rectWindow.left, -wnd->rectWindow.top); + bar->offset.x = bar->extended.left; + bar->offset.y = bar->extended.top; + + /* Move rectangle to edge */ + *from = *to; + *to += GetSystemMetrics(SM_CXVSCROLL); + bar->rect = bar->extended; + + /* Adjust the size based on window style */ + if (wnd->dwStyle & (WS_BORDER | WS_VSCROLL)) + (*(bar->end.coord))++; + if (wnd->dwStyle & WS_BORDER) + (*(bar->start.coord))--; + } + else + bar->rect = bar->extended; -/*********************************************************************** - * SCROLL_RefreshScrollBar - * - * Repaint the scroll bar interior after a SetScrollRange() or - * SetScrollPos() call. - */ -static void SCROLL_RefreshScrollBar( HWND hwnd, INT nBar, - BOOL arrows, BOOL interior ) -{ - HDC hdc = GetDCEx( hwnd, 0, - DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW) ); - if (!hdc) return; + /* handle the extended rect used in thumb tracking */ + /* FIXME: use the correct system metric for win>31 */ + *from -= GetSystemMetrics(SM_CXVSCROLL); + *to += GetSystemMetrics(SM_CXVSCROLL); + WIN_ReleasePtr(wnd); + + /* Get the positions of the pieces and update the draw state */ + bar->drawable = bar->drawable && !(IsRectEmpty(&(bar->rect))); + bar->pixels = *(bar->end.coord) - *(bar->start.coord); + SCROLL_GetThumb(SCROLL_NO_POS, bar); - SCROLL_DrawScrollBar( hwnd, hdc, nBar, arrows, interior ); - ReleaseDC( hwnd, hdc ); + return vertical; } @@ -936,286 +451,415 @@ /*********************************************************************** - * SCROLL_HandleScrollEvent + * SCROLL_DrawArrow * - * Handle a mouse or timer event for the scrollbar. - * 'pt' is the location of the mouse event in client (for SB_CTL) or - * windows coordinates. + * Draw a scroll bar arrow in the needed active and pressed state. */ -static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt) +static void SCROLL_DrawArrow( +HDC hdc /* [in] the drawing control */, +LPRECT rect /* [in] the rectangle to contain the arrow */, +LPSCROLL_EXTREMITY extremity /* [in] the extremity for the arrow */, +BOOL pushed /* Indicates is the button is to be shown in its pushed state */) { - /* Previous mouse position for timer events */ - static POINT prevPt; - /* Thumb position when tracking started. */ - static UINT trackThumbPos; - /* Position in the scroll-bar of the last button-down event. */ - static INT lastClickPos; - /* Position in the scroll-bar of the last mouse event. */ - static INT lastMousePos; - - enum SCROLL_HITTEST hittest; - HWND hwndOwner, hwndCtl; - BOOL vertical; - INT arrowSize, thumbSize, thumbPos; - RECT rect; - HDC hdc; - - SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ); - if (!infoPtr) return; - if ((SCROLL_trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN)) - return; - - hdc = GetDCEx( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW)); - vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect, - &arrowSize, &thumbSize, &thumbPos ); - hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd) : hwnd; - hwndCtl = (nBar == SB_CTL) ? hwnd : 0; - - switch(msg) - { - case WM_LBUTTONDOWN: /* Initialise mouse tracking */ - HideCaret(hwnd); /* hide caret while holding down LBUTTON */ - SCROLL_trackVertical = vertical; - SCROLL_trackHitTest = hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE ); - lastClickPos = vertical ? (pt.y - rect.top) : (pt.x - rect.left); - lastMousePos = lastClickPos; - trackThumbPos = thumbPos; - prevPt = pt; - if (nBar == SB_CTL && (GetWindowLongA(hwnd, GWL_STYLE) & WS_TABSTOP)) SetFocus( hwnd ); - SetCapture( hwnd ); - break; - - case WM_MOUSEMOVE: - hittest = SCROLL_HitTest( hwnd, nBar, pt, TRUE ); - prevPt = pt; - break; - - case WM_LBUTTONUP: - hittest = SCROLL_NOWHERE; - ReleaseCapture(); - /* if scrollbar has focus, show back caret */ - if (hwnd==GetFocus()) ShowCaret(hwnd); - break; - - case WM_SYSTIMER: - pt = prevPt; - hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE ); - break; - - default: - return; /* Should never happen */ - } - - TRACE("Event: hwnd=%04x bar=%d msg=%s pt=%ld,%ld hit=%d\n", - hwnd, nBar, SPY_GetMsgName(msg,hwnd), pt.x, pt.y, hittest ); - - switch(SCROLL_trackHitTest) - { - case SCROLL_NOWHERE: /* No tracking in progress */ - break; - - case SCROLL_TOP_ARROW: - SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical, - (hittest == SCROLL_trackHitTest), FALSE ); - if (hittest == SCROLL_trackHitTest) - { - if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) - { - SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, - SB_LINEUP, (LPARAM)hwndCtl ); - } - - SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? - SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, - (TIMERPROC)0 ); - } - else KillSystemTimer( hwnd, SCROLL_TIMER ); - break; - - case SCROLL_TOP_RECT: - SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize, - thumbPos, infoPtr->flags, vertical, - (hittest == SCROLL_trackHitTest), FALSE ); - if (hittest == SCROLL_trackHitTest) - { - if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) - { - SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, - SB_PAGEUP, (LPARAM)hwndCtl ); - } - SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? - SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, - (TIMERPROC)0 ); - } - else KillSystemTimer( hwnd, SCROLL_TIMER ); - break; - - case SCROLL_THUMB: - if (msg == WM_LBUTTONDOWN) - { - SCROLL_TrackingWin = hwnd; - SCROLL_TrackingBar = nBar; - SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos; - if (!SCROLL_MovingThumb) - SCROLL_DrawMovingThumb(hdc, &rect, vertical, arrowSize, thumbSize); - } - else if (msg == WM_LBUTTONUP) - { - if (SCROLL_MovingThumb) - SCROLL_DrawMovingThumb(hdc, &rect, vertical, arrowSize, thumbSize); - SCROLL_TrackingWin = 0; - SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize, - thumbPos, infoPtr->flags, vertical, - FALSE, FALSE ); - } - else /* WM_MOUSEMOVE */ - { - UINT pos; - - if (!SCROLL_PtInRectEx( &rect, pt, vertical )) pos = lastClickPos; - else - { - pt = SCROLL_ClipPos( &rect, pt ); - pos = vertical ? (pt.y - rect.top) : (pt.x - rect.left); - } - if ( (pos != lastMousePos) || (!SCROLL_MovingThumb) ) - { - if (SCROLL_MovingThumb) - SCROLL_DrawMovingThumb( hdc, &rect, vertical, - arrowSize, thumbSize ); - lastMousePos = pos; - SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos; - SCROLL_TrackingVal = SCROLL_GetThumbVal( infoPtr, &rect, - vertical, - SCROLL_TrackingPos ); - SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, - MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal), - (LPARAM)hwndCtl ); - if (!SCROLL_MovingThumb) - SCROLL_DrawMovingThumb( hdc, &rect, vertical, - arrowSize, thumbSize ); - } - } - break; - - case SCROLL_BOTTOM_RECT: - SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize, - thumbPos, infoPtr->flags, vertical, - FALSE, (hittest == SCROLL_trackHitTest) ); - if (hittest == SCROLL_trackHitTest) - { - if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) - { - SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, - SB_PAGEDOWN, (LPARAM)hwndCtl ); - } - SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? - SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, - (TIMERPROC)0 ); - } - else KillSystemTimer( hwnd, SCROLL_TIMER ); - break; - - case SCROLL_BOTTOM_ARROW: - SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical, - FALSE, (hittest == SCROLL_trackHitTest) ); - if (hittest == SCROLL_trackHitTest) - { - if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) - { - SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, - SB_LINEDOWN, (LPARAM)hwndCtl ); - } - - SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? - SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, - (TIMERPROC)0 ); - } - else KillSystemTimer( hwnd, SCROLL_TIMER ); - break; - } - - if (msg == WM_LBUTTONDOWN) - { - - if (hittest == SCROLL_THUMB) - { - UINT val = SCROLL_GetThumbVal( infoPtr, &rect, vertical, - trackThumbPos + lastMousePos - lastClickPos ); - SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, - MAKEWPARAM( SB_THUMBTRACK, val ), (LPARAM)hwndCtl ); - } - } - - if (msg == WM_LBUTTONUP) - { - hittest = SCROLL_trackHitTest; - SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */ - - if (hittest == SCROLL_THUMB) - { - UINT val = SCROLL_GetThumbVal( infoPtr, &rect, vertical, - trackThumbPos + lastMousePos - lastClickPos ); - SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, - MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)hwndCtl ); - } - SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, - SB_ENDSCROLL, (LPARAM)hwndCtl ); - } + if (extremity->flags & DFCS_TRANSPARENT) return; + + TRACE("hdc=%04x rect=%p extremity=%p pushed=%d\n", + hdc, rect, extremity, pushed); + + /* clear or set pessed states */ + if (pushed) + extremity->flags |= (DFCS_PUSHED | DFCS_FLAT); + else + extremity->flags &= ~(DFCS_PUSHED | DFCS_FLAT); + + if (TWEAK_WineLook != WIN31_LOOK) + DrawFrameControl(hdc, rect, DFC_SCROLL, extremity->flags); + else + { + HDC hdcMem = CreateCompatibleDC(hdc); + HBITMAP hbmpPrev; + + /* load bitmask if not done yet */ + if (!hUp.normal) SCROLL_LoadBitmaps(); - ReleaseDC( hwnd, hdc ); + /* draw the arrow from the image */ + hbmpPrev = SelectObject(hdcMem, + (extremity->flags & DFCS_INACTIVE) ? extremity->arrow->disabled : + ((extremity->flags & DFCS_PUSHED) ? extremity->arrow->pressed : + extremity->arrow->normal)); + SetStretchBltMode(hdc, STRETCH_DELETESCANS); + StretchBlt(hdc, rect->left, rect->top, rect->right - rect->left, + rect->bottom - rect->top, hdcMem, 0, 0, + GetSystemMetrics(SM_CXVSCROLL), + GetSystemMetrics(SM_CYHSCROLL), SRCCOPY); + SelectObject(hdcMem, hbmpPrev); + DeleteDC(hdcMem); + } +} + + +/************************************************************************* + * SCROLL_DrawScrollBar + */ +static void SCROLL_DrawScrollBar( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */, +LPSCROLL_BAR bar /* [in] The place of the thumb */) +{ + HPEN hSavePen; + HBRUSH hSaveBrush; + INT end = *(bar->end.coord); + INT start = *(bar->start.coord); + HDC hdc = GetDCEx(hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW)); + if (!hdc) return; + + /* select the correct brush and pen */ + hSavePen = SelectObject(hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME)); + if (TWEAK_WineLook == WIN31_LOOK && SCROLL_DISABLED(bar->info)) + /* this ought to be the color of the parent window */ + hSaveBrush = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW)); + else if (nBar == SB_CTL) + /* only scrollbar controls send WM_CTLCOLORSCROLLBAR. */ + hSaveBrush = SelectObject(hdc,(HBRUSH)SendMessageA(GetParent(hwnd), + WM_CTLCOLORSCROLLBAR, (WPARAM)hdc, (LPARAM)hwnd)); + else + /* the window-owned scrollbars use DEFWND_ControlColor + * (to set default scroll bar colours) */ + hSaveBrush = SelectObject(hdc, + DEFWND_ControlColor(hdc, CTLCOLOR_SCROLLBAR)); + + /* draw the end arrow at the end */ + *(bar->start.coord) = *(bar->end.coord) - bar->arrow; + SCROLL_DRAW_ARROW(hdc, bar, &(bar->end), SB_LINEDOWN, SB_LINEUP); + *(bar->start.coord) = start; + + /* draw the start arrow at the start */ + *(bar->end.coord) = *(bar->start.coord) + bar->arrow; + SCROLL_DRAW_ARROW(hdc, bar, &(bar->start), SB_LINEUP, SB_LINEDOWN); + *(bar->end.coord) = end; + + /* draw the interior if needed */ + if (!SCROLL_CHANGED(bar) || (bar->hit != SB_LINEUP && bar->hit != SB_LINEDOWN)) + { + TRACE("hwnd=%04x nBar=%d\n", hwnd, nBar); + + /* resize the arrows out of the scroll rectangle */ + *(bar->start.coord) += bar->arrow; + *(bar->end.coord) -= bar->arrow; + + /* draw outline only if Win 3.1. Mar 24, 1999 - Ronald B. Cemer */ + if (TWEAK_WineLook == WIN31_LOOK) + { + Rectangle(hdc, bar->rect.left, bar->rect.top, + bar->rect.right, bar->rect.bottom); + + /* Confine the drawing rect to inside the previous rectangle */ + bar->rect.top++, bar->rect.left++, (*(bar->start.coord))--; + bar->rect.bottom--, bar->rect.right--, (*(bar->end.coord))++; + } + + /* draw a first rect and thumb */ + if (bar->thumb) + { + INT temp = *(bar->end.coord); + HBRUSH hSaveBrushThumb; + + /* draw first rect */ + *(bar->end.coord) = *(bar->start.coord) + bar->pos; + PatBlt(hdc, bar->rect.left, bar->rect.top, + bar->rect.right - bar->rect.left, bar->rect.bottom - bar->rect.top, + SCROLL_PATTERN(bar, SB_PAGEUP)); + *(bar->start.coord) = *(bar->end.coord); + + /* draw thumb */ + *(bar->end.coord) = *(bar->start.coord) + bar->thumb; + hSaveBrushThumb = SelectObject(hdc, GetSysColorBrush(COLOR_BTNFACE)); + Rectangle(hdc, bar->rect.left, bar->rect.top, + bar->rect.right, bar->rect.bottom); + DrawEdge(hdc, &(bar->rect), EDGE_RAISED , BF_RECT); /* | BF_MIDDLE */ + SelectObject(hdc, hSaveBrushThumb); + + /* if scroll bar has focus, reposition the caret */ + if ((hwnd == GetFocus()) && (nBar == SB_CTL)) + SetCaretPos(bar->rect.left + 1, bar->rect.top + 1); + + /* restore rect for next drawing operation */ + *(bar->start.coord) = *(bar->end.coord); + *(bar->end.coord) = temp; + } /* thumb to be drawn */ + + /* draw last and only rect when no thumb is to be drawn */ + PatBlt( hdc, bar->rect.left, bar->rect.top, + bar->rect.right - bar->rect.left, bar->rect.bottom - bar->rect.top, + SCROLL_PATTERN(bar, SB_PAGEDOWN)); + + /* cleanup */ + if (TWEAK_WineLook == WIN31_LOOK) + { + bar->rect.top--, bar->rect.left--, (*(bar->start.coord))++; + bar->rect.bottom++, bar->rect.right++, (*(bar->end.coord))--; + } + *(bar->start.coord) = start; + *(bar->end.coord) = end; + } + ReleaseDC(hwnd, hdc); + SelectObject(hdc, hSavePen); + SelectObject(hdc, hSaveBrush); + bar->lastInside = bar->inside; +} + + +/************************************************************************* + * SCROLL_RefreshScrollBar + */ +static void SCROLL_RefreshScrollBar( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */, +LPSCROLLBAR_INFO info /* [in] The place of the thumb */) +{ + TRACE("hwnd=%04x nBar=%d info=%p\n", hwnd, nBar, info); + + /* use the same scroll info structure unless being used by another */ + if (trackBar.info && trackBar.info == info) + { + /* currently tracking this bar so use the track structure */ + SCROLL_GetThumb(trackBar.hit == SB_THUMBPOSITION ? + trackBar.pos : SCROLL_NO_POS, &trackBar); + if (trackBar.drawable) + SCROLL_DrawScrollBar(hwnd, nBar, &trackBar); + } + else if (!(trackBar.info)) + { + /* not tracking but might soon be so use the track structure */ + SCROLL_GetScrollBar(hwnd, nBar, info, &trackBar); + if (trackBar.drawable) + SCROLL_DrawScrollBar(hwnd, nBar, &trackBar); + trackBar.info = 0; + } + else + { + /* Event ocurred while tracking a bar so create a bar structure */ + SCROLL_BAR bar; + SCROLL_GetScrollBar(hwnd, nBar, info, &bar); + if (bar.drawable) SCROLL_DrawScrollBar(hwnd, nBar, &bar); + } +} + + +/************************************************************************* + * SCROLL_PaintScrollBar + * + * Used by nonclient windows to draw scroll bars in the windows. + * (cleaning up non client would get rid of this) + */ +void SCROLL_PaintScrollBar( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */) +{ + LPSCROLLBAR_INFO info = SCROLL_GetScrollInfo(hwnd, nBar); + + TRACE("hwnd=%04x nBar=%d\n", hwnd, nBar); + + if (info && WIN_IsWindowDrawable(hwnd, FALSE)) + SCROLL_RefreshScrollBar(hwnd, nBar, info); +} + + +/*********************************************************************** + * SCROLL_GetHit + * + * Determine in which part of the scroll bar the event happened. + */ +static UINT SCROLL_GetHit( +LONG coord /* [in] The the position of the mouse at the event */, +LPSCROLL_BAR bar /* [in] The containing bar */) +{ + if (coord < 0) + return SB_LINEUP; + else if (coord >= bar->pixels - bar->arrow * 2) + return SB_LINEDOWN; + else if (coord < bar->pos) + return SB_PAGEUP; + else if (coord >= bar->pos + bar->thumb) + return SB_PAGEDOWN; + else + return SB_THUMBPOSITION; } /*********************************************************************** - * SCROLL_TrackScrollBar + * SCROLL_HandleScrollEvent * - * Track a mouse button press on a scroll-bar. - * pt is in screen-coordinates for non-client scroll bars. + * Handle a mouse or timer event for the scrollbar. */ -void SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt ) +void SCROLL_HandleScrollEvent( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */, +UINT msg /* [in] The windows message identifier */, +LPARAM lParam /* [in] The the position of the mouse at the event */) { - MSG msg; - INT xoffset = 0, yoffset = 0; - - if (scrollbar != SB_CTL) - { - WND *wndPtr = WIN_GetPtr( hwnd ); - if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return; - xoffset = wndPtr->rectClient.left - wndPtr->rectWindow.left; - yoffset = wndPtr->rectClient.top - wndPtr->rectWindow.top; - WIN_ReleasePtr( wndPtr ); - ScreenToClient( hwnd, &pt ); - pt.x += xoffset; - pt.y += yoffset; - } - - SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt ); - - do - { - if (!GetMessageW( &msg, 0, 0, 0 )) break; - if (CallMsgFilterW( &msg, MSGF_SCROLLBAR )) continue; - switch(msg.message) - { - case WM_LBUTTONUP: - case WM_MOUSEMOVE: - case WM_SYSTIMER: - pt.x = LOWORD(msg.lParam) + xoffset; - pt.y = HIWORD(msg.lParam) + yoffset; - SCROLL_HandleScrollEvent( hwnd, scrollbar, msg.message, pt ); - break; - default: - TranslateMessage( &msg ); - DispatchMessageW( &msg ); - break; - } - if (!IsWindow( hwnd )) - { - ReleaseCapture(); - break; - } - } while (msg.message != WM_LBUTTONUP); + static UINT clickPos; /* thumb position when tracking started */ + static INT clickCoord; /* scroll coordinate of last button-down event */ + static INT lastCoord; /* scroll coordinate of last thumb move event */ + + /* Initialise the client position offset */ + MSG mesg; /* message structure used when tracking */ + POINT pt; /* location for event in client coordinates */ + LONG *coordinate; /* pointer to relevent coordinate in pt */ + LONG coord; /* coordinate of event interior to arrows */ + UINT curVal; /* proposed current value during scrolling */ + INT oldPos; /* precious pos when handling moves */ + BOOL tracking = FALSE; /* inicates if the scrol bar is tracking */ + LPARAM hwndCtl = (nBar == SB_CTL) ? (LPARAM)hwnd : (LPARAM)0; + HWND hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd) : hwnd; + + /* check scroll bar is enabled */ + LPSCROLLBAR_INFO info = SCROLL_GetScrollInfo(hwnd, nBar); + if (!info || SCROLL_DISABLED(info)) return; + + TRACE("hwnd=%04x nBar=%d\n",hwnd, nBar); + + /* set the appropriate scroll coordinate from pt */ + if (SCROLL_GetScrollBar(hwnd, nBar, info, &trackBar)) + coordinate = &(pt.y); + else + coordinate = &(pt.x); + + /* fill in initial dummy message structure */ + mesg.message = msg; + mesg.lParam = lParam; + + do { + /* determine the coordinates in client frame */ + if (mesg.message == WM_LBUTTONDOWN || + mesg.message == WM_MOUSEMOVE || + mesg.message == WM_LBUTTONUP) + { + pt.x = LOWORD(mesg.lParam) - trackBar.offset.x; + pt.y = HIWORD(mesg.lParam) - trackBar.offset.y; + } + + /* mouse down messages are in screen coordinates */ + if (mesg.message == WM_LBUTTONDOWN && nBar != SB_CTL) + ScreenToClient(hwnd, &pt); + + /* determine coordinate in bar after arrow */ + coord = *coordinate - *(trackBar.start.coord) - trackBar.arrow; + + TRACE(" processing: msg=%s pt=%ld,%ld\n", + SPY_GetMsgName(mesg.message, hwnd), pt.x, pt.y); + + /* handle mesage */ + if (!tracking || !CallMsgFilterW(&mesg, MSGF_SCROLLBAR)) + switch (mesg.message) + { + case WM_LBUTTONDOWN: + /* handle coords, caret, focus, capture and tracking*/ + if (GetWindowLongA(hwnd, GWL_STYLE) & WS_TABSTOP) SetFocus(hwnd); + SetCapture(hwnd); + HideCaret(hwnd); + tracking = TRUE; + + /* set the hit and tracking parameters */ + clickPos = trackBar.pos; + lastCoord = clickCoord = coord = + *coordinate - *(trackBar.start.coord) - trackBar.arrow; + + /* determine the hit position and draw */ + trackBar.hit = SCROLL_GetHit(coord, &trackBar); + if (trackBar.hit == SB_THUMBPOSITION) break; + SCROLL_DrawScrollBar(hwnd, nBar, &trackBar); + /* fall through */ + + case WM_SYSTIMER: + if (trackBar.inside && trackBar.hit != SB_THUMBPOSITION) + { + /* send the hit message to the parent */ + SendMessageA(hwndOwner, trackBar.direction, trackBar.hit, hwndCtl); + + /* don't repeat when at either the end of the bar */ + if (!((trackBar.hit == SB_LINEUP && info->curVal == info->minVal) || + (trackBar.hit == SB_LINEDOWN && + info->curVal == info->maxVal - info->page + 1))) + SetSystemTimer(hwnd, SCROLL_TIMER, (mesg.message == WM_LBUTTONDOWN) ? + SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC)0); + else + KillSystemTimer(hwnd, SCROLL_TIMER); + + /* handle thumb moving under cursor in page moves */ + if (!(trackBar.inside = (trackBar.hit == SCROLL_GetHit(coord, &trackBar)))) + SCROLL_DrawScrollBar(hwnd, nBar, &trackBar); + } + break; + + case WM_MOUSEMOVE: + /* deterine if inside the bar and update the scroll position */ + curVal = info->curVal; + if (trackBar.hit == SB_LINEUP || trackBar.hit == SB_LINEDOWN) + trackBar.inside = PtInRect(&(trackBar.rect), pt) && + trackBar.hit == SCROLL_GetHit(coord, &trackBar); + else if (!trackBar.inside) + ; /* once outsidebar always outside for non arrow hits */ + else if (trackBar.hit != SB_THUMBPOSITION) + trackBar.inside = PtInRect(&(trackBar.rect), pt) && + trackBar.hit == SCROLL_GetHit(coord, &trackBar); + else if (!(trackBar.inside = PtInRect(&(trackBar.extended), pt))) + trackBar.hit = SCROLL_NO_POS, curVal = SCROLL_GetThumb(clickPos, &trackBar); + else if (coord != lastCoord) + { + /* if move is relevent find new curVal */ + lastCoord = coord; + oldPos = trackBar.pos; + curVal = SCROLL_GetThumb(clickPos + coord - clickCoord, &trackBar); + if (trackBar.pos != oldPos) SCROLL_DrawScrollBar(hwnd, nBar, &trackBar); + } + + /* send SB_THUMBTRACK messages to parent if moved */ + if (info->curVal != curVal) + SendMessageA(hwndOwner, trackBar.direction, + MAKEWPARAM(SB_THUMBPOSITION /*SB_THUMBTRACK*/, curVal), hwndCtl); + + /* redraw if needed */ + if (SCROLL_CHANGED(&trackBar)) + SCROLL_DrawScrollBar(hwnd, nBar, &trackBar); + break; + + case WM_LBUTTONUP: + /* send messages to control */ + if (trackBar.hit == SB_THUMBPOSITION) + SendMessageA(hwndOwner, trackBar.direction, + MAKEWPARAM(trackBar.hit, info->curVal), hwndCtl); + else if (trackBar.inside) + { + trackBar.inside = FALSE; + SCROLL_DrawScrollBar(hwnd, nBar, &trackBar); + } + SendMessageA(hwndOwner, trackBar.direction, SB_ENDSCROLL, hwndCtl); + + /* clean up capture and timer */ + ReleaseCapture(); + KillSystemTimer(hwnd, SCROLL_TIMER); + if (hwnd == GetFocus()) ShowCaret(hwnd); + tracking = FALSE; + break; + + default: + if (tracking) + { + TranslateMessage(&mesg); + DispatchMessageW(&mesg); + } + else + ERR("Illegal message %s\n", SPY_GetMsgName(msg, hwnd)); + break; + } + /*if (tracking && !IsWindow(hwnd)) ReleaseCapture();*/ + } while (tracking && GetMessageW(&mesg, 0, 0, 0)); + + /* Note: failing GetMessageW(&mesg, 0, 0, 0) + * will not clean up capture or scroll timer properly + */ + trackBar.info = 0; } @@ -1227,20 +871,22 @@ static void WINAPI SCROLL_SetFocus( HWND hwnd /* [in] Handle of window with scrollbar(s) */) { - /* Create a caret when a ScrollBar get focus */ - RECT rect; - int arrowSize, thumbSize, thumbPos, vertical; - vertical = SCROLL_GetScrollBarRect( hwnd, SB_CTL, &rect, - &arrowSize, &thumbSize, &thumbPos ); - if (!vertical) + SCROLL_BAR bar; + LPSCROLLBAR_INFO info = SCROLL_GetScrollInfo(hwnd, SB_CTL); + if (!info) return; + + TRACE("hwnd=%04x", hwnd); + + /* Create a caret when a ScrollBar gets focus */ + if (SCROLL_GetScrollBar(hwnd, SB_CTL, info, &bar)) { - CreateCaret(hwnd,1, thumbSize-2, rect.bottom-rect.top-2); - SetCaretPos(thumbPos+1, rect.top+1); + CreateCaret(hwnd, 1, GetSystemMetrics(SM_CXVSCROLL) - 2, bar.thumb - 2); + SetCaretPos(bar.rect.top + 1, bar.pos + 1); } else { - CreateCaret(hwnd,1, rect.right-rect.left-2,thumbSize-2); - SetCaretPos(rect.top+1, thumbPos+1); + CreateCaret(hwnd, 1, bar.thumb - 2, GetSystemMetrics(SM_CYHSCROLL) - 2); + SetCaretPos(bar.pos + 1, bar.rect.top + 1); } ShowCaret(hwnd); } @@ -1254,21 +900,21 @@ static void SCROLL_KillFocus( HWND hwnd /* [in] Handle of window with scrollbar(s) */) { - RECT rect; - int arrowSize, thumbSize, thumbPos, vertical; - vertical = SCROLL_GetScrollBarRect( hwnd, SB_CTL, &rect,&arrowSize, &thumbSize, &thumbPos ); - if (!vertical) - { - rect.left=thumbPos+1; - rect.right=rect.left+thumbSize; - } - else - { - rect.top=thumbPos+1; - rect.bottom=rect.top+thumbSize; - } + SCROLL_BAR bar; + LPSCROLLBAR_INFO info = SCROLL_GetScrollInfo(hwnd, SB_CTL); + if (!info) return; + + TRACE("hwnd=%04x", hwnd); + + SCROLL_GetScrollBar(hwnd, SB_CTL, info, &bar); + + /* move the bar rect */ + *(bar.start.coord) = bar.pos + 1; + *(bar.end.coord) = *(bar.start.coord) + bar.thumb; + + /* Handle the caret display */ HideCaret(hwnd); - InvalidateRect(hwnd,&rect,0); + InvalidateRect(hwnd, &(bar.rect), 0); DestroyCaret(); } @@ -1371,20 +1017,10 @@ wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH); case WM_LBUTTONDOWN: - { - POINT pt; pt.x = SLOWORD(lParam); pt.y = SHIWORD(lParam); - SCROLL_TrackScrollBar( hwnd, SB_CTL, pt ); - } - break; - case WM_LBUTTONUP: case WM_MOUSEMOVE: case WM_SYSTIMER: - { - POINT pt; pt.x = SLOWORD(lParam); pt.y = SHIWORD(lParam); - SCROLL_HandleScrollEvent( hwnd, SB_CTL, message, pt ); - } - break; + SCROLL_HandleScrollEvent(hwnd, SB_CTL, message, lParam); break; case WM_KEYDOWN: SCROLL_HandleKbdEvent(hwnd, wParam, lParam); break; @@ -1406,7 +1042,7 @@ case WM_PAINT: /* FIXME: needs to handle all types of bars */ - SCROLL_RefreshScrollBar(hwnd, SB_CTL, TRUE, TRUE); break; + SCROLL_PaintScrollBar(hwnd, SB_CTL); break; case SBM_SETPOS16: case SBM_SETPOS: @@ -1631,7 +1267,7 @@ if (WIN_IsWindowDrawable(hwnd, FALSE) && ((infoPtr->flags != oldFlags) || (bRedraw && changed && (infoPtr->minVal < gap)))) - SCROLL_RefreshScrollBar(hwnd, nBar, TRUE, TRUE); + SCROLL_RefreshScrollBar(hwnd, nBar, infoPtr); return infoPtr->curVal; } @@ -1810,7 +1446,7 @@ { info->flags = flags; if (WIN_IsWindowDrawable(hwnd, FALSE)) - SCROLL_RefreshScrollBar(hwnd, nBar, TRUE, TRUE); + SCROLL_RefreshScrollBar(hwnd, nBar, info); } return ret;