Dear All, As discussed with Alexandre, this patch makes the GetScroll* API functions send a message to the Window in the case of SB_CTL scroll bars. I had to change the name of the existing SCROLL_GetScrollInfo function to SCROLL_GetScrollBarInfo so that the helper for the API function could use the original name. There are two small parts of the the previous scroll clean up since I used parts of the previous clean up in the internal helper functions. The next patch will add the rest of the first two parts of the original clean up. This also fixes a bug with the return values in GetScrollRange if the info pointer cannot be obtained. Changelog: scrollbar.c - GetScrollRange zeros the return parameters for no infoPtr - GetScrollRange, GetScrollPos and GetScrollInfo send a message to the window for the SB_CTL case - Moves code for GetScroll* to into worker functions License: X11 Andrew Index: controls/scroll.c =================================================================== RCS file: /home/wine/wine/controls/scroll.c,v retrieving revision 1.62 diff -u -r1.62 scroll.c --- controls/scroll.c 14 Jan 2003 23:41:01 -0000 1.62 +++ controls/scroll.c 6 Mar 2003 01:36:00 -0000 @@ -37,7 +37,7 @@ INT maxVal; /* Maximum scroll-bar value */ INT page; /* Page size of scroll bar (Win32) */ UINT flags; /* EnableScrollBar flags */ -} SCROLLBAR_INFO; +} SCROLLBAR_INFO, *LPSCROLLBAR_INFO; static HBITMAP hUpArrow; @@ -81,6 +81,12 @@ /* Scroll timer id */ #define SCROLL_TIMER 0 +/* 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)))) + /* Scroll-bar hit testing */ enum SCROLL_HITTEST { @@ -159,9 +165,9 @@ /*********************************************************************** - * SCROLL_GetScrollInfo + * SCROLL_GetScrollBarInfo */ -static SCROLLBAR_INFO *SCROLL_GetScrollInfo( HWND hwnd, INT nBar ) +static SCROLLBAR_INFO *SCROLL_GetScrollBarInfo( HWND hwnd, INT nBar ) { SCROLLBAR_INFO *infoPtr; WND *wndPtr = WIN_FindWndPtr( hwnd ); @@ -267,7 +273,7 @@ } else { - SCROLLBAR_INFO *info = SCROLL_GetScrollInfo( hwnd, nBar ); + SCROLLBAR_INFO *info = SCROLL_GetScrollBarInfo( hwnd, nBar ); *arrowSize = GetSystemMetrics(SM_CXVSCROLL); pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)); @@ -802,7 +808,7 @@ RECT rect; BOOL vertical; WND *wndPtr = WIN_FindWndPtr( hwnd ); - SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ); + SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollBarInfo( hwnd, nBar ); BOOL Save_SCROLL_MovingThumb = SCROLL_MovingThumb; if (!wndPtr || !infoPtr || @@ -930,7 +936,7 @@ RECT rect; HDC hdc; - SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ); + SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollBarInfo( hwnd, nBar ); if (!infoPtr) return; if ((SCROLL_trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN)) return; @@ -1192,6 +1198,75 @@ } +/************************************************************************* + * SCROLL_GetScrollInfo + * + * Internal helper for the API function + */ +static BOOL SCROLL_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) + || (!(infoPtr = SCROLL_GetScrollBarInfo(hwnd, nBar)))) + return FALSE; + + /* 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_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; +} + + +/************************************************************************* + * SCROLL_GetScrollPos + * + * Internal helper for the API function + */ +static INT SCROLL_GetScrollPos( +HWND hwnd /* [in] Handle of window with scrollbar(s) */, +INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */) +{ + LPSCROLLBAR_INFO infoPtr = SCROLL_GetScrollBarInfo(hwnd, nBar); + return infoPtr ? infoPtr->curVal: 0; +} + + +/************************************************************************* + * SCROLL_GetScrollRange + * + * Internal helper for the API function + * + * RETURNS STD + */ +static BOOL SCROLL_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 */ +LPINT lpMax /* [out] Where to store maximum value */) +{ + LPSCROLLBAR_INFO infoPtr = SCROLL_GetScrollBarInfo(hwnd, nBar); + + if (lpMin) *lpMin = infoPtr ? infoPtr->minVal : 0; + if (lpMax) *lpMax = infoPtr ? infoPtr->maxVal : 0; + + return infoPtr ? TRUE : FALSE; +} + + + /*********************************************************************** * ScrollBarWndProc */ @@ -1206,7 +1281,7 @@ SCROLLBAR_INFO *infoPtr; CREATESTRUCTW *lpCreat = (CREATESTRUCTW *)lParam; - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, SB_CTL ))) return -1; + if (!(infoPtr = SCROLL_GetScrollBarInfo( hwnd, SB_CTL ))) return -1; if (lpCreat->style & WS_DISABLED) { TRACE("Created WS_DISABLED scrollbar\n"); @@ -1243,7 +1318,7 @@ case WM_ENABLE: { SCROLLBAR_INFO *infoPtr; - if ((infoPtr = SCROLL_GetScrollInfo( hwnd, SB_CTL ))) + if ((infoPtr = SCROLL_GetScrollBarInfo( hwnd, SB_CTL ))) { infoPtr->flags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH; SCROLL_RefreshScrollBar(hwnd, SB_CTL, TRUE, TRUE); @@ -1347,7 +1422,7 @@ case SBM_GETPOS16: case SBM_GETPOS: - return GetScrollPos( hwnd, SB_CTL ); + return SCROLL_GetScrollPos(hwnd, SB_CTL); case SBM_SETRANGE16: SetScrollRange( hwnd, SB_CTL, LOWORD(lParam), HIWORD(lParam), @@ -1356,9 +1431,9 @@ case SBM_SETRANGE: { - INT oldPos = GetScrollPos( hwnd, SB_CTL ); + INT oldPos = SCROLL_GetScrollPos( hwnd, SB_CTL ); SetScrollRange( hwnd, SB_CTL, wParam, lParam, FALSE ); - if (oldPos != GetScrollPos( hwnd, SB_CTL )) return oldPos; + if (oldPos != SCROLL_GetScrollPos( hwnd, SB_CTL )) return oldPos; } return 0; @@ -1367,8 +1442,7 @@ return 0; case SBM_GETRANGE: - GetScrollRange( hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam ); - return 0; + return SCROLL_GetScrollRange(hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam); case SBM_ENABLE_ARROWS16: case SBM_ENABLE_ARROWS: @@ -1376,9 +1450,9 @@ case SBM_SETRANGEREDRAW: { - INT oldPos = GetScrollPos( hwnd, SB_CTL ); + INT oldPos = SCROLL_GetScrollPos( hwnd, SB_CTL ); SetScrollRange( hwnd, SB_CTL, wParam, lParam, TRUE ); - if (oldPos != GetScrollPos( hwnd, SB_CTL )) return oldPos; + if (oldPos != SCROLL_GetScrollPos( hwnd, SB_CTL )) return oldPos; } return 0; @@ -1386,7 +1460,7 @@ return SetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam, wParam ); case SBM_GETSCROLLINFO: - return GetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam ); + return SCROLL_GetScrollInfo(hwnd, SB_CTL, (SCROLLINFO *)lParam); case 0x00e5: case 0x00e7: @@ -1461,7 +1535,7 @@ *action = 0; - if (!(infoPtr = SCROLL_GetScrollInfo(hwnd, nBar))) return 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; @@ -1587,33 +1661,24 @@ /************************************************************************* * GetScrollInfo (USER32.@) + * * 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) */) +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) */) { - 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; + TRACE("hwnd=%p nBar=%d info=%p\n", hwnd, nBar, info); - 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; + /* Refer SB_CTL requests to the window */ + if (nBar == SB_CTL) + return SendMessageA(hwnd, SBM_GETSCROLLINFO, (WPARAM)0, (LPARAM)info); + else + return SCROLL_GetScrollInfo(hwnd, nBar, info); } @@ -1638,7 +1703,7 @@ SCROLLBAR_INFO *infoPtr; INT oldPos; - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0; + if (!(infoPtr = SCROLL_GetScrollBarInfo( hwnd, nBar ))) return 0; oldPos = infoPtr->curVal; info.cbSize = sizeof(info); info.nPos = nPos; @@ -1656,17 +1721,20 @@ * 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 */ +HWND hwnd /* [in] Handle of window with scrollbar(s) */, INT nBar /* [in] One of SB_HORZ, SB_VERT, or SB_CTL */) { - SCROLLBAR_INFO *infoPtr; + TRACE("hwnd=%p nBar=%d\n", hwnd, nBar); - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0; - return infoPtr->curVal; + /* Refer SB_CTL requests to the window */ + if (nBar == SB_CTL) + return SendMessageA(hwnd, SBM_GETPOS, (WPARAM)0, (LPARAM)0); + else + return SCROLL_GetScrollPos(hwnd, nBar); } @@ -1736,22 +1804,18 @@ * 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 */ +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; + TRACE("hwnd=%p nBar=%d lpMin=%p lpMax=%p\n", hwnd, nBar, lpMin, lpMax); - 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; + /* Refer SB_CTL requests to the window */ + if (nBar == SB_CTL) + return SendMessageA(hwnd, SBM_GETRANGE, (WPARAM)lpMin, (LPARAM)lpMax); + else + return SCROLL_GetScrollRange(hwnd, nBar, lpMin, lpMax); } @@ -1851,7 +1915,7 @@ if (nBar == SB_BOTH) { - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, SB_VERT ))) return FALSE; + if (!(infoPtr = SCROLL_GetScrollBarInfo( hwnd, SB_VERT ))) return FALSE; if (!(bFineWithMe = (infoPtr->flags == flags)) ) { infoPtr->flags = flags; @@ -1862,7 +1926,7 @@ else bFineWithMe = TRUE; - if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE; + if (!(infoPtr = SCROLL_GetScrollBarInfo( hwnd, nBar ))) return FALSE; if (bFineWithMe && infoPtr->flags == flags) return FALSE; infoPtr->flags = flags;