Changelog: scrollbar.c - removes SCROLL_ShowScrollBar SCROLL_SetScrollInfo - breaks SCROLL_GetScrollInfo into two functions - significantly simplifies SetScrollInfo - simplifies other api functions This interim patch will do a little more drawing than is strictly necessary. (I hear what you asked re not changing names of things but in the interest of producing something this version does make the structure names lower case as is common else where and hence there are some irrelevant changes in SCROLL_GetScrollBarRect) The patch was developed without CVS access use patch -p1 from within the top level wine directory to apply Requires the mdi patch sent on Thursday. License: X11 Andrew --- wine-20020904/controls/scroll.c Sat Aug 3 08:13:48 2002 +++ wine/controls/scroll.c Tue Oct 8 16:04:32 2002 @@ -30,15 +30,25 @@ WINE_DEFAULT_DEBUG_CHANNEL(scroll); +/********************************************************************* + * scrollbar state + * + * Lives as long as the scroll bar + */ typedef struct { - INT CurVal; /* Current scroll-bar value */ - INT MinVal; /* Minimum scroll-bar value */ - INT MaxVal; /* Maximum scroll-bar value */ - INT Page; /* Page size of scroll bar (Win32) */ - UINT flags; /* EnableScrollBar flags */ -} SCROLLBAR_INFO; - + INT curVal; /* Current scroll-bar value */ + INT minVal; /* Minimum scroll-bar value */ + INT maxVal; /* Maximum scroll-bar value */ + INT page; /* Page size of scroll bar (Win32) */ + UINT flags; /* EnableScrollBar flags */ +} SCROLLBAR_INFO, *LPSCROLLBAR_INFO; + +/* Determine if the info is valid */ +#define SCROLL_INFO_INVALID(info) \ + ((info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) || \ + ((info->cbSize != sizeof(*info)) && \ + (info->cbSize != sizeof(*info) - sizeof(info->nTrackPos)))) static HBITMAP hUpArrow; static HBITMAP hDnArrow; @@ -111,10 +121,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, @@ -159,41 +165,58 @@ /*********************************************************************** + * SCROLL_GetInfo + * + * Obtains a valid info pointer for the requested bar + * (creates structure when required) + * + * RETURNS + * Pointer to a scroll info structure + */ +static LPSCROLLBAR_INFO SCROLL_GetInfo( +SCROLLBAR_INFO **info /* [in/out] Potentially the scroll info pointer */) +{ + if (!(*info) && (*info = HeapAlloc(GetProcessHeap(), 0, sizeof(SCROLLBAR_INFO)))) + { + (*info)->minVal = (*info)->curVal = (*info)->page = 0; + (*info)->maxVal = 100; + (*info)->flags = ESB_ENABLE_BOTH; + (*info)->page = 0; + } + return *info; +} + + +/*********************************************************************** * SCROLL_GetScrollInfo + * + * Get the scoll info structure for the scroll bar + * + * RETURNS + * Scroll info pointer */ -static SCROLLBAR_INFO *SCROLL_GetScrollInfo( HWND hwnd, INT nBar ) +LPSCROLLBAR_INFO SCROLL_GetScrollInfo( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */) { - SCROLLBAR_INFO *infoPtr; - WND *wndPtr = WIN_FindWndPtr( hwnd ); + WND *wnd = WIN_FindWndPtr(hwnd); + LPSCROLLBAR_INFO info = 0; - if (!wndPtr) return NULL; - switch(nBar) - { - case SB_HORZ: infoPtr = (SCROLLBAR_INFO *)wndPtr->pHScroll; break; - case SB_VERT: infoPtr = (SCROLLBAR_INFO *)wndPtr->pVScroll; break; - case SB_CTL: infoPtr = (SCROLLBAR_INFO *)wndPtr->wExtra; break; - default: - WIN_ReleaseWndPtr( wndPtr ); - return NULL; - } + if (wnd) + { + switch (nBar) + { + case SB_HORZ: info = SCROLL_GetInfo((SCROLLBAR_INFO **)&(wnd->pHScroll)); break; + case SB_VERT: info = SCROLL_GetInfo((SCROLLBAR_INFO **)&(wnd->pVScroll)); break; + case SB_CTL: info = SCROLL_GetInfo((SCROLLBAR_INFO **)&(wnd->wExtra)); break; + default: ERR("Unhandled scroll bar type\n"); break; + } + WIN_ReleasePtr(wnd); + } - if (!infoPtr) /* Create the info structure if needed */ - { - if ((infoPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(SCROLLBAR_INFO) ))) - { - infoPtr->MinVal = infoPtr->CurVal = infoPtr->Page = 0; - infoPtr->MaxVal = 100; - infoPtr->flags = ESB_ENABLE_BOTH; - if (nBar == SB_HORZ) wndPtr->pHScroll = infoPtr; - else wndPtr->pVScroll = infoPtr; - } - if (!hUpArrow) SCROLL_LoadBitmaps(); - } - WIN_ReleaseWndPtr( wndPtr ); - return infoPtr; + return info; } - /*********************************************************************** * SCROLL_GetScrollBarRect * @@ -269,9 +292,9 @@ *arrowSize = GetSystemMetrics(SM_CXVSCROLL); pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)); - if (info->Page) + if (info->page) { - *thumbSize = MulDiv(pixels,info->Page,(info->MaxVal-info->MinVal+1)); + *thumbSize = MulDiv(pixels,info->page,(info->maxVal-info->minVal+1)); if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB; } else *thumbSize = GetSystemMetrics(SM_CXVSCROLL); @@ -284,12 +307,12 @@ } else { - INT max = info->MaxVal - max( info->Page-1, 0 ); - if (info->MinVal >= max) + 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)); + + MulDiv(pixels, (info->curVal-info->minVal),(max - info->minVal)); } } WIN_ReleaseWndPtr(wndPtr); @@ -310,23 +333,23 @@ 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; + return infoPtr->minVal; - if (infoPtr->Page) + if (infoPtr->page) { - thumbSize = MulDiv(pixels,infoPtr->Page,(infoPtr->MaxVal-infoPtr->MinVal+1)); + 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; + 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); + if (!infoPtr->page) pos *= infoPtr->maxVal - infoPtr->minVal; + else pos *= infoPtr->maxVal - infoPtr->minVal - infoPtr->page + 1; + return infoPtr->minVal + ((pos + pixels / 2) / pixels); } /*********************************************************************** @@ -1407,7 +1430,58 @@ /************************************************************************* + * ShowScrollBar (USER32.@) + * + * RETURNS STD + */ +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 oldStyle = style; + + TRACE("hwnd=%04x nBar=%d fShow=%d\n", hwnd, nBar, fShow); + + /* change the show state as requested */ + switch (nBar) + { + case SB_CTL: + ShowWindow(hwnd, fShow ? SW_SHOW : SW_HIDE ); + return TRUE; + + case SB_BOTH: + case SB_HORZ: + if (fShow) + style |= WS_HSCROLL; + else /* hide it */ + style &= ~WS_HSCROLL; + if (nBar == SB_HORZ) break; + /* fall through */ + case SB_VERT: + if (fShow) + style |= WS_VSCROLL; + else /* hide it */ + style &= ~WS_VSCROLL; + default: + break; + } + + /* 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; +} + + +/************************************************************************* * SetScrollInfo (USER32.@) + * * SetScrollInfo can be used to set the position, upper bound, * lower bound, and page size of a scrollbar control. * @@ -1416,200 +1490,150 @@ * * 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 */, -INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, +INT WINAPI 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 ? */) { - 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. */ + LPSCROLLBAR_INFO infoPtr; + BOOL changed = FALSE; /* only show/hide scrollbar if params change */ + INT gap, value; + UINT oldFlags; + + /* handle invalid data structure */ + if (SCROLL_INFO_INVALID(info)) return 0; + infoPtr = SCROLL_GetScrollInfo(hwnd, nBar); + if (!infoPtr) return 0; - SCROLLBAR_INFO *infoPtr; - UINT new_flags; - BOOL bChangeParams = FALSE; /* don't show/hide scrollbar if params don't change */ - - *action = 0; - - if (!(infoPtr = SCROLL_GetScrollInfo(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; - - if (TRACE_ON(scroll)) - { - TRACE("hwnd=%04x 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 ) + if (TRACE_ON(scroll)) { - infoPtr->Page = info->nPage; - *action |= SA_SSI_REFRESH; - bChangeParams = TRUE; + TRACE("hwnd=%04x 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(" bRedraw=%d\n", bRedraw); } - } - /* Set the scroll pos */ - - if (info->fMask & SIF_POS) - { - if( infoPtr->CurVal != info->nPos ) + /* set the scroll range */ + if (info->fMask & SIF_RANGE) { - infoPtr->CurVal = info->nPos; - *action |= SA_SSI_REFRESH; + 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; + } } - } - - /* 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; - } - } - } - - /* 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; - } + /* 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; + } - if (infoPtr->flags != new_flags) /* check arrow flags */ - { - infoPtr->flags = new_flags; - *action |= SA_SSI_REPAINT_ARROWS; - } - } + /* set the scroll pos */ + 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; + if (!(info->fMask & SIF_ALL)) + ; /* if called without SIF_ALL don't change state */ + else if (info->fMask & SIF_DISABLENOSCROLL) + infoPtr->flags |= ESB_DISABLE_BOTH; + else if (changed && (nBar != SB_CTL) && + (info->fMask & (SIF_RANGE | SIF_PAGE))) + ShowScrollBar(hwnd, nBar, infoPtr->minVal < gap); -done: - /* Return current position */ + /* change position if required */ + if (value != infoPtr->curVal) + { + infoPtr->curVal = value; + changed = 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 infoPtr->CurVal; + return infoPtr->curVal; } /************************************************************************* * GetScrollInfo (USER32.@) - * GetScrollInfo can be used to retrieve the position, upper bound, + * + * GetScrollInfo can be used to retrieve the position, upper bound, * lower bound, and page size of a scrollbar control. * * RETURNS STD */ -BOOL WINAPI GetScrollInfo( - HWND hwnd /* [in] Handle of window */ , - INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, - LPSCROLLINFO info /* [in/out] (info.fMask [in] specifies which values are to retrieve) */) -{ - SCROLLBAR_INFO *infoPtr; - - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE; - if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return FALSE; - if ((info->cbSize != sizeof(*info)) && - (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return FALSE; - - if (info->fMask & SIF_PAGE) info->nPage = infoPtr->Page; - if (info->fMask & SIF_POS) info->nPos = infoPtr->CurVal; - if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info))) - info->nTrackPos = (SCROLL_TrackingWin == WIN_GetFullHandle(hwnd)) ? SCROLL_TrackingVal : infoPtr->CurVal; - if (info->fMask & SIF_RANGE) - { - info->nMin = infoPtr->MinVal; - info->nMax = infoPtr->MaxVal; - } - return (info->fMask & SIF_ALL) != 0; +BOOL WINAPI GetScrollInfo( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, +LPSCROLLINFO info /* [in/out] (fMask specifies which values to retrieve) */) +{ + LPSCROLLBAR_INFO infoPtr; + + /* handle invalid data structure */ + if (SCROLL_INFO_INVALID(info)) return FALSE; + infoPtr = SCROLL_GetScrollInfo(hwnd, nBar); + if (!infoPtr) return FALSE; + + TRACE("hwnd=%04x nBar=%d info=%p\n", hwnd, nBar, info); + + /* fill in the desired scroll info structure */ + if (info->fMask & SIF_PAGE) info->nPage = infoPtr->page; + if (info->fMask & SIF_POS) info->nPos =infoPtr->curVal; + if (info->fMask & SIF_RANGE) + { + info->nMin = infoPtr->minVal; + info->nMax = infoPtr->maxVal; + } + if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info))) + info->nTrackPos = infoPtr->curVal; + + return (info->fMask & SIF_ALL); } @@ -1624,23 +1648,25 @@ * Note the ambiguity when 0 is returned. Use GetLastError * 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 */, +INT WINAPI 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 ? */ ) +BOOL bRedraw /* [in] Should scrollbar be redrawn afterwards ? */) { - SCROLLINFO info; - SCROLLBAR_INFO *infoPtr; - INT oldPos; - - if (!(infoPtr = SCROLL_GetScrollInfo( 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; + INT oldPos = GetScrollPos(hwnd, nBar); + SCROLLINFO info; + + TRACE("hwnd=%04x nBar=%d nPos=%d bRedraw=%d\n", + hwnd, nBar, nPos, bRedraw); + + /* fill in an info structure and use common set info code */ + info.cbSize = sizeof(info); + info.nPos = nPos; + info.fMask = SIF_POS; + SetScrollInfo(hwnd, nBar, &info, bRedraw); + + return oldPos; } @@ -1649,20 +1675,21 @@ * * RETURNS * Success: Current position - * Failure: 0 + * Failure: 0 * * REMARKS - * Note the ambiguity when 0 is returned. Use GetLastError + * There is ambiguity when 0 is returned. Use GetLastError * to make sure there was an error (and to know which one). */ -INT WINAPI GetScrollPos( -HWND hwnd, /* [in] Handle of window */ +INT WINAPI GetScrollPos( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */) { - SCROLLBAR_INFO *infoPtr; + LPSCROLLBAR_INFO info = SCROLL_GetScrollInfo(hwnd, nBar); - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0; - return infoPtr->CurVal; + TRACE("hwnd=%04x nBar=%d\n", hwnd, nBar); + + return info ? info->curVal: 0; } @@ -1671,58 +1698,26 @@ * * 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 */ +BOOL WINAPI 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 ? */) { - SCROLLINFO info; - - info.cbSize = sizeof(info); - info.nMin = MinVal; - info.nMax = MaxVal; - info.fMask = SIF_RANGE; - SetScrollInfo( hwnd, nBar, &info, bRedraw ); - return TRUE; -} - - -/************************************************************************* - * 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; + SCROLLINFO info; - SCROLL_SetScrollInfo( hwnd, SB_VERT, &vInfo, &vA ); - SCROLL_SetScrollInfo( hwnd, SB_HORZ, &hInfo, &hA ); + TRACE("hwnd=%04x nBar=%d minVal=%d maxVal=%d bRedraw=%d\n", + hwnd, nBar, minVal, maxVal, bRedraw); - 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 ); + /* 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; + SetScrollInfo(hwnd, nBar, &info, bRedraw); - if( hA & SA_SSI_REFRESH ) - SCROLL_RefreshScrollBar( hwnd, SB_HORZ, FALSE, TRUE ); - } - return 0; + return TRUE; } @@ -1731,138 +1726,55 @@ * * RETURNS STD */ -BOOL WINAPI GetScrollRange( -HWND hwnd, /* [in] Handle of window */ -INT nBar, /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */ -LPINT lpMin, /* [out] Where to store minimum value */ +BOOL WINAPI GetScrollRange( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */, +LPINT lpMin /* [out] Where to store minimum value */, LPINT lpMax /* [out] Where to store maximum value */) { - SCROLLBAR_INFO *infoPtr; - - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) - { - if (lpMin) lpMin = 0; - if (lpMax) lpMax = 0; - return FALSE; - } - if (lpMin) *lpMin = infoPtr->MinVal; - if (lpMax) *lpMax = infoPtr->MaxVal; - return TRUE; -} - - -/************************************************************************* - * SCROLL_ShowScrollBar() - * - * Back-end for ShowScrollBar(). Returns FALSE if no action was taken. - */ -BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, - BOOL fShowH, BOOL fShowV ) -{ - LONG style = GetWindowLongW( hwnd, GWL_STYLE ); - - TRACE("hwnd=%04x bar=%d horz=%d, vert=%d\n", - hwnd, nBar, fShowH, fShowV ); - - switch(nBar) - { - case SB_CTL: - ShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE ); - return TRUE; - - case SB_BOTH: - case SB_HORZ: - if (fShowH) - { - fShowH = !(style & WS_HSCROLL); - style |= WS_HSCROLL; - } - else /* hide it */ - { - fShowH = (style & WS_HSCROLL); - style &= ~WS_HSCROLL; - } - if( nBar == SB_HORZ ) { - fShowV = FALSE; - break; - } - /* fall through */ - - case SB_VERT: - if (fShowV) - { - fShowV = !(style & WS_VSCROLL); - style |= WS_VSCROLL; - } - else /* hide it */ - { - fShowV = (style & WS_VSCROLL); - style &= ~WS_VSCROLL; - } - if ( nBar == SB_VERT ) - fShowH = FALSE; - break; + LPSCROLLBAR_INFO info = SCROLL_GetScrollInfo(hwnd, nBar); - default: - return FALSE; /* Nothing to do! */ - } - - if( fShowH || fShowV ) /* frame has been changed, let the window redraw itself */ - { - WIN_SetStyle( hwnd, style ); - SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE - | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); - return TRUE; - } - return FALSE; /* no frame changes */ + TRACE("hwnd=%04x nBar=%d lpMin=%p lpMax=%p\n", hwnd, nBar, lpMin, lpMax); + + if (lpMin) *lpMin = info ? info->minVal : 0; + if (lpMax) *lpMax = info ? info->maxVal : 0; + + return (BOOL)info; } /************************************************************************* - * ShowScrollBar (USER32.@) + * EnableScrollBar (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.@) - */ -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("%04x %d %d\n", hwnd, nBar, flags ); + BOOL ret = TRUE; + LPSCROLLBAR_INFO info; - flags &= ESB_DISABLE_BOTH; + TRACE("hwnd=%04x nBar=%d flags=%04x\n", hwnd, nBar, flags); - if (nBar == SB_BOTH) - { - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, SB_VERT ))) return FALSE; - if (!(bFineWithMe = (infoPtr->flags == flags)) ) + /* use recursion to handle the case of two scroll bars */ + if (nBar == SB_BOTH) { - infoPtr->flags = flags; - SCROLL_RefreshScrollBar( hwnd, SB_VERT, TRUE, TRUE ); + ret = EnableScrollBar(hwnd, SB_VERT, flags); + nBar = SB_HORZ; } - nBar = SB_HORZ; - } - else - bFineWithMe = TRUE; - if (!(infoPtr = SCROLL_GetScrollInfo( 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; + info = SCROLL_GetScrollInfo(hwnd, nBar); + ret = ret && info && (info->flags != flags); + if (ret) + { + info->flags = flags; + if (WIN_IsWindowDrawable(hwnd, FALSE)) + SCROLL_RefreshScrollBar(hwnd, nBar, TRUE, TRUE); + } - SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); - return TRUE; + return ret; }