Hi, This patch makes the SetScroll* API calls forward the requests to the window for SB_CTL scrollbars. The code in the API functions is factored into helper which are called from the API and WndProc functions. The code in the functions has been cleaned up in the same ways as the original set of clean up patches Changelog: SCROLL_SetScrollInfo returns current position, old position or old position only if modified as various calling contexts require and handles the redraw if required SetScrollRange, SetScrollPos and SetScrollInfo send a message to the window for the SB_CTL case Moves code for SetScrollRange and SetScrollPos to into worker functions License: X11 Andrew Note needs to be applied after previous three patches 1. The messaging for Get functions 2. The inline function clean up 3. Create refactor --- controls/scroll.c 2003-03-06 16:35:11.000000000 +0800 +++ controls/scroll.c 2003-03-07 16:10:44.000000000 +0800 @@ -111,10 +111,6 @@ static BOOL SCROLL_MovingThumb = FALSE; /* Local functions */ -static BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, - BOOL fShowH, BOOL fShowV ); -static INT SCROLL_SetScrollInfo( HWND hwnd, INT nBar, - const SCROLLINFO *info, INT *action ); static void SCROLL_DrawInterior_9x( HWND hwnd, HDC hdc, INT nBar, RECT *rect, INT arrowSize, INT thumbSize, INT thumbPos, @@ -136,14 +132,15 @@ IDC_ARROWA, /* cursor */ 0 /* brush */ }; - + + /*********************************************************************** * SCROLL_ScrollInfoValid * * Determine if the supplied SCROLLINFO struct is valid. */ inline static BOOL SCROLL_ScrollInfoValid( -LPSCROLLINFO info /* [in] The SCROLLINFO struct to be tested */) +const SCROLLINFO *info /* [in] The SCROLLINFO struct to be tested */) { return !(info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL) || (info->cbSize != sizeof(*info) @@ -896,7 +893,7 @@ /*********************************************************************** * SCROLL_HandleKbdEvent * - * Handle a keyboard event (only for SB_CTL scrollbars with focus). + * Handle a keyboard event (only for SB_CTL scrollbars). */ static void SCROLL_HandleKbdEvent( HWND hwnd /* [in] Handle of window with scrollbar(s) */, @@ -1254,6 +1251,178 @@ /************************************************************************* + * SCROLL_SetScrollInfo + * + * Internal helper for the API function + * + * RETURNS + * oldPos = TRUE, oldChanged = TRUE : old position if changed else zero + * oldPos = TRUE, oldChanged = FALSE : old position always + * oldPos = FALSE, oldChanged = TRUE : TRUE always (unless infoPtr bad) + * oldPos = FALSE, oldChanged = FALSE: New position always + */ +static INT SCROLL_SetScrollInfo( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, +const SCROLLINFO *info /* [in] Specifies what to change and new values */, +BOOL bRedraw /* [in] Should scrollbar be redrawn afterwards ? */, +BOOL oldPos /* [in] Return the old position not the new one */, +BOOL oldChanged /* [in] Return old value only if changed */) +{ + LPSCROLLBAR_INFO infoPtr = SCROLL_GetScrollBarInfo(hwnd, nBar); + INT gap; /* range of allowed values */ + INT value; /* new current value */ + INT ret = 0; /* the return value */ + UINT oldFlags; /* flags before changes */ + BOOL enabled; /* indicates the scroll bar could be enabled */ + BOOL changed = FALSE; /* only show/hide scrollbar if params change */ + + /* handle invalid data structure */ + if (!infoPtr) return 0; + + /* set the scroll range */ + if (info->fMask & SIF_RANGE) + { + if ((info->nMin > info->nMax) || + ((UINT)(info->nMax - info->nMin) >= 0x80000000)) + { + /* invalid range -> range is set to (0,0) */ + changed = ((infoPtr->minVal) || (infoPtr->maxVal)); + infoPtr->minVal = 0; + infoPtr->maxVal = 0; + } + else if ((infoPtr->minVal != info->nMin) || + (infoPtr->maxVal != info->nMax)) + { + infoPtr->minVal = info->nMin; + infoPtr->maxVal = info->nMax; + changed = TRUE; + } + } + + /* determine desired page size */ + value = infoPtr->page; + if ((info->fMask & SIF_PAGE) && (value != info->nPage)) + value = info->nPage; + + /* make sure the page size is valid */ + gap = infoPtr->maxVal - infoPtr->minVal + 1; + if (value > gap) + value = gap; + else if (value < 1) + value = 1; + /* change page if required */ + if (value != infoPtr->page) + { + infoPtr->page = value; + changed = TRUE; + } + + /* set the scroll pos */ + ret = value = infoPtr->curVal; + if ((info->fMask & SIF_POS) && (value != info->nPos)) + value = info->nPos; + + /* make sure the pos is inside the range */ + gap = infoPtr->maxVal - infoPtr->page + 1; + if (value < infoPtr->minVal) + value = infoPtr->minVal; + else if (value > gap) + value = gap; + + TRACE(" new values: page=%d pos=%d min=%d max=%d\n", + infoPtr->page, value, infoPtr->minVal, infoPtr->maxVal); + + /* determine the activation state */ + oldFlags = infoPtr->flags; + enabled = infoPtr->minVal < gap; + if (!(info->fMask & SIF_ALL)) + ; /* if called without SIF_ALL don't change state */ + else if (!enabled && info->fMask & SIF_DISABLENOSCROLL) + infoPtr->flags |= ESB_DISABLE_BOTH; + else + { + if (enabled) + infoPtr->flags &= ~ESB_DISABLE_BOTH; + if (changed && (nBar != SB_CTL) && + (info->fMask & (SIF_RANGE | SIF_PAGE))) + ShowScrollBar(hwnd, nBar, enabled); + } + + /* change position if required and set the return value */ + if (value != infoPtr->curVal) + { + infoPtr->curVal = value; + if (!oldPos) ret = value; + changed = TRUE; + } + else if (oldChanged) + ret = 0; + if (!oldPos && oldChanged) + ret = TRUE; + + /* redraw the scroll bar if desired or required */ + if (WIN_IsWindowDrawable(hwnd, FALSE) && + ((infoPtr->flags != oldFlags) || + (bRedraw && changed && (infoPtr->minVal < gap)))) + SCROLL_RefreshScrollBar(hwnd, nBar, TRUE, TRUE); + + return ret; +} + + +/************************************************************************* + * SCROLL_SetScrollPos + * + * Internal helper for the API function + */ +INT WINAPI SCROLL_SetScrollPos( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, +INT nPos /* [in] New value */, +BOOL bRedraw /* [in] Should scrollbar be redrawn afterwards ? */) +{ + SCROLLINFO info; + + /* fill in an info structure and use common set info code */ + info.cbSize = sizeof(info); + info.nPos = nPos; + info.fMask = SIF_POS; + + return SCROLL_SetScrollInfo(hwnd, nBar, &info, bRedraw, TRUE, FALSE); +} + + +/************************************************************************* + * SCROLL_SetScrollRange + * + * Set scroll range returning old value of position if it has changed + * + * RETURNS + * oldPos = TRUE : The old position if the position has changed + * oldPos = FALSE : 0 + */ +static LRESULT SCROLL_SetScrollRange( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, +INT minVal /* [in] New minimum value */, +INT maxVal /* [in] New maximum value */, +BOOL bRedraw /* [in] Should scrollbar be redrawn afterwards ? */, +BOOL oldPos /* [in] Should function return the oldPosition */) +{ + SCROLLINFO info; + + /* fill in an info structure and use common set info code */ + info.cbSize = sizeof(info); + info.nMin = minVal; + info.nMax = maxVal; + info.fMask = SIF_RANGE; + + return SCROLL_SetScrollInfo(hwnd, nBar, &info, bRedraw, oldPos, TRUE); +} + + +/************************************************************************* * SCROLL_GetScrollInfo * * Internal helper for the API function @@ -1321,31 +1490,33 @@ } - /*********************************************************************** * ScrollBarWndProc - */ -static LRESULT WINAPI ScrollBarWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) + * + * The routine for handling window events + * + * RETURNS + * Zero +*/ +static LRESULT WINAPI ScrollBarWndProc( +HWND hwnd /* [in] Handle of window whose scrollbar(s) will be affected */, +UINT message /* [in] The windows message to be actioned */, +WPARAM wParam /* [in] Variable input including enable state */, +LPARAM lParam /* [in] Variable input including input point */) { - if (!IsWindow( hwnd )) return 0; + TRACE("hwnd=%p message=%s wParam=%d lParam=%ld\n", + hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam); - switch(message) + /* handle the windows message */ + if (IsWindow(hwnd)) switch (message) { case WM_CREATE: SCROLL_CreateScrollBar(hwnd, (LPCREATESTRUCTW)lParam); - if (!hUpArrow) SCROLL_LoadBitmaps(); break; case WM_ENABLE: - { - SCROLLBAR_INFO *infoPtr; - if ((infoPtr = SCROLL_GetScrollBarInfo( hwnd, SB_CTL ))) - { - infoPtr->flags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH; - SCROLL_RefreshScrollBar(hwnd, SB_CTL, TRUE, TRUE); - } - } - return 0; + return EnableScrollBar(hwnd, SB_CTL, + wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH); case WM_LBUTTONDOWN: { @@ -1371,8 +1542,7 @@ break; case WM_KEYUP: - ShowCaret(hwnd); - break; + ShowCaret(hwnd); break; case WM_SETFOCUS: { @@ -1416,10 +1586,10 @@ break; case WM_ERASEBKGND: - return 1; + return 1; case WM_GETDLGCODE: - return DLGC_WANTARROWS; /* Windows returns this value */ + return DLGC_WANTARROWS; /* Windows returns this value */ case WM_PAINT: { @@ -1431,50 +1601,40 @@ SCROLL_DrawScrollBar( hwnd, hdc, SB_CTL, TRUE, TRUE ); EndPaint( hwnd, &ps ); } - break; case SBM_SETPOS16: case SBM_SETPOS: - return SetScrollPos( hwnd, SB_CTL, wParam, (BOOL)lParam ); + return SCROLL_SetScrollPos(hwnd, SB_CTL, wParam, (BOOL)lParam); case SBM_GETPOS16: case SBM_GETPOS: - return SCROLL_GetScrollPos(hwnd, SB_CTL); + return SCROLL_GetScrollPos(hwnd, SB_CTL); case SBM_SETRANGE16: - SetScrollRange( hwnd, SB_CTL, LOWORD(lParam), HIWORD(lParam), - wParam /* FIXME: Is this correct? */ ); - return 0; + return SCROLL_SetScrollRange(hwnd, SB_CTL, LOWORD(lParam), + HIWORD(lParam), wParam, TRUE); case SBM_SETRANGE: - { - INT oldPos = SCROLL_GetScrollPos( hwnd, SB_CTL ); - SetScrollRange( hwnd, SB_CTL, wParam, lParam, FALSE ); - if (oldPos != SCROLL_GetScrollPos( hwnd, SB_CTL )) return oldPos; - } - return 0; + return SCROLL_SetScrollRange(hwnd, SB_CTL, wParam, lParam, FALSE, FALSE); case SBM_GETRANGE16: - FIXME("don't know how to handle SBM_GETRANGE16 (wp=%04x,lp=%08lx)\n", wParam, lParam ); - return 0; + FIXME("don't know how to handle SBM_GETRANGE16 (wp=%04x, lp=%08lx)\n", + wParam, lParam); + break; case SBM_GETRANGE: return SCROLL_GetScrollRange(hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam); case SBM_ENABLE_ARROWS16: case SBM_ENABLE_ARROWS: - return EnableScrollBar( hwnd, SB_CTL, wParam ); + return EnableScrollBar(hwnd, SB_CTL, wParam); case SBM_SETRANGEREDRAW: - { - INT oldPos = SCROLL_GetScrollPos( hwnd, SB_CTL ); - SetScrollRange( hwnd, SB_CTL, wParam, lParam, TRUE ); - if (oldPos != SCROLL_GetScrollPos( hwnd, SB_CTL )) return oldPos; - } - return 0; + return SCROLL_SetScrollRange(hwnd, SB_CTL, wParam, lParam, TRUE, FALSE); case SBM_SETSCROLLINFO: - return SetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam, wParam ); + return SCROLL_SetScrollInfo(hwnd, SB_CTL, (SCROLLINFO *)lParam, + wParam, FALSE, FALSE); case SBM_GETSCROLLINFO: return SCROLL_GetScrollInfo(hwnd, SB_CTL, (SCROLLINFO *)lParam); @@ -1488,14 +1648,14 @@ case 0x00ee: case 0x00ef: ERR("unknown Win32 msg %04x wp=%08x lp=%08lx\n", - message, wParam, lParam ); + message, wParam, lParam); break; default: if (message >= WM_USER) WARN("unknown msg %04x wp=%04x lp=%08lx\n", - message, wParam, lParam ); - return DefWindowProcW( hwnd, message, wParam, lParam ); + message, wParam, lParam); + return DefWindowProcW(hwnd, message, wParam, lParam); } return 0; } @@ -1503,6 +1663,7 @@ /************************************************************************* * SetScrollInfo (USER32.@) + * * SetScrollInfo can be used to set the position, upper bound, * lower bound, and page size of a scrollbar control. * @@ -1511,168 +1672,35 @@ * * NOTE * For 100 lines of text to be displayed in a window of 25 lines, - * one would for instance use info->nMin=0, info->nMax=75 + * one would for instance use info->nMin = 0, info->nMax = 75 * (corresponding to the 76 different positions of the window on - * the text), and info->nPage=25. + * the text), and info->nPage = 25. */ INT WINAPI SetScrollInfo( -HWND hwnd /* [in] Handle of window whose scrollbar will be affected */, +HWND hwnd /* [in] Handle of window with scrollbar(s) */, INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, const SCROLLINFO *info /* [in] Specifies what to change and new values */, BOOL bRedraw /* [in] Should scrollbar be redrawn afterwards ? */) { - INT action; - INT retVal = SCROLL_SetScrollInfo( hwnd, nBar, info, &action ); - - if( action & SA_SSI_HIDE ) - SCROLL_ShowScrollBar( hwnd, nBar, FALSE, FALSE ); - else - { - if( action & SA_SSI_SHOW ) - if( SCROLL_ShowScrollBar( hwnd, nBar, TRUE, TRUE ) ) - return retVal; /* SetWindowPos() already did the painting */ - - if( bRedraw && (action & SA_SSI_REFRESH)) - SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); - else if( action & SA_SSI_REPAINT_ARROWS ) - SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, FALSE ); - } - return retVal; -} - -INT SCROLL_SetScrollInfo( HWND hwnd, INT nBar, - const SCROLLINFO *info, INT *action ) -{ - /* Update the scrollbar state and set action flags according to - * what has to be done graphics wise. */ - - SCROLLBAR_INFO *infoPtr; - UINT new_flags; - BOOL bChangeParams = FALSE; /* don't show/hide scrollbar if params don't change */ - - *action = 0; - - if (!(infoPtr = SCROLL_GetScrollBarInfo(hwnd, nBar))) return 0; - if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return 0; - if ((info->cbSize != sizeof(*info)) && - (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return 0; + /* handle invalid data structure */ + if (!(SCROLL_ScrollInfoValid(info))) return 0; + /* indicate desired values */ if (TRACE_ON(scroll)) { TRACE("hwnd=%p bar=%d", hwnd, nBar); - if (info->fMask & SIF_PAGE) DPRINTF( " page=%d", info->nPage ); - if (info->fMask & SIF_POS) DPRINTF( " pos=%d", info->nPos ); - if (info->fMask & SIF_RANGE) DPRINTF( " min=%d max=%d", info->nMin, info->nMax ); - DPRINTF("\n"); - } - - /* Set the page size */ - - if (info->fMask & SIF_PAGE) - { - if( infoPtr->page != info->nPage ) - { - infoPtr->page = info->nPage; - *action |= SA_SSI_REFRESH; - bChangeParams = TRUE; - } - } - - /* Set the scroll pos */ - - if (info->fMask & SIF_POS) - { - if( infoPtr->curVal != info->nPos ) - { - infoPtr->curVal = info->nPos; - *action |= SA_SSI_REFRESH; - } - } - - /* Set the scroll range */ - - if (info->fMask & SIF_RANGE) - { - /* Invalid range -> range is set to (0,0) */ - if ((info->nMin > info->nMax) || - ((UINT)(info->nMax - info->nMin) >= 0x80000000)) - { - infoPtr->minVal = 0; - infoPtr->maxVal = 0; - bChangeParams = TRUE; - } - else - { - if( infoPtr->minVal != info->nMin || - infoPtr->maxVal != info->nMax ) - { - *action |= SA_SSI_REFRESH; - infoPtr->minVal = info->nMin; - infoPtr->maxVal = info->nMax; - bChangeParams = TRUE; - } - } + if (info->fMask & SIF_PAGE) DPRINTF(" page=%d", info->nPage); + if (info->fMask & SIF_POS) DPRINTF(" pos=%d", info->nPos); + if (info->fMask & SIF_RANGE) + DPRINTF(" min=%d max=%d", info->nMin, info->nMax); + DPRINTF(" bRedraw=%d\n", bRedraw); } - /* Make sure the page size is valid */ - - if (infoPtr->page < 0) infoPtr->page = 0; - else if (infoPtr->page > infoPtr->maxVal - infoPtr->minVal + 1 ) - infoPtr->page = infoPtr->maxVal - infoPtr->minVal + 1; - - /* Make sure the pos is inside the range */ - - if (infoPtr->curVal < infoPtr->minVal) - infoPtr->curVal = infoPtr->minVal; - else if (infoPtr->curVal > infoPtr->maxVal - max( infoPtr->page-1, 0 )) - infoPtr->curVal = infoPtr->maxVal - max( infoPtr->page-1, 0 ); - - TRACE(" new values: page=%d pos=%d min=%d max=%d\n", - infoPtr->page, infoPtr->curVal, - infoPtr->minVal, infoPtr->maxVal ); - - /* don't change the scrollbar state if SetScrollInfo - * is just called with SIF_DISABLENOSCROLL - */ - if(!(info->fMask & SIF_ALL)) goto done; - - /* Check if the scrollbar should be hidden or disabled */ - - if (info->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL)) - { - new_flags = infoPtr->flags; - if (infoPtr->minVal >= infoPtr->maxVal - max( infoPtr->page-1, 0 )) - { - /* Hide or disable scroll-bar */ - if (info->fMask & SIF_DISABLENOSCROLL) - { - new_flags = ESB_DISABLE_BOTH; - *action |= SA_SSI_REFRESH; - } - else if ((nBar != SB_CTL) && bChangeParams) - { - *action = SA_SSI_HIDE; - goto done; - } - } - else /* Show and enable scroll-bar */ - { - new_flags = 0; - if ((nBar != SB_CTL) && bChangeParams) - *action |= SA_SSI_SHOW; - } - - if (infoPtr->flags != new_flags) /* check arrow flags */ - { - infoPtr->flags = new_flags; - *action |= SA_SSI_REPAINT_ARROWS; - } - } - -done: - /* Return current position */ - - return infoPtr->curVal; + /* Refer SB_CTL requests to the window */ + if (nBar == SB_CTL) + return SendMessageA(hwnd, SBM_SETSCROLLINFO, (WPARAM)bRedraw, (LPARAM)info); + else + return SCROLL_SetScrollInfo(hwnd, nBar, info, bRedraw, FALSE, FALSE); } @@ -1711,22 +1739,19 @@ * to make sure there was an error (and to know which one). */ INT WINAPI SetScrollPos( -HWND hwnd /* [in] Handle of window whose scrollbar will be affected */, +HWND hwnd /* [in] Handle of window with scrollbar(s) */, INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, INT nPos /* [in] New value */, -BOOL bRedraw /* [in] Should scrollbar be redrawn afterwards ? */ ) +BOOL bRedraw /* [in] Should scrollbar be redrawn afterwards ? */) { - SCROLLINFO info; - SCROLLBAR_INFO *infoPtr; - INT oldPos; + TRACE("hwnd=%p nBar=%d nPos=%d bRedraw=%d\n", + hwnd, nBar, nPos, bRedraw); - if (!(infoPtr = SCROLL_GetScrollBarInfo( hwnd, nBar ))) return 0; - oldPos = infoPtr->curVal; - info.cbSize = sizeof(info); - info.nPos = nPos; - info.fMask = SIF_POS; - SetScrollInfo( hwnd, nBar, &info, bRedraw ); - return oldPos; + /* Refer SB_CTL requests to the window */ + if (nBar == SB_CTL) + return SendMessageA(hwnd, SBM_SETPOS, (WPARAM)nPos, (LPARAM)bRedraw); + else + return SCROLL_SetScrollPos(hwnd, nBar, nPos, bRedraw); } @@ -1761,57 +1786,25 @@ * RETURNS STD */ BOOL WINAPI SetScrollRange( -HWND hwnd, /* [in] Handle of window whose scrollbar will be affected */ -INT nBar, /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */ -INT minVal, /* [in] New minimum value */ -INT maxVal, /* [in] New maximum value */ +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, +INT minVal /* [in] New minimum value */, +INT maxVal /* [in] New maximum value */, BOOL bRedraw /* [in] Should scrollbar be redrawn afterwards ? */) { - SCROLLINFO info; - - info.cbSize = sizeof(info); - info.nMin = minVal; - info.nMax = maxVal; - info.fMask = SIF_RANGE; - SetScrollInfo( hwnd, nBar, &info, bRedraw ); - return TRUE; -} - + TRACE("hwnd=%p nBar=%d minVal=%d maxVal=%d bRedraw=%d\n", + hwnd, nBar, minVal, maxVal, bRedraw); -/************************************************************************* - * SCROLL_SetNCSbState - * - * Updates both scrollbars at the same time. Used by MDI CalcChildScroll(). - */ -INT SCROLL_SetNCSbState(HWND hwnd, int vMin, int vMax, int vPos, - int hMin, int hMax, int hPos) -{ - INT vA, hA; - SCROLLINFO vInfo, hInfo; - - vInfo.cbSize = hInfo.cbSize = sizeof(SCROLLINFO); - vInfo.nMin = vMin; - vInfo.nMax = vMax; - vInfo.nPos = vPos; - hInfo.nMin = hMin; - hInfo.nMax = hMax; - hInfo.nPos = hPos; - vInfo.fMask = hInfo.fMask = SIF_RANGE | SIF_POS; - - SCROLL_SetScrollInfo( hwnd, SB_VERT, &vInfo, &vA ); - SCROLL_SetScrollInfo( hwnd, SB_HORZ, &hInfo, &hA ); - - if( !SCROLL_ShowScrollBar( hwnd, SB_BOTH, - (hA & SA_SSI_SHOW),(vA & SA_SSI_SHOW) ) ) - { - /* SetWindowPos() wasn't called, just redraw the scrollbars if needed */ - if( vA & SA_SSI_REFRESH ) - SCROLL_RefreshScrollBar( hwnd, SB_VERT, FALSE, TRUE ); - - if( hA & SA_SSI_REFRESH ) - SCROLL_RefreshScrollBar( hwnd, SB_HORZ, FALSE, TRUE ); - } - return 0; + /* Refer SB_CTL requests to the window */ + if (nBar == SB_CTL) + if (bRedraw) + return SendMessageA(hwnd, SBM_SETRANGEREDRAW, + (WPARAM)minVal, (LPARAM)maxVal); + else + return SendMessageA(hwnd, SBM_SETRANGE, + (WPARAM)minVal, (LPARAM)maxVal); + else + return SCROLL_SetScrollRange(hwnd, nBar, minVal, maxVal, bRedraw, FALSE); } @@ -1837,116 +1830,88 @@ /************************************************************************* - * SCROLL_ShowScrollBar() + * ShowScrollBar (USER32.@) * - * Back-end for ShowScrollBar(). Returns FALSE if no action was taken. + * RETURNS STD */ -BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, - BOOL fShowH, BOOL fShowV ) +BOOL WINAPI ShowScrollBar( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */, +BOOL fShow /* [in] TRUE = show, FALSE = hide */) { - LONG style = GetWindowLongW( hwnd, GWL_STYLE ); + LONG style = GetWindowLongW(hwnd, GWL_STYLE); + LONG oldStyle = style; - TRACE("hwnd=%p bar=%d horz=%d, vert=%d\n", hwnd, nBar, fShowH, fShowV ); + TRACE("hwnd=%p nBar=%d fShow=%d\n", hwnd, nBar, fShow); - switch(nBar) + /* change the show state as requested */ + switch (nBar) { case SB_CTL: - ShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE ); + ShowWindow(hwnd, fShow ? SW_SHOW : SW_HIDE); return TRUE; case SB_BOTH: case SB_HORZ: - if (fShowH) - { - fShowH = !(style & WS_HSCROLL); + if (fShow) style |= WS_HSCROLL; - } else /* hide it */ - { - fShowH = (style & WS_HSCROLL); style &= ~WS_HSCROLL; - } - if( nBar == SB_HORZ ) { - fShowV = FALSE; - break; - } - /* fall through */ - + if (nBar == SB_HORZ) break; + /* fall through */ case SB_VERT: - if (fShowV) - { - fShowV = !(style & WS_VSCROLL); + if (fShow) style |= WS_VSCROLL; - } - else /* hide it */ - { - fShowV = (style & WS_VSCROLL); + else /* hide it */ style &= ~WS_VSCROLL; - } - if ( nBar == SB_VERT ) - fShowH = FALSE; - break; - default: - return FALSE; /* Nothing to do! */ + break; } - if( fShowH || fShowV ) /* frame has been changed, let the window redraw itself */ + /* update the window if frame has changed */ + if (style != oldStyle) { - WIN_SetStyle( hwnd, style ); - SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE - | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); - return TRUE; + WIN_SetStyle(hwnd, style); + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | + SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED); } - return FALSE; /* no frame changes */ -} - -/************************************************************************* - * ShowScrollBar (USER32.@) - * - * RETURNS STD - */ -BOOL WINAPI ShowScrollBar( -HWND hwnd, /* [in] Handle of window whose scrollbar(s) will be affected */ -INT nBar, /* [in] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */ -BOOL fShow /* [in] TRUE = show, FALSE = hide */) -{ - SCROLL_ShowScrollBar( hwnd, nBar, (nBar == SB_VERT) ? 0 : fShow, - (nBar == SB_HORZ) ? 0 : fShow ); return TRUE; } /************************************************************************* * EnableScrollBar (USER32.@) + * + * RETURNS STD */ -BOOL WINAPI EnableScrollBar( HWND hwnd, INT nBar, UINT flags ) +BOOL WINAPI EnableScrollBar( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */, +UINT flags /* [in] Flags indicating which scroll bars to enable */) { - BOOL bFineWithMe; - SCROLLBAR_INFO *infoPtr; - - TRACE("%p %d %d\n", hwnd, nBar, flags ); + BOOL ret = TRUE; + LPSCROLLBAR_INFO infoPtr; - flags &= ESB_DISABLE_BOTH; + TRACE("hwnd=%p nBar=%d flags=%04x\n", hwnd, nBar, flags); + /* use recursion to handle the case of two scroll bars */ if (nBar == SB_BOTH) { - if (!(infoPtr = SCROLL_GetScrollBarInfo( hwnd, SB_VERT ))) return FALSE; - if (!(bFineWithMe = (infoPtr->flags == flags)) ) - { - infoPtr->flags = flags; - SCROLL_RefreshScrollBar( hwnd, SB_VERT, TRUE, TRUE ); - } - nBar = SB_HORZ; + ret = EnableScrollBar(hwnd, SB_VERT, flags); + nBar = SB_HORZ; } - else - bFineWithMe = TRUE; - if (!(infoPtr = SCROLL_GetScrollBarInfo( hwnd, nBar ))) return FALSE; - if (bFineWithMe && infoPtr->flags == flags) return FALSE; - infoPtr->flags = flags; + /* change the enable flags of the bar and redraw if necessary */ + flags &= ~ESB_DISABLE_BOTH; + infoPtr = SCROLL_GetScrollBarInfo(hwnd, nBar); + ret = ret && infoPtr && (infoPtr->flags != flags); + if (ret) + { + infoPtr->flags = flags; + if (WIN_IsWindowDrawable(hwnd, FALSE)) + SCROLL_RefreshScrollBar(hwnd, nBar, TRUE, TRUE); + } - SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); - return TRUE; + return ret; }