diff --git a/reactos/include/reactos/undocuser.h b/reactos/include/reactos/undocuser.h index 14002b767ce..c0c6b53a3f5 100644 --- a/reactos/include/reactos/undocuser.h +++ b/reactos/include/reactos/undocuser.h @@ -68,6 +68,9 @@ #define SWP_NOCLIENTMOVE 0x1000 #define SWP_STATECHANGED 0x8000 +/* NtUserSetScrollInfo mask to return original position before it is change */ +#define SIF_PREVIOUSPOS 4096 + /* Non SDK Queue state flags. */ #define QS_SMRESULT 0x8000 /* see "Undoc. Windows" */ diff --git a/reactos/win32ss/user/ntuser/message.c b/reactos/win32ss/user/ntuser/message.c index 05e9dab483e..479e9510810 100644 --- a/reactos/win32ss/user/ntuser/message.c +++ b/reactos/win32ss/user/ntuser/message.c @@ -608,7 +608,7 @@ static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPAR pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND return 0; - TRACE("Internal Event Msg %p\n",msg); + TRACE("Internal Event Msg %p hWnd 0x%x\n",msg,pWnd->head.h); switch(msg) { @@ -742,7 +742,6 @@ co_IntPeekMessage( PMSG Msg, BOOL bGMSG ) { PTHREADINFO pti; - //PCLIENTINFO pci; LARGE_INTEGER LargeTickCount; PUSER_MESSAGE_QUEUE ThreadQueue; BOOL RemoveMessages; @@ -751,11 +750,15 @@ co_IntPeekMessage( PMSG Msg, pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; - //pci = pti->pClientInfo; RemoveMessages = RemoveMsg & PM_REMOVE; ProcessMask = HIWORD(RemoveMsg); + if (ThreadQueue->ptiSysLock && ThreadQueue->ptiSysLock != pti) + { + ERR("PeekMessage: Thread Q 0x%p is locked 0x%p to another pti 0x%p!\n", ThreadQueue, ThreadQueue->ptiSysLock, pti ); + } + /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns all available messages (that is, no range filtering is performed)". */ if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT); @@ -1182,6 +1185,7 @@ UserPostMessage( HWND Wnd, Window = UserGetWindowObject(Wnd); if ( !Window ) { + ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd); return FALSE; } @@ -1246,6 +1250,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd, if (!(Window = UserGetWindowObject(hWnd))) { + TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd); RETURN( FALSE); } @@ -1491,6 +1496,7 @@ co_IntSendMessageWithCallBack( HWND hWnd, if (!(Window = UserGetWindowObject(hWnd))) { + TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd); RETURN(FALSE); } @@ -1514,6 +1520,8 @@ co_IntSendMessageWithCallBack( HWND hWnd, if (Msg & 0x80000000 && Window->head.pti->MessageQueue == Win32Thread->MessageQueue) { + if (Win32Thread->TIF_flags & TIF_INCLEANUP) RETURN( FALSE); + ERR("SMWCB: Internal Message!\n"); Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam ); if (uResult) *uResult = Result; @@ -1650,6 +1658,7 @@ co_IntPostOrSendMessage( HWND hWnd, if(!(Window = UserGetWindowObject(hWnd))) { + TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd); return 0; } @@ -2158,6 +2167,8 @@ NtUserTranslateMessage(LPMSG lpMsg, UINT flags) return Ret; } +LRESULT APIENTRY ScrollBarWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam); + BOOL APIENTRY NtUserMessageCall( HWND hWnd, UINT Msg, @@ -2178,18 +2189,7 @@ NtUserMessageCall( HWND hWnd, { case FNID_SCROLLBAR: { - switch(Msg) - { - case WM_ENABLE: - { - Window = UserGetWindowObject(hWnd); - if (Window->pSBInfo) - { - Window->pSBInfo->WSBflags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH; - } - } - break; - } + lResult = ScrollBarWndProc(hWnd, Msg, wParam, lParam); break; } case FNID_DEFWINDOWPROC: @@ -2675,6 +2675,7 @@ NtUserMessageCall( HWND hWnd, case FNID_DEFWINDOWPROC: case FNID_CALLWNDPROC: case FNID_CALLWNDPROCRET: + case FNID_SCROLLBAR: if (ResultInfo) { _SEH2_TRY diff --git a/reactos/win32ss/user/ntuser/scrollbar.c b/reactos/win32ss/user/ntuser/scrollbar.c index c31dcf298f7..775a543f1d0 100644 --- a/reactos/win32ss/user/ntuser/scrollbar.c +++ b/reactos/win32ss/user/ntuser/scrollbar.c @@ -38,42 +38,94 @@ DBG_DEFAULT_CHANNEL(UserScrollbar); * '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 inline void mirror_rect( const RECT *window_rect, RECT *rect ) +{ + int width = window_rect->right - window_rect->left; + int tmp = rect->left; + rect->left = width - rect->right; + rect->right = width - tmp; +} + +PSBDATA FASTCALL +IntGetSBData(PWND pwnd, INT Bar) +{ + PSBWND pSBWnd; + PSBINFO pSBInfo; + + pSBInfo = pwnd->pSBInfo; + switch (Bar) + { + case SB_HORZ: + return &pSBInfo->Horz; + case SB_VERT: + return &pSBInfo->Vert; + case SB_CTL: + if ( pwnd->cbwndExtra != (sizeof(SBWND)-sizeof(WND)) ) + { + ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n"); + return 0; + } + pSBWnd = (PSBWND)pwnd; + return (PSBDATA)&pSBWnd->SBCalc; + default: + ERR("IntGetSBData Bad Bar!\n"); + } + return NULL; +} + BOOL FASTCALL IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect) { BOOL vertical; - RECTL ClientRect = Wnd->rcClient; - RECTL WindowRect = Wnd->rcWindow; + *lprect = Wnd->rcClient; + + RECTL_vOffsetRect( lprect, -Wnd->rcWindow.left, -Wnd->rcWindow.top ); + if (Wnd->ExStyle & WS_EX_LAYOUTRTL) + mirror_rect( &Wnd->rcWindow, lprect ); switch (nBar) { case SB_HORZ: - lprect->left = ClientRect.left - WindowRect.left; - lprect->top = ClientRect.bottom - WindowRect.top; - lprect->right = ClientRect.right - WindowRect.left; - lprect->bottom = lprect->top + UserGetSystemMetrics (SM_CYHSCROLL); + lprect->top = lprect->bottom; + lprect->bottom += UserGetSystemMetrics (SM_CYHSCROLL); + if (Wnd->style & WS_BORDER) + { + lprect->left--; + lprect->right++; + } + else if (Wnd->style & WS_VSCROLL) + { + lprect->right++; + } vertical = FALSE; break; case SB_VERT: if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR) { - lprect->right = ClientRect.left - WindowRect.left; - lprect->left = lprect->right - UserGetSystemMetrics(SM_CXVSCROLL); + lprect->right = lprect->right;; + lprect->left -= UserGetSystemMetrics(SM_CXVSCROLL); } else { - lprect->left = ClientRect.right - WindowRect.left; - lprect->right = lprect->left + UserGetSystemMetrics(SM_CXVSCROLL); + lprect->left = lprect->right; + lprect->right += UserGetSystemMetrics(SM_CXVSCROLL); + } + if (Wnd->style & WS_BORDER) + { + lprect->top--; + lprect->bottom++; + } + else if (Wnd->style & WS_HSCROLL) + { + lprect->bottom++; } - lprect->top = ClientRect.top - WindowRect.top; - lprect->bottom = ClientRect.bottom - WindowRect.top; vertical = TRUE; break; case SB_CTL: IntGetClientRect (Wnd, lprect); - vertical = ((Wnd->style & SBS_VERT) != 0); + vertical = !!(Wnd->style & SBS_VERT); break; default: @@ -84,7 +136,7 @@ IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect) } BOOL FASTCALL -IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi) +IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, PSBDATA pSBData) { INT Thumb, ThumbBox, ThumbPos, cxy, mx; RECTL ClientRect; @@ -127,20 +179,20 @@ IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi } else { - ThumbBox = psi->nPage ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB); + ThumbBox = pSBData->page ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB); cxy -= (2 * Thumb); if(cxy >= ThumbBox) { - if(psi->nPage) + if(pSBData->page) { - ThumbBox = max(EngMulDiv(cxy, psi->nPage, psi->nMax - psi->nMin + 1), ThumbBox); + ThumbBox = max(EngMulDiv(cxy, pSBData->page, pSBData->posMax - pSBData->posMin + 1), ThumbBox); } if(cxy > ThumbBox) { - mx = psi->nMax - max(psi->nPage - 1, 0); - if(psi->nMin < mx) - ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, psi->nPos - psi->nMin, mx - psi->nMin); + mx = pSBData->posMax - max(pSBData->page - 1, 0); + if(pSBData->posMin < mx) + ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, pSBData->pos - pSBData->posMin, mx - pSBData->posMin); else ThumbPos = Thumb + ThumbBox; } @@ -158,25 +210,25 @@ IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi return TRUE; } - +/* static VOID FASTCALL IntUpdateSBInfo(PWND Window, int wBar) { PSCROLLBARINFO sbi; - LPSCROLLINFO psi; + PSBDATA pSBData; ASSERT(Window); ASSERT(Window->pSBInfo); ASSERT(Window->pSBInfoex); sbi = IntGetScrollbarInfoFromWindow(Window, wBar); - psi = IntGetScrollInfoFromWindow(Window, wBar); + pSBData = IntGetSBData(Window, wBar); IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar)); - IntCalculateThumb(Window, wBar, sbi, psi); + IntCalculateThumb(Window, wBar, sbi, pSBData); } - +*/ static BOOL FASTCALL -co_IntGetScrollInfo(PWND Window, INT nBar, LPSCROLLINFO lpsi) +co_IntGetScrollInfo(PWND Window, INT nBar, PSBDATA pSBData, LPSCROLLINFO lpsi) { UINT Mask; LPSCROLLINFO psi; @@ -190,7 +242,11 @@ co_IntGetScrollInfo(PWND Window, INT nBar, LPSCROLLINFO lpsi) return FALSE; } - if (!Window->pSBInfo) return FALSE; + if (!Window->pSBInfo) + { + ERR("IntGetScrollInfo No window scrollbar info!\n"); + return FALSE; + } psi = IntGetScrollInfoFromWindow(Window, nBar); @@ -288,6 +344,8 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) PSCROLLBARINFO psbi; UINT new_flags; INT action = 0; + PSBDATA pSBData; + DWORD OldPos; BOOL bChangeParams = FALSE; /* Don't show/hide scrollbar if params don't change */ ASSERT_REFS_CO(Window); @@ -310,7 +368,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) EngSetLastError(ERROR_INVALID_PARAMETER); return 0; } - if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) + if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL | SIF_PREVIOUSPOS)) { EngSetLastError(ERROR_INVALID_PARAMETER); return 0; @@ -318,6 +376,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) psbi = IntGetScrollbarInfoFromWindow(Window, nBar); Info = IntGetScrollInfoFromWindow(Window, nBar); + pSBData = IntGetSBData(Window, nBar); /* Set the page size */ if (lpsi->fMask & SIF_PAGE) @@ -325,6 +384,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) if (Info->nPage != lpsi->nPage) { Info->nPage = lpsi->nPage; + pSBData->page = lpsi->nPage; bChangeParams = TRUE; } } @@ -334,7 +394,9 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) { if (Info->nPos != lpsi->nPos) { + OldPos = Info->nPos; Info->nPos = lpsi->nPos; + pSBData->pos = lpsi->nPos; bChangeParams = TRUE; } } @@ -348,32 +410,38 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) { Info->nMin = 0; Info->nMax = 0; + pSBData->posMin = 0; + pSBData->posMax = 0; bChangeParams = TRUE; } else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax) { Info->nMin = lpsi->nMin; Info->nMax = lpsi->nMax; + pSBData->posMin = lpsi->nMin; + pSBData->posMax = lpsi->nMax; bChangeParams = TRUE; } } /* Make sure the page size is valid */ if (Info->nPage < 0) - Info->nPage = 0; + { + pSBData->page = Info->nPage = 0; + } else if ((Info->nMax - Info->nMin + 1UL) < Info->nPage) { - Info->nPage = Info->nMax - Info->nMin + 1; + pSBData->page = Info->nPage = Info->nMax - Info->nMin + 1; } /* Make sure the pos is inside the range */ if (Info->nPos < Info->nMin) { - Info->nPos = Info->nMin; + pSBData->pos = Info->nPos = Info->nMin; } else if (Info->nPos > (Info->nMax - max((int)Info->nPage - 1, 0))) { - Info->nPos = Info->nMax - max(Info->nPage - 1, 0); + pSBData->pos = Info->nPos = Info->nMax - max(Info->nPage - 1, 0); } /* @@ -382,7 +450,8 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) */ if (!(lpsi->fMask & SIF_ALL)) { - goto done; //return Info->nPos; + //goto done; + return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; } /* Check if the scrollbar should be hidden or disabled */ @@ -419,7 +488,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) } } -done: +//done: if ( action & SA_SSI_HIDE ) { co_UserShowScrollBar(Window, nBar, FALSE, FALSE); @@ -428,7 +497,7 @@ done: { if ( action & SA_SSI_SHOW ) if ( co_UserShowScrollBar(Window, nBar, TRUE, TRUE) ) - return Info->nPos; /* SetWindowPos() already did the painting */ + return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; /* SetWindowPos() already did the painting */ if (bRedraw) { // FIXME: Arrows and interior. RECTL UpdateRect = psbi->rcScrollBar; @@ -438,7 +507,7 @@ done: UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top; co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); } // FIXME: Arrows - else if( action & SA_SSI_REPAINT_ARROWS ) +/* else if( action & SA_SSI_REPAINT_ARROWS ) { RECTL UpdateRect = psbi->rcScrollBar; UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left; @@ -447,9 +516,9 @@ done: UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top; co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); } - } +*/ } /* Return current position */ - return Info->nPos; + return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; } BOOL FASTCALL @@ -457,7 +526,7 @@ co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi) { INT Bar; PSCROLLBARINFO sbi; - LPSCROLLINFO psi; + PSBDATA pSBData; ASSERT_REFS_CO(Window); Bar = SBOBJ_TO_SBID(idObject); @@ -471,14 +540,15 @@ co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi) if(!co_IntCreateScrollBars(Window)) { + ERR("Failed to create scrollbars for window.\n"); return FALSE; } sbi = IntGetScrollbarInfoFromWindow(Window, Bar); - psi = IntGetScrollInfoFromWindow(Window, Bar); + pSBData = IntGetSBData(Window, Bar); IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar)); - IntCalculateThumb(Window, Bar, sbi, psi); + IntCalculateThumb(Window, Bar, sbi, pSBData); RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO)); @@ -489,7 +559,7 @@ BOOL FASTCALL co_IntCreateScrollBars(PWND Window) { PSCROLLBARINFO psbi; - LPSCROLLINFO psi; + PSBDATA pSBData; ULONG Size, s; INT i; @@ -532,12 +602,10 @@ co_IntCreateScrollBars(PWND Window) for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++) psbi->rgstate[i] = 0; - psi = IntGetScrollInfoFromWindow(Window, s); - psi->cbSize = sizeof(LPSCROLLINFO); - psi->nMax = 100; + pSBData = IntGetSBData(Window, s); IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar)); - IntCalculateThumb(Window, s, psbi, psi); + IntCalculateThumb(Window, s, psbi, pSBData); } return TRUE; @@ -607,7 +675,7 @@ co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV) { case SB_CTL: { - if (Wnd->pSBInfo) IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o! + //IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o! co_WinPosShowWindow(Wnd, fShowH ? SW_SHOW : SW_HIDE); return TRUE; @@ -627,20 +695,12 @@ co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV) return FALSE; } - - old_style = Wnd->style; - Wnd->style = (Wnd->style | set_bits) & ~clear_bits; - - if (fShowH || fShowV) - { - if (!Wnd->pSBInfo) co_IntCreateScrollBars(Wnd); - } - + old_style = IntSetStyle( Wnd, set_bits, clear_bits ); if ((old_style & clear_bits) != 0 || (old_style & set_bits) != set_bits) { ///// Is this needed? Was tested w/o! - if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ); - if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT); + //if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ); + //if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT); ///// /* Frame has been changed, let the window redraw itself */ co_WinPosSetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | @@ -650,6 +710,28 @@ co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV) return FALSE; } +LRESULT APIENTRY +ScrollBarWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT lResult = 0; + PWND pWnd; + pWnd = UserGetWindowObject(hWnd); + if (!pWnd) return 0; + + switch(Msg) + { + case WM_ENABLE: + { + if (pWnd->pSBInfo) + { + pWnd->pSBInfo->WSBflags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH; + } + } + break; + } + return lResult; +} + //// BOOL @@ -706,47 +788,53 @@ NtUserSBGetParms( PSBDATA pSBData, LPSCROLLINFO lpsi) { - NTSTATUS Status; PWND Window; SCROLLINFO psi; - DWORD sz; BOOL Ret; + SBDATA SBDataSafe; DECLARE_RETURN(BOOL); USER_REFERENCE_ENTRY Ref; TRACE("Enter NtUserGetScrollInfo\n"); - UserEnterExclusive(); + UserEnterShared(); - Status = MmCopyFromCaller(&psi.cbSize, &(lpsi->cbSize), sizeof(UINT)); - if(!NT_SUCCESS(Status) || - !((psi.cbSize == sizeof(SCROLLINFO)) || (psi.cbSize == sizeof(SCROLLINFO) - sizeof(psi.nTrackPos)))) + _SEH2_TRY { - SetLastNtError(Status); - RETURN(FALSE); + RtlCopyMemory(&psi, lpsi, sizeof(SCROLLINFO)); + if (pSBData) + { + RtlCopyMemory(&SBDataSafe, pSBData, sizeof(SBDATA)); + } } - sz = psi.cbSize; - Status = MmCopyFromCaller(&psi, lpsi, sz); - if (!NT_SUCCESS(Status)) + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - SetLastNtError(Status); - RETURN(FALSE); + ERR("NtUserGetScrollInfo Failed size.\n"); + SetLastNtError(_SEH2_GetExceptionCode()); + _SEH2_YIELD(RETURN(FALSE)); } + _SEH2_END if(!(Window = UserGetWindowObject(hWnd))) { + ERR("NtUserGetScrollInfo Bad window.\n"); RETURN(FALSE); } UserRefObjectCo(Window, &Ref); - Ret = co_IntGetScrollInfo(Window, fnBar, &psi); + Ret = co_IntGetScrollInfo(Window, fnBar, &SBDataSafe, &psi); UserDerefObjectCo(Window); - Status = MmCopyToCaller(lpsi, &psi, sz); - if(!NT_SUCCESS(Status)) + _SEH2_TRY { - SetLastNtError(Status); - RETURN( FALSE); + RtlCopyMemory(lpsi, &psi, sizeof(SCROLLINFO)); } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ERR("NtUserGetScrollInfo Failed copy to user.\n"); + SetLastNtError(_SEH2_GetExceptionCode()); + _SEH2_YIELD(RETURN(FALSE)); + } + _SEH2_END RETURN( Ret); @@ -773,7 +861,9 @@ NtUserEnableScrollBar( TRACE("Enter NtUserEnableScrollBar\n"); UserEnterExclusive(); - if (!(Window = UserGetWindowObject(hWnd))) + if (!(Window = UserGetWindowObject(hWnd)) || // FIXME: + Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN(FALSE); } @@ -827,6 +917,7 @@ NtUserEnableScrollBar( // Done in user32: // SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); + RETURN( Chg); if (OrigArrows == wArrows) RETURN( FALSE); RETURN( TRUE); @@ -856,7 +947,9 @@ NtUserSetScrollInfo( TRACE("Enter NtUserSetScrollInfo\n"); UserEnterExclusive(); - if(!(Window = UserGetWindowObject(hWnd))) + if(!(Window = UserGetWindowObject(hWnd)) || // FIXME: + Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP + Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN( 0); } diff --git a/reactos/win32ss/user/user32/controls/scrollbar.c b/reactos/win32ss/user/user32/controls/scrollbar.c index 9f4c19833d7..af8bd42f8a3 100644 --- a/reactos/win32ss/user/user32/controls/scrollbar.c +++ b/reactos/win32ss/user/user32/controls/scrollbar.c @@ -55,6 +55,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(scrollbar); /* Minimum size of the thumb in pixels */ #define SCROLL_MIN_THUMB 6 + /* Overlap between arrows and thumb */ +#define SCROLL_ARROW_THUMB_OVERLAP 0 + /* Thumb-tracking info */ static HWND ScrollTrackingWin = 0; static INT ScrollTrackingBar = 0; @@ -86,6 +89,32 @@ const struct builtin_class_descr SCROLL_builtin_class = /* PRIVATE FUNCTIONS **********************************************************/ +static PSBDATA +IntGetSBData(PWND pwnd, INT Bar) +{ + PSBWND pSBWnd; + PSBINFO pSBInfo; + + pSBInfo = DesktopPtrToUser(pwnd->pSBInfo); + switch (Bar) + { + case SB_HORZ: + return &pSBInfo->Horz; + case SB_VERT: + return &pSBInfo->Vert; + case SB_CTL: + if ( pwnd->cbwndExtra != (sizeof(SBWND)-sizeof(WND)) ) + { + ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n"); + return 0; + } + pSBWnd = (PSBWND)pwnd; + return (PSBDATA)&pSBWnd->SBCalc; + default: + ERR("IntGetSBData Bad Bar!\n"); + } + return NULL; +} static void IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, @@ -253,25 +282,16 @@ IntScrollDrawMovingThumb(HDC Dc, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical) INT OldTop; if (Vertical) - { MaxSize = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->rcScrollBar.top; - } else - { MaxSize = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->rcScrollBar.left; - } - MaxSize -= ScrollBarInfo->dxyLineButton + ScrollBarInfo->xyThumbBottom - - ScrollBarInfo->xyThumbTop; + MaxSize -= ScrollBarInfo->dxyLineButton + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; if (Pos < ScrollBarInfo->dxyLineButton) - { Pos = ScrollBarInfo->dxyLineButton; - } else if (MaxSize < Pos) - { Pos = MaxSize; - } OldTop = ScrollBarInfo->xyThumbTop; ScrollBarInfo->xyThumbBottom = Pos + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; @@ -280,21 +300,16 @@ IntScrollDrawMovingThumb(HDC Dc, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical) ScrollBarInfo->xyThumbBottom = OldTop + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; ScrollBarInfo->xyThumbTop = OldTop; - ScrollMovingThumb = ! ScrollMovingThumb; + ScrollMovingThumb = !ScrollMovingThumb; } static LONG FASTCALL IntScrollGetObjectId(INT SBType) { - if (SB_VERT == SBType) - { + if (SBType == SB_VERT) return OBJID_VSCROLL; - } - if (SB_HORZ == SBType) - { + if (SBType == SB_HORZ) return OBJID_HSCROLL; - } - return OBJID_CLIENT; } @@ -334,15 +349,15 @@ IntDrawScrollBar(HWND Wnd, HDC DC, INT Bar) default: return; } - if (! IntGetScrollBarInfo(Wnd, Bar, &Info)) - { + if (!IntGetScrollBarInfo(Wnd, Bar, &Info)) + { return; - } + } if (IsRectEmpty(&Info.rcScrollBar)) - { + { return; - } + } //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop; @@ -350,9 +365,9 @@ IntDrawScrollBar(HWND Wnd, HDC DC, INT Bar) * Draw the arrows. */ if (Info.dxyLineButton) - { + { IntDrawScrollArrows(DC, &Info, Vertical); - } + } /* * Draw the interior. @@ -363,34 +378,44 @@ IntDrawScrollBar(HWND Wnd, HDC DC, INT Bar) * If scroll bar has focus, reposition the caret. */ if (Wnd == GetFocus() && SB_CTL == Bar) - { + { if (Vertical) - { + { SetCaretPos(Info.rcScrollBar.top + 1, Info.dxyLineButton + 1); - } + } else - { + { SetCaretPos(Info.dxyLineButton + 1, Info.rcScrollBar.top + 1); - } - } + } + } } static BOOL FASTCALL IntScrollPtInRectEx(LPRECT Rect, POINT Pt, BOOL Vertical) { RECT TempRect = *Rect; - if (Vertical) - { - TempRect.left -= Rect->right - Rect->left; - TempRect.right += Rect->right - Rect->left; - } - else - { - TempRect.top -= Rect->bottom - Rect->top; - TempRect.bottom += Rect->bottom - Rect->top; - } + int scrollbarWidth; - return PtInRect(&TempRect, Pt); + /* Pad hit rect to allow mouse to be dragged outside of scrollbar and + * still be considered in the scrollbar. */ + if (Vertical) + { + scrollbarWidth = Rect->right - Rect->left; + TempRect.left -= scrollbarWidth*8; + TempRect.right += scrollbarWidth*8; + TempRect.top -= scrollbarWidth*2; + TempRect.bottom += scrollbarWidth*2; + } + else + { + scrollbarWidth = Rect->bottom - Rect->top; + TempRect.left -= scrollbarWidth*2; + TempRect.right += scrollbarWidth*2; + TempRect.top -= scrollbarWidth*8; + TempRect.bottom += scrollbarWidth*8; + } + + return PtInRect(&TempRect, Pt); } static DWORD FASTCALL @@ -399,63 +424,30 @@ IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo, BOOL Vertical, POINT Pt, BOOL Dra INT ArrowSize, ThumbSize, ThumbPos; if ((Dragging && ! IntScrollPtInRectEx(&ScrollBarInfo->rcScrollBar, Pt, Vertical)) || - ! PtInRect(&ScrollBarInfo->rcScrollBar, Pt)) - { - return SCROLL_NOWHERE; - } + ! PtInRect(&ScrollBarInfo->rcScrollBar, Pt)) return SCROLL_NOWHERE; ThumbPos = ScrollBarInfo->xyThumbTop; ThumbSize = ScrollBarInfo->xyThumbBottom - ThumbPos; ArrowSize = ScrollBarInfo->dxyLineButton; if (Vertical) - { - if (Pt.y < ScrollBarInfo->rcScrollBar.top + ArrowSize) - { - return SCROLL_TOP_ARROW; - } - if (ScrollBarInfo->rcScrollBar.bottom - ArrowSize <= Pt.y) - { - return SCROLL_BOTTOM_ARROW; - } - if (0 == ThumbPos) - { - return SCROLL_TOP_RECT; - } + { + if (Pt.y < ScrollBarInfo->rcScrollBar.top + ArrowSize) return SCROLL_TOP_ARROW; + if (Pt.y >= ScrollBarInfo->rcScrollBar.bottom - ArrowSize) return SCROLL_BOTTOM_ARROW; + if (!ThumbPos) return SCROLL_TOP_RECT; Pt.y -= ScrollBarInfo->rcScrollBar.top; - if (Pt.y < ThumbPos) - { - return SCROLL_TOP_RECT; - } - if (ThumbPos + ThumbSize <= Pt.y) - { - return SCROLL_BOTTOM_RECT; - } - } + if (Pt.y < ThumbPos) return SCROLL_TOP_RECT; + if (Pt.y >= ThumbPos + ThumbSize) return SCROLL_BOTTOM_RECT; + } else - { - if (Pt.x < ScrollBarInfo->rcScrollBar.left + ArrowSize) - { - return SCROLL_TOP_ARROW; - } - if (ScrollBarInfo->rcScrollBar.right - ArrowSize <= Pt.x) - { - return SCROLL_BOTTOM_ARROW; - } - if (0 == ThumbPos) - { - return SCROLL_TOP_RECT; - } + { + if (Pt.x < ScrollBarInfo->rcScrollBar.left + ArrowSize) return SCROLL_TOP_ARROW; + if (Pt.x >= ScrollBarInfo->rcScrollBar.right - ArrowSize) return SCROLL_BOTTOM_ARROW; + if (!ThumbPos) return SCROLL_TOP_RECT; Pt.x -= ScrollBarInfo->rcScrollBar.left; - if (Pt.x < ThumbPos) - { - return SCROLL_TOP_RECT; - } - if (ThumbPos + ThumbSize <= Pt.x) - { - return SCROLL_BOTTOM_RECT; - } - } + if (Pt.x < ThumbPos) return SCROLL_TOP_RECT; + if (Pt.x >= ThumbPos + ThumbSize) return SCROLL_BOTTOM_RECT; + } return SCROLL_THUMB; } @@ -479,145 +471,113 @@ IntScrollGetScrollBarRect(HWND Wnd, INT Bar, RECT *Rect, { INT Pixels; BOOL Vertical; - RECT ClientRect; - RECT WindowRect; - DWORD Style, ExStyle; PWND pWnd; PSBINFO pSBInfo; + PSBDATA pSBData; + PSBWND pSBWnd; pWnd = ValidateHwnd( Wnd ); + if (!pWnd) return FALSE; pSBInfo = DesktopPtrToUser(pWnd->pSBInfo); - GetClientRect(Wnd, &ClientRect); - if (SB_HORZ == Bar || SB_VERT == Bar) - { - ClientToScreen(Wnd, (LPPOINT) &ClientRect.left); - ClientToScreen(Wnd, (LPPOINT) &ClientRect.right); - GetWindowRect(Wnd, &WindowRect); - } - Style = GetWindowLongPtrW(Wnd, GWL_STYLE); + *Rect = pWnd->rcClient; + OffsetRect( Rect, -pWnd->rcWindow.left, -pWnd->rcWindow.top ); + if (pWnd->ExStyle & WS_EX_LAYOUTRTL) + mirror_rect( &pWnd->rcWindow, Rect ); switch (Bar) { case SB_HORZ: - Rect->left = ClientRect.left - WindowRect.left; - Rect->top = ClientRect.bottom - WindowRect.top; - Rect->right = ClientRect.right - WindowRect.left; - Rect->bottom = Rect->top + GetSystemMetrics(SM_CYHSCROLL); - if (0 != (Style & WS_BORDER)) - { +// WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect ); + Rect->top = Rect->bottom; + Rect->bottom += GetSystemMetrics(SM_CYHSCROLL); + if (pWnd->style & WS_BORDER) + { Rect->left--; Rect->right++; - } - else if (0 != (Style & WS_VSCROLL)) - { + } + else if (pWnd->style & WS_VSCROLL) + { Rect->right++; - } + } Vertical = FALSE; + pSBData = &pSBInfo->Horz; break; case SB_VERT: - ExStyle = GetWindowLongPtrW(Wnd, GWL_EXSTYLE); - if (0 != (ExStyle & WS_EX_LEFTSCROLLBAR)) - { - Rect->left = ClientRect.left - WindowRect.left - GetSystemMetrics(SM_CXVSCROLL); - } +// WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect ); + if (pWnd->ExStyle & WS_EX_LEFTSCROLLBAR) + { + Rect->right = Rect->left; + Rect->left -= GetSystemMetrics(SM_CXVSCROLL); + } else - { - Rect->left = ClientRect.right - WindowRect.left; - } - Rect->top = ClientRect.top - WindowRect.top; - Rect->right = Rect->left + GetSystemMetrics(SM_CXVSCROLL); - Rect->bottom = ClientRect.bottom - WindowRect.top; - if (0 != (Style & WS_BORDER)) - { + { + Rect->left = Rect->right; + Rect->right += GetSystemMetrics(SM_CXVSCROLL); + } + if (pWnd->style & WS_BORDER) + { Rect->top--; Rect->bottom++; - } - else if (0 != (Style & WS_HSCROLL)) - { + } + else if (pWnd->style & WS_HSCROLL) + { Rect->bottom++; - } + } Vertical = TRUE; + pSBData = &pSBInfo->Vert; break; case SB_CTL: - *Rect = ClientRect; - Vertical = (0 != (Style & SBS_VERT)); + GetClientRect( Wnd, Rect ); + Vertical = (pWnd->style & SBS_VERT); + pSBWnd = (PSBWND)pWnd; + pSBData = (PSBDATA)&pSBWnd->SBCalc; break; default: return FALSE; } - if (Vertical) - { - Pixels = Rect->bottom - Rect->top; - } - else - { - Pixels = Rect->right - Rect->left; - } + if (Vertical) Pixels = Rect->bottom - Rect->top; + else Pixels = Rect->right - Rect->left; if (Pixels <= 2 * GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT) - { + { if (SCROLL_MIN_RECT < Pixels) - { *ArrowSize = (Pixels - SCROLL_MIN_RECT) / 2; - } else - { *ArrowSize = 0; - } *ThumbPos = *ThumbSize = 0; - } + } else { - SCROLLINFO Info; - - NtUserSBGetParms(Wnd, Bar, NULL, &Info); *ArrowSize = GetSystemMetrics(SM_CXVSCROLL); - Pixels -= (2 * GetSystemMetrics(SM_CXVSCROLL)); - - if (0 != Info.nPage) + Pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)); + if (pSBData->page) { - *ThumbSize = MulDiv(Pixels, Info.nPage, (Info.nMax - Info.nMin + 1)); - if (*ThumbSize < SCROLL_MIN_THUMB) - { - *ThumbSize = SCROLL_MIN_THUMB; - } - } - else - { - *ThumbSize = GetSystemMetrics(SM_CXVSCROLL); + *ThumbSize = MulDiv(Pixels, pSBData->page, (pSBData->posMax - pSBData->posMin + 1)); + if (*ThumbSize < SCROLL_MIN_THUMB) *ThumbSize = SCROLL_MIN_THUMB; } + else *ThumbSize = GetSystemMetrics(SM_CXVSCROLL); -//#if 0 /* FIXME */ if (((Pixels -= *ThumbSize ) < 0) || (( pSBInfo->WSBflags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)) -//#else -// if ((Pixels -= *ThumbSize ) < 0) -//#endif { /* Rectangle too small or scrollbar disabled -> no thumb */ *ThumbPos = *ThumbSize = 0; } else { - INT Max = Info.nMax - max(Info.nPage - 1, 0); - if (Max <= Info.nMin) - { - *ThumbPos = *ArrowSize; - } + INT Max = pSBData->posMax - max(pSBData->page - 1, 0); + if (pSBData->posMin >= Max) + *ThumbPos = *ArrowSize - SCROLL_ARROW_THUMB_OVERLAP; else - { - *ThumbPos = *ArrowSize - + MulDiv(Pixels, (Info.nPos - Info.nMin), - (Max - Info.nMin)); - } + *ThumbPos = *ArrowSize - SCROLL_ARROW_THUMB_OVERLAP + + MulDiv(Pixels, (pSBData->pos - pSBData->posMin),(Max - pSBData->posMin)); } } - return Vertical; } @@ -631,70 +591,61 @@ static UINT FASTCALL IntScrollGetThumbVal(HWND Wnd, INT SBType, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical, INT Pos) { - SCROLLINFO si; + PWND pWnd; + PSBDATA pSBData; INT Pixels = Vertical ? ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->rcScrollBar.top : ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->rcScrollBar.left; - si.cbSize = sizeof(SCROLLINFO); - si.fMask = SIF_RANGE | SIF_PAGE; - NtUserSBGetParms(Wnd, SBType, NULL, &si); + pWnd = ValidateHwnd( Wnd ); + if (!pWnd) return FALSE; + + pSBData = IntGetSBData(pWnd, SBType); + if ((Pixels -= 2 * ScrollBarInfo->dxyLineButton) <= 0) - { - return si.nMin; - } + { + return pSBData->posMin; + } if ((Pixels -= (ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop)) <= 0) - { - return si.nMin; - } + { + return pSBData->posMin; + } Pos = Pos - ScrollBarInfo->dxyLineButton; if (Pos < 0) - { + { Pos = 0; - } - if (Pixels < Pos) - { - Pos = Pixels; - } + } + if (Pos > Pixels) Pos = Pixels; - if (0 == si.nPage) - { - Pos *= si.nMax - si.nMin; - } + if (!pSBData->page) + Pos *= pSBData->posMax - pSBData->posMin; else - { - Pos *= si.nMax - si.nMin - si.nPage + 1; - } - return si.nMin + ((Pos + Pixels / 2) / Pixels); + Pos *= pSBData->posMax - pSBData->posMin - pSBData->page + 1; + + return pSBData->posMin + ((Pos + Pixels / 2) / Pixels); } /*********************************************************************** * IntScrollClipPos */ -static POINT IntScrollClipPos(PRECT Rect, POINT Pt) +static POINT IntScrollClipPos(PRECT lpRect, POINT pt) { - if (Pt.x < Rect->left) - { - Pt.x = Rect->left; - } - else if (Rect->right < Pt.x) - { - Pt.x = Rect->right; - } + if( pt.x < lpRect->left ) + pt.x = lpRect->left; + else + if( pt.x > lpRect->right ) + pt.x = lpRect->right; - if (Pt.y < Rect->top) - { - Pt.y = Rect->top; - } - else if (Rect->bottom < Pt.y) - { - Pt.y = Rect->bottom; - } + if( pt.y < lpRect->top ) + pt.y = lpRect->top; + else + if( pt.y > lpRect->bottom ) + pt.y = lpRect->bottom; - return Pt; + return pt; } /*********************************************************************** @@ -895,9 +846,9 @@ IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt) ScrollBarInfo.rgstate[ScrollTrackHitTest] &= ~STATE_SYSTEM_PRESSED; NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest]; NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); - + IntDrawScrollArrows(Dc, &ScrollBarInfo, Vertical); - + break; case WM_SYSTIMER: @@ -1092,7 +1043,7 @@ static void IntScrollCreateScrollBar( TRACE("hwnd=%p lpCreate=%p\n", Wnd, lpCreate); -//#if 0 /* FIXME */ +#if 0 /* FIXME */ if (lpCreate->style & WS_DISABLED) { // info->flags = ESB_DISABLE_BOTH; @@ -1100,7 +1051,7 @@ static void IntScrollCreateScrollBar( NtUserMessageCall( Wnd, WM_ENABLE, FALSE, 0, 0, FNID_SCROLLBAR, FALSE); ERR("Created WS_DISABLED scrollbar\n"); } -//#endif +#endif if (0 != (lpCreate->style & (SBS_SIZEGRIP | SBS_SIZEBOX))) { if (0 != (lpCreate->style & SBS_SIZEBOXTOPLEFTALIGN)) @@ -1148,42 +1099,6 @@ static void IntScrollCreateScrollBar( } } -static INT FASTCALL -IntScrollGetScrollPos(HWND Wnd, INT Bar) -{ - SCROLLINFO ScrollInfo; - - ScrollInfo.cbSize = sizeof(SCROLLINFO); - ScrollInfo.fMask = SIF_POS; - if (!NtUserSBGetParms(Wnd, Bar, NULL, &ScrollInfo)) - { - return 0; - } - - return ScrollInfo.nPos; -} - -static BOOL FASTCALL -IntScrollGetScrollRange(HWND Wnd, int Bar, LPINT MinPos, LPINT MaxPos) -{ - BOOL Result; - SCROLLINFO ScrollInfo; - - if (NULL == MinPos || NULL == MaxPos) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - ScrollInfo.cbSize = sizeof(SCROLLINFO); - ScrollInfo.fMask = SIF_RANGE; - Result = NtUserSBGetParms(Wnd, Bar, NULL, &ScrollInfo); - *MinPos = Result ? ScrollInfo.nMin : 0; - *MaxPos = Result ? ScrollInfo.nMax : 0; - - return Result; -} - /* USER32 INTERNAL FUNCTIONS **************************************************/ /*********************************************************************** @@ -1199,13 +1114,13 @@ ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt) UINT XOffset = 0, YOffset = 0; if (SBType != SB_CTL) - { // Replace HAX for CMD mouse tracking. + { // Used with CMD mouse tracking. PWND pwnd = ValidateHwnd(Wnd); if (!pwnd) return; XOffset = pwnd->rcClient.left - pwnd->rcWindow.left; YOffset = pwnd->rcClient.top - pwnd->rcWindow.top; // RECT rect; -// GetClientRect(Wnd, &rect); +// WIN_GetRectangles( Wnd, COORDS_CLIENT, &rect, NULL ); ScreenToClient(Wnd, &Pt); // Pt.x -= rect.left; // Pt.y -= rect.top; @@ -1241,6 +1156,15 @@ ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt) } +static DWORD FASTCALL +IntSetScrollInfo(HWND Wnd, LPCSCROLLINFO Info, BOOL bRedraw) +{ + DWORD Ret = NtUserSetScrollInfo(Wnd, SB_CTL, Info, bRedraw); + if (Ret) IntNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, Wnd, OBJID_CLIENT, CHILDID_SELF, WEF_SETBYWNDPTI); + return Ret; +} + + /*********************************************************************** * ScrollBarWndProc */ @@ -1249,12 +1173,21 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam { #ifdef __REACTOS__ // Do this now, remove after Server side is fixed. PWND pWnd; + PSBWND pSBWnd; + SCROLLINFO ScrollInfo; pWnd = ValidateHwnd(Wnd); if (pWnd) { if (!pWnd->fnid) { + ERR("ScrollBar CTL size %d\n",(sizeof(SBWND)-sizeof(WND))); + if ( pWnd->cbwndExtra != (sizeof(SBWND)-sizeof(WND)) ) + { + ERR("Wrong Extra bytes for Scrollbar!\n"); + return 0; + } + if (Msg != WM_CREATE) { return DefWindowProc(Wnd, Msg, wParam, lParam); @@ -1277,6 +1210,9 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam return 0; } + // Must be a scroll bar control! + pSBWnd = (PSBWND)pWnd; + switch (Msg) { case WM_CREATE: @@ -1285,17 +1221,8 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam case WM_ENABLE: { - PWND pWnd = ValidateHwnd(Wnd); - if (pWnd->pSBInfo) - { - ERR("ScrollBarWndProc WM_ENABLE\n"); - //NtUserEnableScrollBar(Wnd,SB_CTL,(wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH)); - NtUserMessageCall( Wnd, Msg, wParam, lParam, 0, FNID_SCROLLBAR, !unicode); - /* Refresh Scrollbars. */ - SCROLL_RefreshScrollBar(Wnd, SB_CTL, TRUE, TRUE); - } - } - return 0; + return SendMessageW( Wnd, SBM_ENABLE_ARROWS, wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH, 0); + } case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: @@ -1408,35 +1335,49 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam } break; - case SBM_SETPOS: - return SetScrollPos(Wnd, SB_CTL, wParam, (BOOL) lParam); - case SBM_GETPOS: - return IntScrollGetScrollPos(Wnd, SB_CTL); - - case SBM_SETRANGEREDRAW: - case SBM_SETRANGE: - { - INT OldPos = IntScrollGetScrollPos(Wnd, SB_CTL); - SetScrollRange(Wnd, SB_CTL, wParam, lParam, FALSE); - if (Msg == SBM_SETRANGEREDRAW) - SCROLL_RefreshScrollBar( Wnd, SB_CTL, TRUE, TRUE ); - if (OldPos != IntScrollGetScrollPos(Wnd, SB_CTL)) return OldPos; - } - return 0; + return pSBWnd->SBCalc.pos; case SBM_GETRANGE: - return IntScrollGetScrollRange(Wnd, SB_CTL, (LPINT) wParam, (LPINT) lParam); + *(LPINT)wParam = pSBWnd->SBCalc.posMin; + *(LPINT)lParam = pSBWnd->SBCalc.posMax; + // This message does not return a value. + return 0; case SBM_ENABLE_ARROWS: return EnableScrollBar( Wnd, SB_CTL, wParam ); + case SBM_SETPOS: + { + ScrollInfo.cbSize = sizeof(SCROLLINFO); + ScrollInfo.fMask = SIF_POS|SIF_PREVIOUSPOS; + ScrollInfo.nPos = wParam; + return IntSetScrollInfo(Wnd, &ScrollInfo, lParam); + } + + case SBM_SETRANGEREDRAW: + case SBM_SETRANGE: + { + ScrollInfo.cbSize = sizeof(SCROLLINFO); + ScrollInfo.fMask = SIF_RANGE|SIF_PREVIOUSPOS; + ScrollInfo.nMin = wParam; + ScrollInfo.nMax = lParam; + return IntSetScrollInfo(Wnd, &ScrollInfo, Msg == SBM_SETRANGEREDRAW ? TRUE : FALSE); + } + case SBM_SETSCROLLINFO: - return NtUserSetScrollInfo(Wnd, SB_CTL, (SCROLLINFO *) lParam, wParam); + return IntSetScrollInfo(Wnd, (LPCSCROLLINFO)lParam, wParam); case SBM_GETSCROLLINFO: - return NtUserSBGetParms(Wnd, SB_CTL, NULL, (SCROLLINFO *) lParam); - + { + PSBDATA pSBData = (PSBDATA)&pSBWnd->SBCalc; + DWORD ret = NtUserSBGetParms(Wnd, SB_CTL, pSBData, (SCROLLINFO *) lParam); + if (!ret) + { + ERR("SBM_GETSCROLLINFO No ScrollInfo\n"); + } + return ret; + } case SBM_GETSCROLLBARINFO: ((PSCROLLBARINFO)lParam)->cbSize = sizeof(SCROLLBARINFO); return NtUserGetScrollBarInfo(Wnd, OBJID_CLIENT, (PSCROLLBARINFO)lParam); @@ -1496,8 +1437,7 @@ BOOL WINAPI EnableScrollBar( HWND hwnd, UINT nBar, UINT flags ) if (!Hook) { Ret = NtUserEnableScrollBar(hwnd, nBar, flags); - if (GetLastError() == ERROR_INVALID_PARAMETER) return Ret; - if (nBar == SB_CTL) return Ret; + if (!Ret) return Ret; SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); return Ret; } @@ -1519,7 +1459,7 @@ BOOL WINAPI RealGetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info) { PWND pWnd; - PSBDATA pSBData = NULL; + PSBDATA pSBData; if (SB_CTL == SBType) { @@ -1534,7 +1474,12 @@ RealGetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info) SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - // FIXME add support to set pSBData from pWnd->pSBInfo + if (!pWnd->pSBInfo) + { + SetLastError(ERROR_NO_SCROLLBARS); + return FALSE; + } + pSBData = IntGetSBData(pWnd, SBType); return NtUserSBGetParms(Wnd, SBType, pSBData, Info); } @@ -1573,17 +1518,33 @@ GetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info) INT WINAPI GetScrollPos(HWND Wnd, INT Bar) { + PWND pwnd; + PSBDATA pSBData; + TRACE("Wnd=%p Bar=%d\n", Wnd, Bar); /* Refer SB_CTL requests to the window */ if (SB_CTL == Bar) - { + { return SendMessageW(Wnd, SBM_GETPOS, (WPARAM) 0, (LPARAM) 0); - } - else - { - return IntScrollGetScrollPos(Wnd, Bar); - } + } + else if (Bar == SB_HORZ || Bar == SB_VERT ) + { + pwnd = ValidateHwnd(Wnd); + if (!pwnd) return 0; + + if (pwnd->pSBInfo) + { + pSBData = IntGetSBData(pwnd, Bar); + return pSBData->pos; + } + + SetLastError(ERROR_NO_SCROLLBARS); + ERR("GetScrollPos No Scroll Info\n"); + return 0; + } + SetLastError(ERROR_INVALID_PARAMETER); + return 0; } /* @@ -1592,17 +1553,37 @@ GetScrollPos(HWND Wnd, INT Bar) BOOL WINAPI GetScrollRange(HWND Wnd, int Bar, LPINT MinPos, LPINT MaxPos) { + PWND pwnd; + PSBDATA pSBData; + TRACE("Wnd=%x Bar=%d Min=%p Max=%p\n", Wnd, Bar, MinPos, MaxPos); /* Refer SB_CTL requests to the window */ if (SB_CTL == Bar) - { + { return SendMessageW(Wnd, SBM_GETRANGE, (WPARAM) MinPos, (LPARAM) MaxPos); - } - else - { - return IntScrollGetScrollRange(Wnd, Bar, MinPos, MaxPos); - } + } + else if (Bar == SB_HORZ || Bar == SB_VERT ) + { + pwnd = ValidateHwnd(Wnd); + if (!pwnd) return FALSE; + + if (pwnd->pSBInfo) + { + pSBData = IntGetSBData(pwnd, Bar); + *MinPos = pSBData->posMin; + *MaxPos = pSBData->posMax; + } + else + { + SetLastError(ERROR_NO_SCROLLBARS); + *MinPos = 0; + *MaxPos = 0; + } + return TRUE; + } + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } INT WINAPI @@ -1655,32 +1636,13 @@ SetScrollInfo(HWND Wnd, int SBType, LPCSCROLLINFO Info, BOOL bRedraw) INT WINAPI SetScrollPos(HWND hWnd, INT nBar, INT nPos, BOOL bRedraw) { - PWND pWnd; - INT Result = 0; SCROLLINFO ScrollInfo; - pWnd = ValidateHwnd(hWnd); - if ( !pWnd || !pWnd->pSBInfo ) return 0; - ScrollInfo.cbSize = sizeof(SCROLLINFO); - ScrollInfo.fMask = SIF_POS; + ScrollInfo.fMask = SIF_POS|SIF_PREVIOUSPOS; + ScrollInfo.nPos = nPos; - /* - * Call NtUserSBGetParms() to get the previous position that - * we will later return. - */ - if (NtUserSBGetParms(hWnd, nBar, NULL, &ScrollInfo)) - { - Result = ScrollInfo.nPos; - if (Result != nPos) - { - ScrollInfo.nPos = nPos; - /* Finally set the new position */ - NtUserSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); - } - } - - return Result; + return RealSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); } /* @@ -1706,6 +1668,5 @@ SetScrollRange(HWND hWnd, INT nBar, INT nMinPos, INT nMaxPos, BOOL bRedraw) ScrollInfo.nMin = nMinPos; ScrollInfo.nMax = nMaxPos; SetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); // do not bypass themes. - return TRUE; }