[Win32SS]

- Fixed skip test regression in User32 Win wine test.
- Regressed one scroll control test. AbiWord scrolls and Explorer redraw issue still
the same.
- WIP: Rearranged code for standard structures prior to moving scroll code to Win32k. Proc support will remain in User32 (A2W etc) and redirected to Win32k. Drawing support will be added when this switch is made. Then ReactOS will have 100 percent wine scrolls plus our fixes in one file.

svn path=/trunk/; revision=57091
This commit is contained in:
James Tabor 2012-08-18 00:59:35 +00:00
parent 4107cfe3f6
commit 3f6031fbbf
4 changed files with 478 additions and 420 deletions

View file

@ -68,6 +68,9 @@
#define SWP_NOCLIENTMOVE 0x1000 #define SWP_NOCLIENTMOVE 0x1000
#define SWP_STATECHANGED 0x8000 #define SWP_STATECHANGED 0x8000
/* NtUserSetScrollInfo mask to return original position before it is change */
#define SIF_PREVIOUSPOS 4096
/* Non SDK Queue state flags. */ /* Non SDK Queue state flags. */
#define QS_SMRESULT 0x8000 /* see "Undoc. Windows" */ #define QS_SMRESULT 0x8000 /* see "Undoc. Windows" */

View file

@ -608,7 +608,7 @@ static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPAR
pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND pWnd == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
return 0; return 0;
TRACE("Internal Event Msg %p\n",msg); TRACE("Internal Event Msg %p hWnd 0x%x\n",msg,pWnd->head.h);
switch(msg) switch(msg)
{ {
@ -742,7 +742,6 @@ co_IntPeekMessage( PMSG Msg,
BOOL bGMSG ) BOOL bGMSG )
{ {
PTHREADINFO pti; PTHREADINFO pti;
//PCLIENTINFO pci;
LARGE_INTEGER LargeTickCount; LARGE_INTEGER LargeTickCount;
PUSER_MESSAGE_QUEUE ThreadQueue; PUSER_MESSAGE_QUEUE ThreadQueue;
BOOL RemoveMessages; BOOL RemoveMessages;
@ -751,11 +750,15 @@ co_IntPeekMessage( PMSG Msg,
pti = PsGetCurrentThreadWin32Thread(); pti = PsGetCurrentThreadWin32Thread();
ThreadQueue = pti->MessageQueue; ThreadQueue = pti->MessageQueue;
//pci = pti->pClientInfo;
RemoveMessages = RemoveMsg & PM_REMOVE; RemoveMessages = RemoveMsg & PM_REMOVE;
ProcessMask = HIWORD(RemoveMsg); 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 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
all available messages (that is, no range filtering is performed)". */ all available messages (that is, no range filtering is performed)". */
if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT); if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT);
@ -1182,6 +1185,7 @@ UserPostMessage( HWND Wnd,
Window = UserGetWindowObject(Wnd); Window = UserGetWindowObject(Wnd);
if ( !Window ) if ( !Window )
{ {
ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd);
return FALSE; return FALSE;
} }
@ -1246,6 +1250,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
if (!(Window = UserGetWindowObject(hWnd))) if (!(Window = UserGetWindowObject(hWnd)))
{ {
TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd);
RETURN( FALSE); RETURN( FALSE);
} }
@ -1491,6 +1496,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
if (!(Window = UserGetWindowObject(hWnd))) if (!(Window = UserGetWindowObject(hWnd)))
{ {
TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd);
RETURN(FALSE); RETURN(FALSE);
} }
@ -1514,6 +1520,8 @@ co_IntSendMessageWithCallBack( HWND hWnd,
if (Msg & 0x80000000 && if (Msg & 0x80000000 &&
Window->head.pti->MessageQueue == Win32Thread->MessageQueue) Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
{ {
if (Win32Thread->TIF_flags & TIF_INCLEANUP) RETURN( FALSE);
ERR("SMWCB: Internal Message!\n"); ERR("SMWCB: Internal Message!\n");
Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam ); Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam );
if (uResult) *uResult = Result; if (uResult) *uResult = Result;
@ -1650,6 +1658,7 @@ co_IntPostOrSendMessage( HWND hWnd,
if(!(Window = UserGetWindowObject(hWnd))) if(!(Window = UserGetWindowObject(hWnd)))
{ {
TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd);
return 0; return 0;
} }
@ -2158,6 +2167,8 @@ NtUserTranslateMessage(LPMSG lpMsg, UINT flags)
return Ret; return Ret;
} }
LRESULT APIENTRY ScrollBarWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam);
BOOL APIENTRY BOOL APIENTRY
NtUserMessageCall( HWND hWnd, NtUserMessageCall( HWND hWnd,
UINT Msg, UINT Msg,
@ -2178,18 +2189,7 @@ NtUserMessageCall( HWND hWnd,
{ {
case FNID_SCROLLBAR: case FNID_SCROLLBAR:
{ {
switch(Msg) lResult = ScrollBarWndProc(hWnd, Msg, wParam, lParam);
{
case WM_ENABLE:
{
Window = UserGetWindowObject(hWnd);
if (Window->pSBInfo)
{
Window->pSBInfo->WSBflags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
}
}
break;
}
break; break;
} }
case FNID_DEFWINDOWPROC: case FNID_DEFWINDOWPROC:
@ -2675,6 +2675,7 @@ NtUserMessageCall( HWND hWnd,
case FNID_DEFWINDOWPROC: case FNID_DEFWINDOWPROC:
case FNID_CALLWNDPROC: case FNID_CALLWNDPROC:
case FNID_CALLWNDPROCRET: case FNID_CALLWNDPROCRET:
case FNID_SCROLLBAR:
if (ResultInfo) if (ResultInfo)
{ {
_SEH2_TRY _SEH2_TRY

View file

@ -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 * '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. * 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 BOOL FASTCALL
IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect) IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect)
{ {
BOOL vertical; BOOL vertical;
RECTL ClientRect = Wnd->rcClient; *lprect = Wnd->rcClient;
RECTL WindowRect = Wnd->rcWindow;
RECTL_vOffsetRect( lprect, -Wnd->rcWindow.left, -Wnd->rcWindow.top );
if (Wnd->ExStyle & WS_EX_LAYOUTRTL)
mirror_rect( &Wnd->rcWindow, lprect );
switch (nBar) switch (nBar)
{ {
case SB_HORZ: case SB_HORZ:
lprect->left = ClientRect.left - WindowRect.left; lprect->top = lprect->bottom;
lprect->top = ClientRect.bottom - WindowRect.top; lprect->bottom += UserGetSystemMetrics (SM_CYHSCROLL);
lprect->right = ClientRect.right - WindowRect.left; if (Wnd->style & WS_BORDER)
lprect->bottom = lprect->top + UserGetSystemMetrics (SM_CYHSCROLL); {
lprect->left--;
lprect->right++;
}
else if (Wnd->style & WS_VSCROLL)
{
lprect->right++;
}
vertical = FALSE; vertical = FALSE;
break; break;
case SB_VERT: case SB_VERT:
if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR) if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR)
{ {
lprect->right = ClientRect.left - WindowRect.left; lprect->right = lprect->right;;
lprect->left = lprect->right - UserGetSystemMetrics(SM_CXVSCROLL); lprect->left -= UserGetSystemMetrics(SM_CXVSCROLL);
} }
else else
{ {
lprect->left = ClientRect.right - WindowRect.left; lprect->left = lprect->right;
lprect->right = lprect->left + UserGetSystemMetrics(SM_CXVSCROLL); 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; vertical = TRUE;
break; break;
case SB_CTL: case SB_CTL:
IntGetClientRect (Wnd, lprect); IntGetClientRect (Wnd, lprect);
vertical = ((Wnd->style & SBS_VERT) != 0); vertical = !!(Wnd->style & SBS_VERT);
break; break;
default: default:
@ -84,7 +136,7 @@ IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect)
} }
BOOL FASTCALL 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; INT Thumb, ThumbBox, ThumbPos, cxy, mx;
RECTL ClientRect; RECTL ClientRect;
@ -127,20 +179,20 @@ IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi
} }
else else
{ {
ThumbBox = psi->nPage ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB); ThumbBox = pSBData->page ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB);
cxy -= (2 * Thumb); cxy -= (2 * Thumb);
if(cxy >= ThumbBox) 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) if(cxy > ThumbBox)
{ {
mx = psi->nMax - max(psi->nPage - 1, 0); mx = pSBData->posMax - max(pSBData->page - 1, 0);
if(psi->nMin < mx) if(pSBData->posMin < mx)
ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, psi->nPos - psi->nMin, mx - psi->nMin); ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, pSBData->pos - pSBData->posMin, mx - pSBData->posMin);
else else
ThumbPos = Thumb + ThumbBox; ThumbPos = Thumb + ThumbBox;
} }
@ -158,25 +210,25 @@ IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi
return TRUE; return TRUE;
} }
/*
static VOID FASTCALL static VOID FASTCALL
IntUpdateSBInfo(PWND Window, int wBar) IntUpdateSBInfo(PWND Window, int wBar)
{ {
PSCROLLBARINFO sbi; PSCROLLBARINFO sbi;
LPSCROLLINFO psi; PSBDATA pSBData;
ASSERT(Window); ASSERT(Window);
ASSERT(Window->pSBInfo); ASSERT(Window->pSBInfo);
ASSERT(Window->pSBInfoex); ASSERT(Window->pSBInfoex);
sbi = IntGetScrollbarInfoFromWindow(Window, wBar); sbi = IntGetScrollbarInfoFromWindow(Window, wBar);
psi = IntGetScrollInfoFromWindow(Window, wBar); pSBData = IntGetSBData(Window, wBar);
IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar)); IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar));
IntCalculateThumb(Window, wBar, sbi, psi); IntCalculateThumb(Window, wBar, sbi, pSBData);
} }
*/
static BOOL FASTCALL static BOOL FASTCALL
co_IntGetScrollInfo(PWND Window, INT nBar, LPSCROLLINFO lpsi) co_IntGetScrollInfo(PWND Window, INT nBar, PSBDATA pSBData, LPSCROLLINFO lpsi)
{ {
UINT Mask; UINT Mask;
LPSCROLLINFO psi; LPSCROLLINFO psi;
@ -190,7 +242,11 @@ co_IntGetScrollInfo(PWND Window, INT nBar, LPSCROLLINFO lpsi)
return FALSE; return FALSE;
} }
if (!Window->pSBInfo) return FALSE; if (!Window->pSBInfo)
{
ERR("IntGetScrollInfo No window scrollbar info!\n");
return FALSE;
}
psi = IntGetScrollInfoFromWindow(Window, nBar); psi = IntGetScrollInfoFromWindow(Window, nBar);
@ -288,6 +344,8 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
PSCROLLBARINFO psbi; PSCROLLBARINFO psbi;
UINT new_flags; UINT new_flags;
INT action = 0; INT action = 0;
PSBDATA pSBData;
DWORD OldPos;
BOOL bChangeParams = FALSE; /* Don't show/hide scrollbar if params don't change */ BOOL bChangeParams = FALSE; /* Don't show/hide scrollbar if params don't change */
ASSERT_REFS_CO(Window); ASSERT_REFS_CO(Window);
@ -310,7 +368,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
EngSetLastError(ERROR_INVALID_PARAMETER); EngSetLastError(ERROR_INVALID_PARAMETER);
return 0; return 0;
} }
if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL | SIF_PREVIOUSPOS))
{ {
EngSetLastError(ERROR_INVALID_PARAMETER); EngSetLastError(ERROR_INVALID_PARAMETER);
return 0; return 0;
@ -318,6 +376,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
psbi = IntGetScrollbarInfoFromWindow(Window, nBar); psbi = IntGetScrollbarInfoFromWindow(Window, nBar);
Info = IntGetScrollInfoFromWindow(Window, nBar); Info = IntGetScrollInfoFromWindow(Window, nBar);
pSBData = IntGetSBData(Window, nBar);
/* Set the page size */ /* Set the page size */
if (lpsi->fMask & SIF_PAGE) if (lpsi->fMask & SIF_PAGE)
@ -325,6 +384,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
if (Info->nPage != lpsi->nPage) if (Info->nPage != lpsi->nPage)
{ {
Info->nPage = lpsi->nPage; Info->nPage = lpsi->nPage;
pSBData->page = lpsi->nPage;
bChangeParams = TRUE; bChangeParams = TRUE;
} }
} }
@ -334,7 +394,9 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
{ {
if (Info->nPos != lpsi->nPos) if (Info->nPos != lpsi->nPos)
{ {
OldPos = Info->nPos;
Info->nPos = lpsi->nPos; Info->nPos = lpsi->nPos;
pSBData->pos = lpsi->nPos;
bChangeParams = TRUE; bChangeParams = TRUE;
} }
} }
@ -348,32 +410,38 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
{ {
Info->nMin = 0; Info->nMin = 0;
Info->nMax = 0; Info->nMax = 0;
pSBData->posMin = 0;
pSBData->posMax = 0;
bChangeParams = TRUE; bChangeParams = TRUE;
} }
else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax) else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax)
{ {
Info->nMin = lpsi->nMin; Info->nMin = lpsi->nMin;
Info->nMax = lpsi->nMax; Info->nMax = lpsi->nMax;
pSBData->posMin = lpsi->nMin;
pSBData->posMax = lpsi->nMax;
bChangeParams = TRUE; bChangeParams = TRUE;
} }
} }
/* Make sure the page size is valid */ /* Make sure the page size is valid */
if (Info->nPage < 0) if (Info->nPage < 0)
Info->nPage = 0; {
pSBData->page = Info->nPage = 0;
}
else if ((Info->nMax - Info->nMin + 1UL) < Info->nPage) 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 */ /* Make sure the pos is inside the range */
if (Info->nPos < Info->nMin) 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))) 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)) 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 */ /* 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 ) if ( action & SA_SSI_HIDE )
{ {
co_UserShowScrollBar(Window, nBar, FALSE, FALSE); co_UserShowScrollBar(Window, nBar, FALSE, FALSE);
@ -428,7 +497,7 @@ done:
{ {
if ( action & SA_SSI_SHOW ) if ( action & SA_SSI_SHOW )
if ( co_UserShowScrollBar(Window, nBar, TRUE, TRUE) ) 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) if (bRedraw)
{ // FIXME: Arrows and interior. { // FIXME: Arrows and interior.
RECTL UpdateRect = psbi->rcScrollBar; RECTL UpdateRect = psbi->rcScrollBar;
@ -438,7 +507,7 @@ done:
UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top; UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
} // FIXME: Arrows } // FIXME: Arrows
else if( action & SA_SSI_REPAINT_ARROWS ) /* else if( action & SA_SSI_REPAINT_ARROWS )
{ {
RECTL UpdateRect = psbi->rcScrollBar; RECTL UpdateRect = psbi->rcScrollBar;
UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left; UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left;
@ -447,9 +516,9 @@ done:
UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top; UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
} }
} */ }
/* Return current position */ /* Return current position */
return Info->nPos; return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos;
} }
BOOL FASTCALL BOOL FASTCALL
@ -457,7 +526,7 @@ co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi)
{ {
INT Bar; INT Bar;
PSCROLLBARINFO sbi; PSCROLLBARINFO sbi;
LPSCROLLINFO psi; PSBDATA pSBData;
ASSERT_REFS_CO(Window); ASSERT_REFS_CO(Window);
Bar = SBOBJ_TO_SBID(idObject); Bar = SBOBJ_TO_SBID(idObject);
@ -471,14 +540,15 @@ co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi)
if(!co_IntCreateScrollBars(Window)) if(!co_IntCreateScrollBars(Window))
{ {
ERR("Failed to create scrollbars for window.\n");
return FALSE; return FALSE;
} }
sbi = IntGetScrollbarInfoFromWindow(Window, Bar); sbi = IntGetScrollbarInfoFromWindow(Window, Bar);
psi = IntGetScrollInfoFromWindow(Window, Bar); pSBData = IntGetSBData(Window, Bar);
IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar)); IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar));
IntCalculateThumb(Window, Bar, sbi, psi); IntCalculateThumb(Window, Bar, sbi, pSBData);
RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO)); RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO));
@ -489,7 +559,7 @@ BOOL FASTCALL
co_IntCreateScrollBars(PWND Window) co_IntCreateScrollBars(PWND Window)
{ {
PSCROLLBARINFO psbi; PSCROLLBARINFO psbi;
LPSCROLLINFO psi; PSBDATA pSBData;
ULONG Size, s; ULONG Size, s;
INT i; INT i;
@ -532,12 +602,10 @@ co_IntCreateScrollBars(PWND Window)
for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++) for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++)
psbi->rgstate[i] = 0; psbi->rgstate[i] = 0;
psi = IntGetScrollInfoFromWindow(Window, s); pSBData = IntGetSBData(Window, s);
psi->cbSize = sizeof(LPSCROLLINFO);
psi->nMax = 100;
IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar)); IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar));
IntCalculateThumb(Window, s, psbi, psi); IntCalculateThumb(Window, s, psbi, pSBData);
} }
return TRUE; return TRUE;
@ -607,7 +675,7 @@ co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV)
{ {
case SB_CTL: 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); co_WinPosShowWindow(Wnd, fShowH ? SW_SHOW : SW_HIDE);
return TRUE; return TRUE;
@ -627,20 +695,12 @@ co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV)
return FALSE; return FALSE;
} }
old_style = IntSetStyle( Wnd, set_bits, clear_bits );
old_style = Wnd->style;
Wnd->style = (Wnd->style | set_bits) & ~clear_bits;
if (fShowH || fShowV)
{
if (!Wnd->pSBInfo) co_IntCreateScrollBars(Wnd);
}
if ((old_style & clear_bits) != 0 || (old_style & set_bits) != set_bits) if ((old_style & clear_bits) != 0 || (old_style & set_bits) != set_bits)
{ {
///// Is this needed? Was tested w/o! ///// Is this needed? Was tested w/o!
if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ); //if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ);
if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT); //if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT);
///// /////
/* Frame has been changed, let the window redraw itself */ /* Frame has been changed, let the window redraw itself */
co_WinPosSetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | 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; 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 BOOL
@ -706,47 +788,53 @@ NtUserSBGetParms(
PSBDATA pSBData, PSBDATA pSBData,
LPSCROLLINFO lpsi) LPSCROLLINFO lpsi)
{ {
NTSTATUS Status;
PWND Window; PWND Window;
SCROLLINFO psi; SCROLLINFO psi;
DWORD sz;
BOOL Ret; BOOL Ret;
SBDATA SBDataSafe;
DECLARE_RETURN(BOOL); DECLARE_RETURN(BOOL);
USER_REFERENCE_ENTRY Ref; USER_REFERENCE_ENTRY Ref;
TRACE("Enter NtUserGetScrollInfo\n"); TRACE("Enter NtUserGetScrollInfo\n");
UserEnterExclusive(); UserEnterShared();
Status = MmCopyFromCaller(&psi.cbSize, &(lpsi->cbSize), sizeof(UINT)); _SEH2_TRY
if(!NT_SUCCESS(Status) ||
!((psi.cbSize == sizeof(SCROLLINFO)) || (psi.cbSize == sizeof(SCROLLINFO) - sizeof(psi.nTrackPos))))
{ {
SetLastNtError(Status); RtlCopyMemory(&psi, lpsi, sizeof(SCROLLINFO));
RETURN(FALSE); if (pSBData)
}
sz = psi.cbSize;
Status = MmCopyFromCaller(&psi, lpsi, sz);
if (!NT_SUCCESS(Status))
{ {
SetLastNtError(Status); RtlCopyMemory(&SBDataSafe, pSBData, sizeof(SBDATA));
RETURN(FALSE);
} }
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ERR("NtUserGetScrollInfo Failed size.\n");
SetLastNtError(_SEH2_GetExceptionCode());
_SEH2_YIELD(RETURN(FALSE));
}
_SEH2_END
if(!(Window = UserGetWindowObject(hWnd))) if(!(Window = UserGetWindowObject(hWnd)))
{ {
ERR("NtUserGetScrollInfo Bad window.\n");
RETURN(FALSE); RETURN(FALSE);
} }
UserRefObjectCo(Window, &Ref); UserRefObjectCo(Window, &Ref);
Ret = co_IntGetScrollInfo(Window, fnBar, &psi); Ret = co_IntGetScrollInfo(Window, fnBar, &SBDataSafe, &psi);
UserDerefObjectCo(Window); UserDerefObjectCo(Window);
Status = MmCopyToCaller(lpsi, &psi, sz); _SEH2_TRY
if(!NT_SUCCESS(Status))
{ {
SetLastNtError(Status); RtlCopyMemory(lpsi, &psi, sizeof(SCROLLINFO));
RETURN( FALSE);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ERR("NtUserGetScrollInfo Failed copy to user.\n");
SetLastNtError(_SEH2_GetExceptionCode());
_SEH2_YIELD(RETURN(FALSE));
}
_SEH2_END
RETURN( Ret); RETURN( Ret);
@ -773,7 +861,9 @@ NtUserEnableScrollBar(
TRACE("Enter NtUserEnableScrollBar\n"); TRACE("Enter NtUserEnableScrollBar\n");
UserEnterExclusive(); UserEnterExclusive();
if (!(Window = UserGetWindowObject(hWnd))) if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
RETURN(FALSE); RETURN(FALSE);
} }
@ -827,6 +917,7 @@ NtUserEnableScrollBar(
// Done in user32: // Done in user32:
// SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); // SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
RETURN( Chg);
if (OrigArrows == wArrows) RETURN( FALSE); if (OrigArrows == wArrows) RETURN( FALSE);
RETURN( TRUE); RETURN( TRUE);
@ -856,7 +947,9 @@ NtUserSetScrollInfo(
TRACE("Enter NtUserSetScrollInfo\n"); TRACE("Enter NtUserSetScrollInfo\n");
UserEnterExclusive(); UserEnterExclusive();
if(!(Window = UserGetWindowObject(hWnd))) if(!(Window = UserGetWindowObject(hWnd)) || // FIXME:
Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
{ {
RETURN( 0); RETURN( 0);
} }

View file

@ -55,6 +55,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(scrollbar);
/* Minimum size of the thumb in pixels */ /* Minimum size of the thumb in pixels */
#define SCROLL_MIN_THUMB 6 #define SCROLL_MIN_THUMB 6
/* Overlap between arrows and thumb */
#define SCROLL_ARROW_THUMB_OVERLAP 0
/* Thumb-tracking info */ /* Thumb-tracking info */
static HWND ScrollTrackingWin = 0; static HWND ScrollTrackingWin = 0;
static INT ScrollTrackingBar = 0; static INT ScrollTrackingBar = 0;
@ -86,6 +89,32 @@ const struct builtin_class_descr SCROLL_builtin_class =
/* PRIVATE FUNCTIONS **********************************************************/ /* 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 static void
IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical, IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical,
@ -253,25 +282,16 @@ IntScrollDrawMovingThumb(HDC Dc, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical)
INT OldTop; INT OldTop;
if (Vertical) if (Vertical)
{
MaxSize = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->rcScrollBar.top; MaxSize = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->rcScrollBar.top;
}
else else
{
MaxSize = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->rcScrollBar.left; MaxSize = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->rcScrollBar.left;
}
MaxSize -= ScrollBarInfo->dxyLineButton + ScrollBarInfo->xyThumbBottom MaxSize -= ScrollBarInfo->dxyLineButton + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop;
- ScrollBarInfo->xyThumbTop;
if (Pos < ScrollBarInfo->dxyLineButton) if (Pos < ScrollBarInfo->dxyLineButton)
{
Pos = ScrollBarInfo->dxyLineButton; Pos = ScrollBarInfo->dxyLineButton;
}
else if (MaxSize < Pos) else if (MaxSize < Pos)
{
Pos = MaxSize; Pos = MaxSize;
}
OldTop = ScrollBarInfo->xyThumbTop; OldTop = ScrollBarInfo->xyThumbTop;
ScrollBarInfo->xyThumbBottom = Pos + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; ScrollBarInfo->xyThumbBottom = Pos + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop;
@ -286,15 +306,10 @@ IntScrollDrawMovingThumb(HDC Dc, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical)
static LONG FASTCALL static LONG FASTCALL
IntScrollGetObjectId(INT SBType) IntScrollGetObjectId(INT SBType)
{ {
if (SB_VERT == SBType) if (SBType == SB_VERT)
{
return OBJID_VSCROLL; return OBJID_VSCROLL;
} if (SBType == SB_HORZ)
if (SB_HORZ == SBType)
{
return OBJID_HSCROLL; return OBJID_HSCROLL;
}
return OBJID_CLIENT; return OBJID_CLIENT;
} }
@ -379,15 +394,25 @@ static BOOL FASTCALL
IntScrollPtInRectEx(LPRECT Rect, POINT Pt, BOOL Vertical) IntScrollPtInRectEx(LPRECT Rect, POINT Pt, BOOL Vertical)
{ {
RECT TempRect = *Rect; RECT TempRect = *Rect;
int scrollbarWidth;
/* Pad hit rect to allow mouse to be dragged outside of scrollbar and
* still be considered in the scrollbar. */
if (Vertical) if (Vertical)
{ {
TempRect.left -= Rect->right - Rect->left; scrollbarWidth = Rect->right - Rect->left;
TempRect.right += Rect->right - Rect->left; TempRect.left -= scrollbarWidth*8;
TempRect.right += scrollbarWidth*8;
TempRect.top -= scrollbarWidth*2;
TempRect.bottom += scrollbarWidth*2;
} }
else else
{ {
TempRect.top -= Rect->bottom - Rect->top; scrollbarWidth = Rect->bottom - Rect->top;
TempRect.bottom += Rect->bottom - Rect->top; TempRect.left -= scrollbarWidth*2;
TempRect.right += scrollbarWidth*2;
TempRect.top -= scrollbarWidth*8;
TempRect.bottom += scrollbarWidth*8;
} }
return PtInRect(&TempRect, Pt); return PtInRect(&TempRect, Pt);
@ -399,10 +424,7 @@ IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo, BOOL Vertical, POINT Pt, BOOL Dra
INT ArrowSize, ThumbSize, ThumbPos; INT ArrowSize, ThumbSize, ThumbPos;
if ((Dragging && ! IntScrollPtInRectEx(&ScrollBarInfo->rcScrollBar, Pt, Vertical)) || if ((Dragging && ! IntScrollPtInRectEx(&ScrollBarInfo->rcScrollBar, Pt, Vertical)) ||
! PtInRect(&ScrollBarInfo->rcScrollBar, Pt)) ! PtInRect(&ScrollBarInfo->rcScrollBar, Pt)) return SCROLL_NOWHERE;
{
return SCROLL_NOWHERE;
}
ThumbPos = ScrollBarInfo->xyThumbTop; ThumbPos = ScrollBarInfo->xyThumbTop;
ThumbSize = ScrollBarInfo->xyThumbBottom - ThumbPos; ThumbSize = ScrollBarInfo->xyThumbBottom - ThumbPos;
@ -410,51 +432,21 @@ IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo, BOOL Vertical, POINT Pt, BOOL Dra
if (Vertical) if (Vertical)
{ {
if (Pt.y < ScrollBarInfo->rcScrollBar.top + ArrowSize) if (Pt.y < ScrollBarInfo->rcScrollBar.top + ArrowSize) return SCROLL_TOP_ARROW;
{ if (Pt.y >= ScrollBarInfo->rcScrollBar.bottom - ArrowSize) return SCROLL_BOTTOM_ARROW;
return SCROLL_TOP_ARROW; if (!ThumbPos) return SCROLL_TOP_RECT;
}
if (ScrollBarInfo->rcScrollBar.bottom - ArrowSize <= Pt.y)
{
return SCROLL_BOTTOM_ARROW;
}
if (0 == ThumbPos)
{
return SCROLL_TOP_RECT;
}
Pt.y -= ScrollBarInfo->rcScrollBar.top; Pt.y -= ScrollBarInfo->rcScrollBar.top;
if (Pt.y < ThumbPos) if (Pt.y < ThumbPos) return SCROLL_TOP_RECT;
{ if (Pt.y >= ThumbPos + ThumbSize) return SCROLL_BOTTOM_RECT;
return SCROLL_TOP_RECT;
}
if (ThumbPos + ThumbSize <= Pt.y)
{
return SCROLL_BOTTOM_RECT;
}
} }
else else
{ {
if (Pt.x < ScrollBarInfo->rcScrollBar.left + ArrowSize) if (Pt.x < ScrollBarInfo->rcScrollBar.left + ArrowSize) return SCROLL_TOP_ARROW;
{ if (Pt.x >= ScrollBarInfo->rcScrollBar.right - ArrowSize) return SCROLL_BOTTOM_ARROW;
return SCROLL_TOP_ARROW; if (!ThumbPos) return SCROLL_TOP_RECT;
}
if (ScrollBarInfo->rcScrollBar.right - ArrowSize <= Pt.x)
{
return SCROLL_BOTTOM_ARROW;
}
if (0 == ThumbPos)
{
return SCROLL_TOP_RECT;
}
Pt.x -= ScrollBarInfo->rcScrollBar.left; Pt.x -= ScrollBarInfo->rcScrollBar.left;
if (Pt.x < ThumbPos) if (Pt.x < ThumbPos) return SCROLL_TOP_RECT;
{ if (Pt.x >= ThumbPos + ThumbSize) return SCROLL_BOTTOM_RECT;
return SCROLL_TOP_RECT;
}
if (ThumbPos + ThumbSize <= Pt.x)
{
return SCROLL_BOTTOM_RECT;
}
} }
return SCROLL_THUMB; return SCROLL_THUMB;
@ -479,145 +471,113 @@ IntScrollGetScrollBarRect(HWND Wnd, INT Bar, RECT *Rect,
{ {
INT Pixels; INT Pixels;
BOOL Vertical; BOOL Vertical;
RECT ClientRect;
RECT WindowRect;
DWORD Style, ExStyle;
PWND pWnd; PWND pWnd;
PSBINFO pSBInfo; PSBINFO pSBInfo;
PSBDATA pSBData;
PSBWND pSBWnd;
pWnd = ValidateHwnd( Wnd ); pWnd = ValidateHwnd( Wnd );
if (!pWnd) return FALSE;
pSBInfo = DesktopPtrToUser(pWnd->pSBInfo); pSBInfo = DesktopPtrToUser(pWnd->pSBInfo);
GetClientRect(Wnd, &ClientRect); *Rect = pWnd->rcClient;
if (SB_HORZ == Bar || SB_VERT == Bar) OffsetRect( Rect, -pWnd->rcWindow.left, -pWnd->rcWindow.top );
{ if (pWnd->ExStyle & WS_EX_LAYOUTRTL)
ClientToScreen(Wnd, (LPPOINT) &ClientRect.left); mirror_rect( &pWnd->rcWindow, Rect );
ClientToScreen(Wnd, (LPPOINT) &ClientRect.right);
GetWindowRect(Wnd, &WindowRect);
}
Style = GetWindowLongPtrW(Wnd, GWL_STYLE);
switch (Bar) switch (Bar)
{ {
case SB_HORZ: case SB_HORZ:
Rect->left = ClientRect.left - WindowRect.left; // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
Rect->top = ClientRect.bottom - WindowRect.top; Rect->top = Rect->bottom;
Rect->right = ClientRect.right - WindowRect.left; Rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
Rect->bottom = Rect->top + GetSystemMetrics(SM_CYHSCROLL); if (pWnd->style & WS_BORDER)
if (0 != (Style & WS_BORDER))
{ {
Rect->left--; Rect->left--;
Rect->right++; Rect->right++;
} }
else if (0 != (Style & WS_VSCROLL)) else if (pWnd->style & WS_VSCROLL)
{ {
Rect->right++; Rect->right++;
} }
Vertical = FALSE; Vertical = FALSE;
pSBData = &pSBInfo->Horz;
break; break;
case SB_VERT: case SB_VERT:
ExStyle = GetWindowLongPtrW(Wnd, GWL_EXSTYLE); // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
if (0 != (ExStyle & WS_EX_LEFTSCROLLBAR)) if (pWnd->ExStyle & WS_EX_LEFTSCROLLBAR)
{ {
Rect->left = ClientRect.left - WindowRect.left - GetSystemMetrics(SM_CXVSCROLL); Rect->right = Rect->left;
Rect->left -= GetSystemMetrics(SM_CXVSCROLL);
} }
else else
{ {
Rect->left = ClientRect.right - WindowRect.left; Rect->left = Rect->right;
Rect->right += GetSystemMetrics(SM_CXVSCROLL);
} }
Rect->top = ClientRect.top - WindowRect.top; if (pWnd->style & WS_BORDER)
Rect->right = Rect->left + GetSystemMetrics(SM_CXVSCROLL);
Rect->bottom = ClientRect.bottom - WindowRect.top;
if (0 != (Style & WS_BORDER))
{ {
Rect->top--; Rect->top--;
Rect->bottom++; Rect->bottom++;
} }
else if (0 != (Style & WS_HSCROLL)) else if (pWnd->style & WS_HSCROLL)
{ {
Rect->bottom++; Rect->bottom++;
} }
Vertical = TRUE; Vertical = TRUE;
pSBData = &pSBInfo->Vert;
break; break;
case SB_CTL: case SB_CTL:
*Rect = ClientRect; GetClientRect( Wnd, Rect );
Vertical = (0 != (Style & SBS_VERT)); Vertical = (pWnd->style & SBS_VERT);
pSBWnd = (PSBWND)pWnd;
pSBData = (PSBDATA)&pSBWnd->SBCalc;
break; break;
default: default:
return FALSE; return FALSE;
} }
if (Vertical) if (Vertical) Pixels = Rect->bottom - Rect->top;
{ else Pixels = Rect->right - Rect->left;
Pixels = Rect->bottom - Rect->top;
}
else
{
Pixels = Rect->right - Rect->left;
}
if (Pixels <= 2 * GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT) if (Pixels <= 2 * GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT)
{ {
if (SCROLL_MIN_RECT < Pixels) if (SCROLL_MIN_RECT < Pixels)
{
*ArrowSize = (Pixels - SCROLL_MIN_RECT) / 2; *ArrowSize = (Pixels - SCROLL_MIN_RECT) / 2;
}
else else
{
*ArrowSize = 0; *ArrowSize = 0;
}
*ThumbPos = *ThumbSize = 0; *ThumbPos = *ThumbSize = 0;
} }
else else
{ {
SCROLLINFO Info;
NtUserSBGetParms(Wnd, Bar, NULL, &Info);
*ArrowSize = GetSystemMetrics(SM_CXVSCROLL); *ArrowSize = GetSystemMetrics(SM_CXVSCROLL);
Pixels -= (2 * GetSystemMetrics(SM_CXVSCROLL)); Pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
if (pSBData->page)
{
*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 != Info.nPage)
{
*ThumbSize = MulDiv(Pixels, Info.nPage, (Info.nMax - Info.nMin + 1));
if (*ThumbSize < SCROLL_MIN_THUMB)
{
*ThumbSize = SCROLL_MIN_THUMB;
}
}
else
{
*ThumbSize = GetSystemMetrics(SM_CXVSCROLL);
}
//#if 0 /* FIXME */
if (((Pixels -= *ThumbSize ) < 0) || if (((Pixels -= *ThumbSize ) < 0) ||
(( pSBInfo->WSBflags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)) (( pSBInfo->WSBflags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
//#else
// if ((Pixels -= *ThumbSize ) < 0)
//#endif
{ {
/* Rectangle too small or scrollbar disabled -> no thumb */ /* Rectangle too small or scrollbar disabled -> no thumb */
*ThumbPos = *ThumbSize = 0; *ThumbPos = *ThumbSize = 0;
} }
else else
{ {
INT Max = Info.nMax - max(Info.nPage - 1, 0); INT Max = pSBData->posMax - max(pSBData->page - 1, 0);
if (Max <= Info.nMin) if (pSBData->posMin >= Max)
{ *ThumbPos = *ArrowSize - SCROLL_ARROW_THUMB_OVERLAP;
*ThumbPos = *ArrowSize;
}
else else
{ *ThumbPos = *ArrowSize - SCROLL_ARROW_THUMB_OVERLAP
*ThumbPos = *ArrowSize + MulDiv(Pixels, (pSBData->pos - pSBData->posMin),(Max - pSBData->posMin));
+ MulDiv(Pixels, (Info.nPos - Info.nMin),
(Max - Info.nMin));
} }
} }
}
return Vertical; return Vertical;
} }
@ -631,23 +591,26 @@ static UINT FASTCALL
IntScrollGetThumbVal(HWND Wnd, INT SBType, PSCROLLBARINFO ScrollBarInfo, IntScrollGetThumbVal(HWND Wnd, INT SBType, PSCROLLBARINFO ScrollBarInfo,
BOOL Vertical, INT Pos) BOOL Vertical, INT Pos)
{ {
SCROLLINFO si; PWND pWnd;
PSBDATA pSBData;
INT Pixels = Vertical ? ScrollBarInfo->rcScrollBar.bottom INT Pixels = Vertical ? ScrollBarInfo->rcScrollBar.bottom
- ScrollBarInfo->rcScrollBar.top - ScrollBarInfo->rcScrollBar.top
: ScrollBarInfo->rcScrollBar.right : ScrollBarInfo->rcScrollBar.right
- ScrollBarInfo->rcScrollBar.left; - ScrollBarInfo->rcScrollBar.left;
si.cbSize = sizeof(SCROLLINFO); pWnd = ValidateHwnd( Wnd );
si.fMask = SIF_RANGE | SIF_PAGE; if (!pWnd) return FALSE;
NtUserSBGetParms(Wnd, SBType, NULL, &si);
pSBData = IntGetSBData(pWnd, SBType);
if ((Pixels -= 2 * ScrollBarInfo->dxyLineButton) <= 0) if ((Pixels -= 2 * ScrollBarInfo->dxyLineButton) <= 0)
{ {
return si.nMin; return pSBData->posMin;
} }
if ((Pixels -= (ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop)) <= 0) if ((Pixels -= (ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop)) <= 0)
{ {
return si.nMin; return pSBData->posMin;
} }
Pos = Pos - ScrollBarInfo->dxyLineButton; Pos = Pos - ScrollBarInfo->dxyLineButton;
@ -655,46 +618,34 @@ IntScrollGetThumbVal(HWND Wnd, INT SBType, PSCROLLBARINFO ScrollBarInfo,
{ {
Pos = 0; Pos = 0;
} }
if (Pixels < Pos) if (Pos > Pixels) Pos = Pixels;
{
Pos = Pixels;
}
if (0 == si.nPage) if (!pSBData->page)
{ Pos *= pSBData->posMax - pSBData->posMin;
Pos *= si.nMax - si.nMin;
}
else else
{ Pos *= pSBData->posMax - pSBData->posMin - pSBData->page + 1;
Pos *= si.nMax - si.nMin - si.nPage + 1;
} return pSBData->posMin + ((Pos + Pixels / 2) / Pixels);
return si.nMin + ((Pos + Pixels / 2) / Pixels);
} }
/*********************************************************************** /***********************************************************************
* IntScrollClipPos * IntScrollClipPos
*/ */
static POINT IntScrollClipPos(PRECT Rect, POINT Pt) static POINT IntScrollClipPos(PRECT lpRect, POINT pt)
{ {
if (Pt.x < Rect->left) if( pt.x < lpRect->left )
{ pt.x = lpRect->left;
Pt.x = Rect->left; else
} if( pt.x > lpRect->right )
else if (Rect->right < Pt.x) pt.x = lpRect->right;
{
Pt.x = Rect->right;
}
if (Pt.y < Rect->top) if( pt.y < lpRect->top )
{ pt.y = lpRect->top;
Pt.y = Rect->top; else
} if( pt.y > lpRect->bottom )
else if (Rect->bottom < Pt.y) pt.y = lpRect->bottom;
{
Pt.y = Rect->bottom;
}
return Pt; return pt;
} }
/*********************************************************************** /***********************************************************************
@ -1092,7 +1043,7 @@ static void IntScrollCreateScrollBar(
TRACE("hwnd=%p lpCreate=%p\n", Wnd, lpCreate); TRACE("hwnd=%p lpCreate=%p\n", Wnd, lpCreate);
//#if 0 /* FIXME */ #if 0 /* FIXME */
if (lpCreate->style & WS_DISABLED) if (lpCreate->style & WS_DISABLED)
{ {
// info->flags = ESB_DISABLE_BOTH; // info->flags = ESB_DISABLE_BOTH;
@ -1100,7 +1051,7 @@ static void IntScrollCreateScrollBar(
NtUserMessageCall( Wnd, WM_ENABLE, FALSE, 0, 0, FNID_SCROLLBAR, FALSE); NtUserMessageCall( Wnd, WM_ENABLE, FALSE, 0, 0, FNID_SCROLLBAR, FALSE);
ERR("Created WS_DISABLED scrollbar\n"); ERR("Created WS_DISABLED scrollbar\n");
} }
//#endif #endif
if (0 != (lpCreate->style & (SBS_SIZEGRIP | SBS_SIZEBOX))) if (0 != (lpCreate->style & (SBS_SIZEGRIP | SBS_SIZEBOX)))
{ {
if (0 != (lpCreate->style & SBS_SIZEBOXTOPLEFTALIGN)) 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 **************************************************/ /* USER32 INTERNAL FUNCTIONS **************************************************/
/*********************************************************************** /***********************************************************************
@ -1199,13 +1114,13 @@ ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt)
UINT XOffset = 0, YOffset = 0; UINT XOffset = 0, YOffset = 0;
if (SBType != SB_CTL) if (SBType != SB_CTL)
{ // Replace HAX for CMD mouse tracking. { // Used with CMD mouse tracking.
PWND pwnd = ValidateHwnd(Wnd); PWND pwnd = ValidateHwnd(Wnd);
if (!pwnd) return; if (!pwnd) return;
XOffset = pwnd->rcClient.left - pwnd->rcWindow.left; XOffset = pwnd->rcClient.left - pwnd->rcWindow.left;
YOffset = pwnd->rcClient.top - pwnd->rcWindow.top; YOffset = pwnd->rcClient.top - pwnd->rcWindow.top;
// RECT rect; // RECT rect;
// GetClientRect(Wnd, &rect); // WIN_GetRectangles( Wnd, COORDS_CLIENT, &rect, NULL );
ScreenToClient(Wnd, &Pt); ScreenToClient(Wnd, &Pt);
// Pt.x -= rect.left; // Pt.x -= rect.left;
// Pt.y -= rect.top; // 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 * 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. #ifdef __REACTOS__ // Do this now, remove after Server side is fixed.
PWND pWnd; PWND pWnd;
PSBWND pSBWnd;
SCROLLINFO ScrollInfo;
pWnd = ValidateHwnd(Wnd); pWnd = ValidateHwnd(Wnd);
if (pWnd) if (pWnd)
{ {
if (!pWnd->fnid) 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) if (Msg != WM_CREATE)
{ {
return DefWindowProc(Wnd, Msg, wParam, lParam); return DefWindowProc(Wnd, Msg, wParam, lParam);
@ -1277,6 +1210,9 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam
return 0; return 0;
} }
// Must be a scroll bar control!
pSBWnd = (PSBWND)pWnd;
switch (Msg) switch (Msg)
{ {
case WM_CREATE: case WM_CREATE:
@ -1285,17 +1221,8 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam
case WM_ENABLE: case WM_ENABLE:
{ {
PWND pWnd = ValidateHwnd(Wnd); return SendMessageW( Wnd, SBM_ENABLE_ARROWS, wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH, 0);
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;
case WM_LBUTTONDBLCLK: case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
@ -1408,35 +1335,49 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam
} }
break; break;
case SBM_SETPOS:
return SetScrollPos(Wnd, SB_CTL, wParam, (BOOL) lParam);
case SBM_GETPOS: case SBM_GETPOS:
return IntScrollGetScrollPos(Wnd, SB_CTL); return pSBWnd->SBCalc.pos;
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;
case SBM_GETRANGE: 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: case SBM_ENABLE_ARROWS:
return EnableScrollBar( Wnd, SB_CTL, wParam ); 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: case SBM_SETSCROLLINFO:
return NtUserSetScrollInfo(Wnd, SB_CTL, (SCROLLINFO *) lParam, wParam); return IntSetScrollInfo(Wnd, (LPCSCROLLINFO)lParam, wParam);
case SBM_GETSCROLLINFO: 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: case SBM_GETSCROLLBARINFO:
((PSCROLLBARINFO)lParam)->cbSize = sizeof(SCROLLBARINFO); ((PSCROLLBARINFO)lParam)->cbSize = sizeof(SCROLLBARINFO);
return NtUserGetScrollBarInfo(Wnd, OBJID_CLIENT, (PSCROLLBARINFO)lParam); return NtUserGetScrollBarInfo(Wnd, OBJID_CLIENT, (PSCROLLBARINFO)lParam);
@ -1496,8 +1437,7 @@ BOOL WINAPI EnableScrollBar( HWND hwnd, UINT nBar, UINT flags )
if (!Hook) if (!Hook)
{ {
Ret = NtUserEnableScrollBar(hwnd, nBar, flags); Ret = NtUserEnableScrollBar(hwnd, nBar, flags);
if (GetLastError() == ERROR_INVALID_PARAMETER) return Ret; if (!Ret) return Ret;
if (nBar == SB_CTL) return Ret;
SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
return Ret; return Ret;
} }
@ -1519,7 +1459,7 @@ BOOL WINAPI
RealGetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info) RealGetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info)
{ {
PWND pWnd; PWND pWnd;
PSBDATA pSBData = NULL; PSBDATA pSBData;
if (SB_CTL == SBType) if (SB_CTL == SBType)
{ {
@ -1534,7 +1474,12 @@ RealGetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info)
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return FALSE; 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); return NtUserSBGetParms(Wnd, SBType, pSBData, Info);
} }
@ -1573,6 +1518,9 @@ GetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info)
INT WINAPI INT WINAPI
GetScrollPos(HWND Wnd, INT Bar) GetScrollPos(HWND Wnd, INT Bar)
{ {
PWND pwnd;
PSBDATA pSBData;
TRACE("Wnd=%p Bar=%d\n", Wnd, Bar); TRACE("Wnd=%p Bar=%d\n", Wnd, Bar);
/* Refer SB_CTL requests to the window */ /* Refer SB_CTL requests to the window */
@ -1580,10 +1528,23 @@ GetScrollPos(HWND Wnd, INT Bar)
{ {
return SendMessageW(Wnd, SBM_GETPOS, (WPARAM) 0, (LPARAM) 0); return SendMessageW(Wnd, SBM_GETPOS, (WPARAM) 0, (LPARAM) 0);
} }
else else if (Bar == SB_HORZ || Bar == SB_VERT )
{ {
return IntScrollGetScrollPos(Wnd, Bar); 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,6 +1553,9 @@ GetScrollPos(HWND Wnd, INT Bar)
BOOL WINAPI BOOL WINAPI
GetScrollRange(HWND Wnd, int Bar, LPINT MinPos, LPINT MaxPos) 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); TRACE("Wnd=%x Bar=%d Min=%p Max=%p\n", Wnd, Bar, MinPos, MaxPos);
/* Refer SB_CTL requests to the window */ /* Refer SB_CTL requests to the window */
@ -1599,10 +1563,27 @@ GetScrollRange(HWND Wnd, int Bar, LPINT MinPos, LPINT MaxPos)
{ {
return SendMessageW(Wnd, SBM_GETRANGE, (WPARAM) MinPos, (LPARAM) MaxPos); return SendMessageW(Wnd, SBM_GETRANGE, (WPARAM) MinPos, (LPARAM) 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 else
{ {
return IntScrollGetScrollRange(Wnd, Bar, MinPos, MaxPos); SetLastError(ERROR_NO_SCROLLBARS);
*MinPos = 0;
*MaxPos = 0;
} }
return TRUE;
}
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
} }
INT WINAPI INT WINAPI
@ -1655,32 +1636,13 @@ SetScrollInfo(HWND Wnd, int SBType, LPCSCROLLINFO Info, BOOL bRedraw)
INT WINAPI INT WINAPI
SetScrollPos(HWND hWnd, INT nBar, INT nPos, BOOL bRedraw) SetScrollPos(HWND hWnd, INT nBar, INT nPos, BOOL bRedraw)
{ {
PWND pWnd;
INT Result = 0;
SCROLLINFO ScrollInfo; SCROLLINFO ScrollInfo;
pWnd = ValidateHwnd(hWnd);
if ( !pWnd || !pWnd->pSBInfo ) return 0;
ScrollInfo.cbSize = sizeof(SCROLLINFO); ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_POS; ScrollInfo.fMask = SIF_POS|SIF_PREVIOUSPOS;
/*
* 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; 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.nMin = nMinPos;
ScrollInfo.nMax = nMaxPos; ScrollInfo.nMax = nMaxPos;
SetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); // do not bypass themes. SetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); // do not bypass themes.
return TRUE; return TRUE;
} }