Implement scrollbar controls

svn path=/trunk/; revision=8887
This commit is contained in:
Gé van Geldorp 2004-03-27 10:46:32 +00:00
parent 0529529902
commit dd3a343e64
3 changed files with 860 additions and 299 deletions

View file

@ -1,4 +1,4 @@
/* $Id: regcontrol.c,v 1.17 2003/12/07 23:02:57 gvg Exp $ /* $Id: regcontrol.c,v 1.18 2004/03/27 10:46:32 gvg Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS User32 * PROJECT: ReactOS User32
@ -65,8 +65,8 @@ ControlsInit(LPCWSTR ClassName)
&MDICLIENT_builtin_class, &MDICLIENT_builtin_class,
#if 0 #if 0
&MENU_builtin_class, &MENU_builtin_class,
&SCROLL_builtin_class,
#endif #endif
&SCROLL_builtin_class,
&BUTTON_builtin_class, &BUTTON_builtin_class,
&LISTBOX_builtin_class, &LISTBOX_builtin_class,
&EDIT_builtin_class, &EDIT_builtin_class,

View file

@ -36,6 +36,7 @@
#include <draw.h> #include <draw.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <user32/regcontrol.h>
#include <rosrtl/minmax.h> #include <rosrtl/minmax.h>
/* GLOBAL VARIABLES ***********************************************************/ /* GLOBAL VARIABLES ***********************************************************/
@ -54,6 +55,12 @@
#define SCROLL_TIMER 0 /* Scroll timer id */ #define SCROLL_TIMER 0 /* Scroll timer id */
/* Minimum size of the rectangle between the arrows */
#define SCROLL_MIN_RECT 4
/* Minimum size of the thumb in pixels */
#define SCROLL_MIN_THUMB 6
/* Thumb-tracking info */ /* Thumb-tracking info */
static HWND ScrollTrackingWin = 0; static HWND ScrollTrackingWin = 0;
static INT ScrollTrackingBar = 0; static INT ScrollTrackingBar = 0;
@ -66,6 +73,24 @@ static BOOL ScrollTrackVertical;
HBRUSH DefWndControlColor(HDC hDC, UINT ctlType); HBRUSH DefWndControlColor(HDC hDC, UINT ctlType);
static LRESULT WINAPI ScrollBarWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
/*********************************************************************
* scrollbar class descriptor
*/
const struct builtin_class_descr SCROLL_builtin_class =
{
L"ScrollBar", /* name */
CS_VREDRAW | CS_HREDRAW | CS_PARENTDC, /* style, Wine included CS_DBLCLK but then didn't
handle any WM_xBUTTONDBLCLK messages */
ScrollBarWndProc, /* procW */
NULL, /* procA (winproc is Unicode only) */
sizeof(SCROLLBARINFO) + sizeof(SCROLLINFO), /* extra */
IDC_ARROW, /* cursor */
0 /* brush */
};
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
@ -269,67 +294,92 @@ IntScrollDrawMovingThumb(HDC Dc, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical)
ScrollMovingThumb = ! ScrollMovingThumb; ScrollMovingThumb = ! ScrollMovingThumb;
} }
void STATIC LONG FASTCALL
IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar) IntScrollGetObjectId(INT SBType)
{ {
INT ThumbSize; if (SB_VERT == SBType)
SCROLLBARINFO Info; {
BOOL Vertical; return OBJID_VSCROLL;
}
if (SB_HORZ == SBType)
{
return OBJID_HSCROLL;
}
/* return OBJID_CLIENT;
* Get scroll bar info. }
*/
Info.cbSize = sizeof(SCROLLBARINFO); STATIC BOOL FASTCALL
switch (nBar) IntGetScrollBarInfo(HWND Wnd, INT Bar, PSCROLLBARINFO ScrollBarInfo)
{ {
ScrollBarInfo->cbSize = sizeof(SCROLLBARINFO);
return NtUserGetScrollBarInfo(Wnd, IntScrollGetObjectId(Bar), ScrollBarInfo);
}
void
IntDrawScrollBar(HWND Wnd, HDC DC, INT Bar)
{
INT ThumbSize;
SCROLLBARINFO Info;
BOOL Vertical;
/*
* Get scroll bar info.
*/
switch (Bar)
{
case SB_HORZ: case SB_HORZ:
Vertical = FALSE; Vertical = FALSE;
NtUserGetScrollBarInfo(hWnd, OBJID_HSCROLL, &Info); break;
break;
case SB_VERT: case SB_VERT:
Vertical = TRUE; Vertical = TRUE;
NtUserGetScrollBarInfo(hWnd, OBJID_VSCROLL, &Info); break;
break;
case SB_CTL: case SB_CTL:
Vertical = (GetWindowLongW(hWnd, GWL_STYLE) & SBS_VERT) != 0; Vertical = (GetWindowLongW(Wnd, GWL_STYLE) & SBS_VERT) != 0;
NtUserGetScrollBarInfo(hWnd, OBJID_CLIENT, &Info); break;
break; }
} if (! IntGetScrollBarInfo(Wnd, Bar, &Info))
{
if (IsRectEmpty(&Info.rcScrollBar))
{
return; return;
} }
if (IsRectEmpty(&Info.rcScrollBar))
{
return;
}
ThumbSize = Info.xyThumbBottom - Info.xyThumbTop; ThumbSize = Info.xyThumbBottom - Info.xyThumbTop;
/* /*
* Draw the arrows. * Draw the arrows.
*/ */
if (Info.dxyLineButton)
{
IntDrawScrollArrows(DC, &Info, Vertical);
}
if (Info.dxyLineButton) /*
IntDrawScrollArrows(hDC, &Info, Vertical); * Draw the interior.
*/
IntDrawScrollInterior(Wnd, DC, Bar, Vertical, &Info);
/* /*
* Draw the interior. * If scroll bar has focus, reposition the caret.
*/ */
if (Wnd == GetFocus() && SB_CTL == Bar)
IntDrawScrollInterior(hWnd, hDC, nBar, Vertical, &Info); {
if (Vertical)
/* {
* If scroll bar has focus, reposition the caret. SetCaretPos(Info.rcScrollBar.top + 1, Info.dxyLineButton + 1);
*/ }
else
if (hWnd == GetFocus() && nBar == SB_CTL) {
{ SetCaretPos(Info.dxyLineButton + 1, Info.rcScrollBar.top + 1);
if (nBar == SB_HORZ) }
SetCaretPos(Info.dxyLineButton + 1, Info.rcScrollBar.top + 1); }
else if (nBar == SB_VERT)
SetCaretPos(Info.rcScrollBar.top + 1, Info.dxyLineButton + 1);
}
} }
STATIC BOOL FASTCALL STATIC BOOL FASTCALL
@ -350,29 +400,6 @@ IntScrollPtInRectEx(LPRECT Rect, POINT Pt, BOOL Vertical)
return PtInRect(&TempRect, Pt); return PtInRect(&TempRect, Pt);
} }
STATIC LONG FASTCALL
IntScrollGetObjectId(INT SBType)
{
if (SB_VERT == SBType)
{
return OBJID_VSCROLL;
}
if (SB_HORZ == SBType)
{
return OBJID_HSCROLL;
}
return OBJID_CLIENT;
}
STATIC BOOL FASTCALL
IntGetScrollBarInfo(HWND Wnd, INT SBType, PSCROLLBARINFO ScrollBarInfo)
{
ScrollBarInfo->cbSize = sizeof(SCROLLBARINFO);
return NtUserGetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), ScrollBarInfo);
}
STATIC DWORD FASTCALL STATIC DWORD FASTCALL
IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo, BOOL Vertical, POINT Pt, BOOL Dragging) IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo, BOOL Vertical, POINT Pt, BOOL Dragging)
{ {
@ -440,6 +467,162 @@ IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo, BOOL Vertical, POINT Pt, BOOL Dra
return SCROLL_THUMB; return SCROLL_THUMB;
} }
/***********************************************************************
* IntScrollGetScrollBarRect
*
* Compute the scroll bar rectangle, in drawing coordinates (i.e. client
* coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
* 'arrowSize' returns the width or height of an arrow (depending on
* the orientation of the scrollbar), '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 BOOL FASTCALL
IntScrollGetScrollBarRect(HWND Wnd, INT Bar, RECT *Rect,
INT *ArrowSize, INT *ThumbSize,
INT *ThumbPos)
{
INT Pixels;
BOOL Vertical;
RECT ClientRect;
RECT WindowRect;
DWORD Style, ExStyle;
GetClientRect(Wnd, &ClientRect);
if (SB_HORZ == Bar || SB_VERT == Bar)
{
ClientToScreen(Wnd, (LPPOINT) &ClientRect.left);
ClientToScreen(Wnd, (LPPOINT) &ClientRect.right);
GetWindowRect(Wnd, &WindowRect);
}
Style = GetWindowLongW(Wnd, GWL_STYLE);
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))
{
Rect->left--;
Rect->right++;
}
else if (0 != (Style & WS_VSCROLL))
{
Rect->right++;
}
Vertical = FALSE;
break;
case SB_VERT:
ExStyle = GetWindowLongW(Wnd, GWL_EXSTYLE);
if (0 != (ExStyle & WS_EX_LEFTSCROLLBAR))
{
Rect->left = ClientRect.left - WindowRect.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->top--;
Rect->bottom++;
}
else if (0 != (Style & WS_HSCROLL))
{
Rect->bottom++;
}
Vertical = TRUE;
break;
case SB_CTL:
*Rect = ClientRect;
Vertical = (0 != (Style & SBS_VERT));
break;
default:
return FALSE;
}
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;
NtUserGetScrollInfo(Wnd, Bar, &Info);
*ArrowSize = GetSystemMetrics(SM_CXVSCROLL);
Pixels -= (2 * 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) ||
((info->flags & 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;
}
else
{
*ThumbPos = *ArrowSize
+ MulDiv(Pixels, (Info.nPos - Info.nMin),
(Max - Info.nMin));
}
}
}
return Vertical;
}
/*********************************************************************** /***********************************************************************
* IntScrollGetThumbVal * IntScrollGetThumbVal
* *
@ -512,6 +695,79 @@ STATIC POINT IntScrollClipPos(PRECT Rect, POINT Pt)
return Pt; return Pt;
} }
/***********************************************************************
* IntScrollDrawSizeGrip
*
* Draw the size grip.
*/
STATIC void FASTCALL
IntScrollDrawSizeGrip(HWND Wnd, HDC Dc)
{
RECT Rect;
GetClientRect(Wnd, &Rect);
FillRect(Dc, &Rect, GetSysColorBrush(COLOR_SCROLLBAR));
Rect.left = max(Rect.left, Rect.right - GetSystemMetrics(SM_CXVSCROLL) - 1);
Rect.top = max(Rect.top, Rect.bottom - GetSystemMetrics(SM_CYHSCROLL) - 1);
DrawFrameControl(Dc, &Rect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
}
/***********************************************************************
* IntScrollHandleKbdEvent
*
* Handle a keyboard event (only for SB_CTL scrollbars with focus).
*/
STATIC void FASTCALL
IntScrollHandleKbdEvent(
HWND Wnd /* [in] Handle of window with scrollbar(s) */,
WPARAM wParam /* [in] Variable input including enable state */,
LPARAM lParam /* [in] Variable input including input point */)
{
DPRINT("Wnd=%p wParam=%d lParam=%ld\n", Wnd, wParam, lParam);
/* hide caret on first KEYDOWN to prevent flicker */
if (0 == (lParam & PFD_DOUBLEBUFFER_DONTCARE))
{
HideCaret(Wnd);
}
switch(wParam)
{
case VK_PRIOR:
wParam = SB_PAGEUP;
break;
case VK_NEXT:
wParam = SB_PAGEDOWN;
break;
case VK_HOME:
wParam = SB_TOP;
break;
case VK_END:
wParam = SB_BOTTOM;
break;
case VK_UP:
wParam = SB_LINEUP;
break;
case VK_DOWN:
wParam = SB_LINEDOWN;
break;
default:
return;
}
SendMessageW(GetParent(Wnd),
(0 != (GetWindowLongW(Wnd, GWL_STYLE ) & SBS_VERT) ?
WM_VSCROLL : WM_HSCROLL), wParam, (LPARAM) Wnd);
}
/*********************************************************************** /***********************************************************************
* IntScrollHandleScrollEvent * IntScrollHandleScrollEvent
* *
@ -799,6 +1055,122 @@ IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt)
} }
/***********************************************************************
* IntScrollCreateScrollBar
*
* Create a scroll bar
*/
static void IntScrollCreateScrollBar(
HWND Wnd /* [in] Handle of window with scrollbar(s) */,
LPCREATESTRUCTW lpCreate /* [in] The style and place of the scroll bar */)
{
SCROLLINFO Info;
Info.cbSize = sizeof(SCROLLINFO);
Info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
Info.nMin = 0;
Info.nMax = 100;
Info.nPage = 0;
Info.nPos = 0;
Info.nTrackPos = 0;
NtUserSetScrollInfo(Wnd, SB_CTL, &Info, FALSE);
DPRINT("hwnd=%p lpCreate=%p\n", Wnd, lpCreate);
#if 0 /* FIXME */
if (lpCreate->style & WS_DISABLED)
{
info->flags = ESB_DISABLE_BOTH;
TRACE("Created WS_DISABLED scrollbar\n");
}
#endif
if (0 != (lpCreate->style & (SBS_SIZEGRIP | SBS_SIZEBOX)))
{
if (0 != (lpCreate->style & SBS_SIZEBOXTOPLEFTALIGN))
{
MoveWindow(Wnd, lpCreate->x, lpCreate->y, GetSystemMetrics(SM_CXVSCROLL) + 1,
GetSystemMetrics(SM_CYHSCROLL) + 1, FALSE);
}
else if (0 != (lpCreate->style & SBS_SIZEBOXBOTTOMRIGHTALIGN))
{
MoveWindow(Wnd, lpCreate->x + lpCreate->cx - GetSystemMetrics(SM_CXVSCROLL) - 1,
lpCreate->y + lpCreate->cy - GetSystemMetrics(SM_CYHSCROLL) - 1,
GetSystemMetrics(SM_CXVSCROLL) + 1,
GetSystemMetrics(SM_CYHSCROLL) + 1, FALSE);
}
}
else if (0 != (lpCreate->style & SBS_VERT))
{
if (0 != (lpCreate->style & SBS_LEFTALIGN))
{
MoveWindow(Wnd, lpCreate->x, lpCreate->y,
GetSystemMetrics(SM_CXVSCROLL) + 1, lpCreate->cy, FALSE);
}
else if (0 != (lpCreate->style & SBS_RIGHTALIGN))
{
MoveWindow(Wnd,
lpCreate->x + lpCreate->cx - GetSystemMetrics(SM_CXVSCROLL) - 1,
lpCreate->y,
GetSystemMetrics(SM_CXVSCROLL) + 1, lpCreate->cy, FALSE);
}
}
else /* SBS_HORZ */
{
if (0 != (lpCreate->style & SBS_TOPALIGN))
{
MoveWindow(Wnd, lpCreate->x, lpCreate->y,
lpCreate->cx, GetSystemMetrics(SM_CYHSCROLL) + 1, FALSE);
}
else if (0 != (lpCreate->style & SBS_BOTTOMALIGN))
{
MoveWindow(Wnd,
lpCreate->x,
lpCreate->y + lpCreate->cy - GetSystemMetrics(SM_CYHSCROLL) - 1,
lpCreate->cx, GetSystemMetrics(SM_CYHSCROLL) + 1, FALSE);
}
}
}
STATIC INT FASTCALL
IntScrollGetScrollPos(HWND Wnd, INT Bar)
{
SCROLLINFO ScrollInfo;
ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_POS;
if (! NtUserGetScrollInfo(Wnd, Bar, &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 = NtUserGetScrollInfo(Wnd, Bar, &ScrollInfo);
if (Result)
{
*MinPos = ScrollInfo.nMin;
*MaxPos = ScrollInfo.nMax;
}
return Result;
}
/* USER32 INTERNAL FUNCTIONS **************************************************/ /* USER32 INTERNAL FUNCTIONS **************************************************/
/*********************************************************************** /***********************************************************************
@ -871,6 +1243,211 @@ ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt)
while (WM_LBUTTONUP != Msg.message); while (WM_LBUTTONUP != Msg.message);
} }
/***********************************************************************
* ScrollBarWndProc
*/
static LRESULT WINAPI
ScrollBarWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (! IsWindow(Wnd))
{
return 0;
}
switch (Msg)
{
case WM_CREATE:
IntScrollCreateScrollBar(Wnd, (LPCREATESTRUCTW) lParam);
break;
#if 0 /* FIXME */
case WM_ENABLE:
{
SCROLLBAR_INFO *infoPtr;
if ((infoPtr = SCROLL_GetScrollBarInfo( hwnd, SB_CTL )))
{
infoPtr->flags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
SCROLL_RefreshScrollBar(hwnd, SB_CTL, TRUE, TRUE);
}
}
return 0;
#endif
case WM_LBUTTONDOWN:
{
POINT Pt;
Pt.x = (short)LOWORD(lParam);
Pt.y = (short)HIWORD(lParam);
ScrollTrackScrollBar(Wnd, SB_CTL, Pt);
}
break;
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
case WM_SYSTIMER:
{
POINT Pt;
Pt.x = (short)LOWORD(lParam);
Pt.y = (short)HIWORD(lParam);
IntScrollHandleScrollEvent(Wnd, SB_CTL, Msg, Pt);
}
break;
case WM_KEYDOWN:
IntScrollHandleKbdEvent(Wnd, wParam, lParam);
break;
case WM_KEYUP:
ShowCaret(Wnd);
break;
case WM_SETFOCUS:
{
/* Create a caret when a ScrollBar get focus */
RECT Rect;
int ArrowSize, ThumbSize, ThumbPos, Vertical;
Vertical = IntScrollGetScrollBarRect(Wnd, SB_CTL, &Rect,
&ArrowSize, &ThumbSize, &ThumbPos);
if (! Vertical)
{
CreateCaret(Wnd, (HBITMAP) 1, ThumbSize - 2, Rect.bottom - Rect.top - 2);
SetCaretPos(ThumbPos + 1, Rect.top + 1);
}
else
{
CreateCaret(Wnd, (HBITMAP) 1, Rect.right - Rect.left - 2, ThumbSize - 2);
SetCaretPos(Rect.top + 1, ThumbPos + 1);
}
ShowCaret(Wnd);
}
break;
case WM_KILLFOCUS:
{
RECT Rect;
int ArrowSize, ThumbSize, ThumbPos, Vertical;
Vertical = IntScrollGetScrollBarRect(Wnd, SB_CTL, &Rect,
&ArrowSize, &ThumbSize, &ThumbPos);
if (! Vertical)
{
Rect.left = ThumbPos + 1;
Rect.right = Rect.left + ThumbSize;
}
else
{
Rect.top = ThumbPos + 1;
Rect.bottom = Rect.top + ThumbSize;
}
HideCaret(Wnd);
InvalidateRect(Wnd, &Rect, FALSE);
DestroyCaret();
}
break;
case WM_ERASEBKGND:
return 1;
case WM_GETDLGCODE:
return DLGC_WANTARROWS; /* Windows returns this value */
case WM_PAINT:
{
PAINTSTRUCT Ps;
HDC Dc;
Dc = (0 != wParam ? (HDC) wParam : BeginPaint(Wnd, &Ps));
if (GetWindowLongW(Wnd, GWL_STYLE) & SBS_SIZEGRIP)
{
IntScrollDrawSizeGrip(Wnd, Dc);
}
else if (0 != (GetWindowLongW(Wnd, GWL_STYLE) & SBS_SIZEBOX))
{
RECT Rect;
GetClientRect(Wnd, &Rect);
FillRect(Dc, &Rect, GetSysColorBrush(COLOR_SCROLLBAR));
}
else
{
IntDrawScrollBar(Wnd, Dc, SB_CTL/*, TRUE, TRUE*/);
}
if (0 == wParam)
{
EndPaint(Wnd, &Ps);
}
}
break;
case SBM_SETPOS:
return SetScrollPos(Wnd, SB_CTL, wParam, (BOOL) lParam);
case SBM_GETPOS:
return IntScrollGetScrollPos(Wnd, SB_CTL);
case SBM_SETRANGE:
{
INT OldPos = IntScrollGetScrollPos(Wnd, SB_CTL);
SetScrollRange(Wnd, SB_CTL, wParam, lParam, FALSE);
if (OldPos != IntScrollGetScrollPos(Wnd, SB_CTL))
{
return OldPos;
}
}
return 0;
case SBM_GETRANGE:
return IntScrollGetScrollRange(Wnd, SB_CTL, (LPINT) wParam, (LPINT) lParam);
case SBM_ENABLE_ARROWS:
return EnableScrollBar(Wnd, SB_CTL, wParam);
case SBM_SETRANGEREDRAW:
{
INT OldPos = IntScrollGetScrollPos(Wnd, SB_CTL);
SetScrollRange(Wnd, SB_CTL, wParam, lParam, TRUE);
if (OldPos != IntScrollGetScrollPos(Wnd, SB_CTL))
{
return OldPos;
}
}
return 0;
case SBM_SETSCROLLINFO:
return SetScrollInfo(Wnd, SB_CTL, (SCROLLINFO *) lParam, wParam);
case SBM_GETSCROLLINFO:
return NtUserGetScrollInfo(Wnd, SB_CTL, (SCROLLINFO *) lParam);
case 0x00e5:
case 0x00e7:
case 0x00e8:
case 0x00eb:
case 0x00ec:
case 0x00ed:
case 0x00ee:
case 0x00ef:
DPRINT("unknown Win32 msg %04x wp=%08x lp=%08lx\n",
Msg, wParam, lParam );
break;
default:
if (WM_USER <= Msg)
{
DPRINT("unknown msg %04x wp=%04x lp=%08lx\n", Msg, wParam, lParam);
}
return DefWindowProcW(Wnd, Msg, wParam, lParam );
}
return 0;
}
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
/* /*
@ -904,45 +1481,38 @@ GetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO lpsi)
* @implemented * @implemented
*/ */
INT STDCALL INT STDCALL
GetScrollPos(HWND hWnd, INT nBar) GetScrollPos(HWND Wnd, INT Bar)
{ {
SCROLLINFO ScrollInfo; DPRINT("Wnd=%p Bar=%d\n", Wnd, Bar);
ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_POS;
if (! NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo))
{
return 0;
}
return ScrollInfo.nPos; /* 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);
}
} }
/* /*
* @implemented * @implemented
*/ */
BOOL STDCALL BOOL STDCALL
GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos) GetScrollRange(HWND Wnd, int Bar, LPINT MinPos, LPINT MaxPos)
{ {
BOOL Result; DPRINT("Wnd=%x Bar=%d Min=%p Max=%p\n", Wnd, Bar, MinPos, MaxPos);
SCROLLINFO ScrollInfo;
/* Refer SB_CTL requests to the window */
if (NULL == lpMinPos || NULL == lpMaxPos) if (SB_CTL == Bar)
{ {
SetLastError(ERROR_INVALID_PARAMETER); return SendMessageW(Wnd, SBM_GETRANGE, (WPARAM) MinPos, (LPARAM) MaxPos);
return FALSE;
} }
else
ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_RANGE;
Result = NtUserGetScrollInfo(hWnd, nBar, &ScrollInfo);
if (Result)
{ {
*lpMinPos = ScrollInfo.nMin; return IntScrollGetScrollRange(Wnd, Bar, MinPos, MaxPos);
*lpMaxPos = ScrollInfo.nMax;
} }
return Result;
} }
/* /*

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: scrollbar.c,v 1.27 2004/02/19 21:12:09 weiden Exp $ /* $Id: scrollbar.c,v 1.28 2004/03/27 10:46:31 gvg Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -177,247 +177,244 @@ IntCalculateThumb(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi, LPS
return TRUE; return TRUE;
} }
BOOL FASTCALL static BOOL FASTCALL
IntGetScrollInfo(PWINDOW_OBJECT Window, INT nBar, LPSCROLLINFO lpsi) IntGetScrollInfo(PWINDOW_OBJECT Window, INT nBar, LPSCROLLINFO lpsi)
{ {
UINT Mask; UINT Mask;
LPSCROLLINFO psi; LPSCROLLINFO psi;
PSCROLLBARINFO Info; PSCROLLBARINFO Info;
switch(nBar) switch (nBar)
{ {
case SB_HORZ: case SB_HORZ:
Info = Window->pHScroll; Info = Window->pHScroll;
if(Info)
break; break;
/* fall through */ case SB_VERT:
case SB_VERT: Info = Window->pVScroll;
Info = Window->pVScroll;
if(Info)
break; break;
/* fall through */ case SB_CTL:
case SB_CTL: if (Window->ExtraDataSize < sizeof(SCROLLBARINFO) + sizeof(SCROLLINFO))
/* FIXME {
Send a SBM_GETSCROLLINFO message to the window. Fail if the window Info = NULL;
doesn't handle the message }
*/ else
return 0; {
Info = (PSCROLLBARINFO) Window->ExtraData;
Info = Window->wExtra; }
if(Info)
break; break;
/* fall through */ default:
default: DPRINT1("Trying to get scrollinfo for unknown scrollbar type %d", nBar);
return FALSE;
}
if (NULL == Info)
{
DPRINT1("No scrollinfo available\n");
return FALSE; return FALSE;
} }
psi = (LPSCROLLINFO)((PSCROLLBARINFO)(Info + 1)); psi = (LPSCROLLINFO)(Info + 1);
if(lpsi->fMask == SIF_ALL) if (lpsi->fMask == SIF_ALL)
Mask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; {
Mask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS;
}
else else
Mask = lpsi->fMask; {
Mask = lpsi->fMask;
}
if(Mask & SIF_PAGE) if (0 != (Mask & SIF_PAGE))
{ {
lpsi->nPage = psi->nPage; lpsi->nPage = psi->nPage;
} }
if(Mask & SIF_POS) if (0 != (Mask & SIF_POS))
{ {
lpsi->nPos = psi->nPos; lpsi->nPos = psi->nPos;
} }
if(Mask & SIF_RANGE) if (0 != (Mask & SIF_RANGE))
{ {
lpsi->nMin = psi->nMin; lpsi->nMin = psi->nMin;
lpsi->nMax = psi->nMax; lpsi->nMax = psi->nMax;
} }
if(Mask & SIF_TRACKPOS) if (0 != (Mask & SIF_TRACKPOS))
{ {
lpsi->nTrackPos = psi->nTrackPos; lpsi->nTrackPos = psi->nTrackPos;
} }
return TRUE; return TRUE;
} }
DWORD FASTCALL static DWORD FASTCALL
IntSetScrollInfo(PWINDOW_OBJECT Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) IntSetScrollInfo(PWINDOW_OBJECT Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
{ {
/* /*
* Update the scrollbar state and set action flags according to * Update the scrollbar state and set action flags according to
* what has to be done graphics wise. * what has to be done graphics wise.
*/ */
LPSCROLLINFO Info; LPSCROLLINFO Info;
PSCROLLBARINFO psbi; PSCROLLBARINFO psbi;
/* UINT new_flags;*/ /* UINT new_flags;*/
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 */
if (lpsi->cbSize != sizeof(SCROLLINFO) && if (lpsi->cbSize != sizeof(SCROLLINFO) &&
lpsi->cbSize != (sizeof(SCROLLINFO) - sizeof(lpsi->nTrackPos))) lpsi->cbSize != (sizeof(SCROLLINFO) - sizeof(lpsi->nTrackPos)))
{ {
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0; return 0;
} }
if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL))
{ {
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0; return 0;
} }
switch(nBar) switch (nBar)
{ {
case SB_HORZ: case SB_HORZ:
if (Window->pHScroll == NULL) if (NULL == Window->pHScroll)
{ {
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0; return 0;
} }
psbi = Window->pHScroll; psbi = Window->pHScroll;
Info = (LPSCROLLINFO)(Window->pHScroll + 1); break;
break;
case SB_VERT: case SB_VERT:
if (Window->pVScroll == NULL) if (NULL == Window->pVScroll)
{ {
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0; return 0;
} }
psbi = Window->pVScroll; psbi = Window->pVScroll;
Info = (LPSCROLLINFO)(Window->pVScroll + 1); break;
break;
case SB_CTL: case SB_CTL:
UNIMPLEMENTED; if (Window->ExtraDataSize < sizeof(SCROLLBARINFO) + sizeof(SCROLLINFO))
break; {
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0;
}
psbi = (PSCROLLBARINFO) Window->ExtraData;
break;
default: default:
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0; return 0;
} }
/* Set the page size */ Info = (LPSCROLLINFO)(psbi + 1);
if (lpsi->fMask & SIF_PAGE)
{ /* Set the page size */
if (0 != (lpsi->fMask & SIF_PAGE))
{
if (Info->nPage != lpsi->nPage) if (Info->nPage != lpsi->nPage)
{ {
Info->nPage = lpsi->nPage; Info->nPage = lpsi->nPage;
#if 0 bChangeParams = TRUE;
*Action |= SA_SSI_REFRESH; }
#endif }
bChangeParams = TRUE;
}
}
/* Set the scroll pos */ /* Set the scroll pos */
if (lpsi->fMask & SIF_POS) if (0 != (lpsi->fMask & SIF_POS))
{ {
if (Info->nPos != lpsi->nPos) if (Info->nPos != lpsi->nPos)
{ {
Info->nPos = lpsi->nPos; Info->nPos = lpsi->nPos;
#if 0 }
*Action |= SA_SSI_REFRESH; }
#endif
}
}
/* Set the scroll range */ /* Set the scroll range */
if (lpsi->fMask & SIF_RANGE) if (0 != (lpsi->fMask & SIF_RANGE))
{ {
/* Invalid range -> range is set to (0,0) */ /* Invalid range -> range is set to (0,0) */
if (lpsi->nMin > lpsi->nMax || if (lpsi->nMin > lpsi->nMax ||
(UINT)(lpsi->nMax - lpsi->nMin) >= 0x80000000) 0x80000000 <= (UINT)(lpsi->nMax - lpsi->nMin))
{ {
Info->nMin = 0; Info->nMin = 0;
Info->nMax = 0; Info->nMax = 0;
bChangeParams = TRUE; bChangeParams = TRUE;
} }
else else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax)
{ {
if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax) Info->nMin = lpsi->nMin;
{ Info->nMax = lpsi->nMax;
#if 0 bChangeParams = TRUE;
*Action |= SA_SSI_REFRESH; }
#endif }
Info->nMin = lpsi->nMin;
Info->nMax = lpsi->nMax;
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; Info->nPage = 0;
} }
else if (Info->nPage > Info->nMax - Info->nMin + 1) else if (Info->nMax - Info->nMin + 1 < Info->nPage)
{ {
Info->nPage = Info->nMax - Info->nMin + 1; 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; Info->nPos = Info->nMin;
} }
else if (Info->nPos > Info->nMax - max(Info->nPage - 1, 0)) else if (Info->nPos > Info->nMax - max(Info->nPage - 1, 0))
{ {
Info->nPos = Info->nMax - max(Info->nPage - 1, 0); Info->nPos = Info->nMax - max(Info->nPage - 1, 0);
} }
/* /*
* Don't change the scrollbar state if SetScrollInfo is just called * Don't change the scrollbar state if SetScrollInfo is just called
* with SIF_DISABLENOSCROLL * with SIF_DISABLENOSCROLL
*/ */
if (!(lpsi->fMask & SIF_ALL)) if (0 == (lpsi->fMask & SIF_ALL))
{ {
return Info->nPos; return Info->nPos;
} }
/* Check if the scrollbar should be hidden or disabled */ /* Check if the scrollbar should be hidden or disabled */
if (lpsi->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL)) if (0 != (lpsi->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL)))
{ {
/* new_flags = Info->flags;*/
if (Info->nMin >= Info->nMax - max(Info->nPage - 1, 0)) if (Info->nMin >= Info->nMax - max(Info->nPage - 1, 0))
{ {
/* Hide or disable scroll-bar */ /* Hide or disable scroll-bar */
if (lpsi->fMask & SIF_DISABLENOSCROLL) if (0 != (lpsi->fMask & SIF_DISABLENOSCROLL))
{ {
/* new_flags = ESB_DISABLE_BOTH;*/ /* new_flags = ESB_DISABLE_BOTH;*/
#if 0 }
*Action |= SA_SSI_REFRESH; else if ((nBar != SB_CTL) && bChangeParams)
#endif {
} NtUserShowScrollBar(Window->Self, nBar, FALSE);
else if ((nBar != SB_CTL) && bChangeParams) return Info->nPos;
{ }
NtUserShowScrollBar(Window->Self, nBar, FALSE); }
return Info->nPos;
}
}
else /* Show and enable scroll-bar */ else /* Show and enable scroll-bar */
{ {
/* new_flags = 0;*/ /* new_flags = 0;*/
if ((nBar != SB_CTL) && bChangeParams) if ((nBar != SB_CTL) && bChangeParams)
NtUserShowScrollBar(Window->Self, nBar, TRUE); {
} NtUserShowScrollBar(Window->Self, nBar, TRUE);
}
}
#if 0 #if 0
if (infoPtr->flags != new_flags) /* check arrow flags */ if (infoPtr->flags != new_flags) /* check arrow flags */
{ {
infoPtr->flags = new_flags; infoPtr->flags = new_flags;
*Action |= SA_SSI_REPAINT_ARROWS; *Action |= SA_SSI_REPAINT_ARROWS;
} }
#endif #endif
} }
if (bRedraw) if (bRedraw)
{ {
RECT UpdateRect = psbi->rcScrollBar; RECT UpdateRect = psbi->rcScrollBar;
UpdateRect.left -= Window->ClientRect.left - Window->WindowRect.left; UpdateRect.left -= Window->ClientRect.left - Window->WindowRect.left;
UpdateRect.right -= Window->ClientRect.left - Window->WindowRect.left; UpdateRect.right -= Window->ClientRect.left - Window->WindowRect.left;
UpdateRect.top -= Window->ClientRect.top - Window->WindowRect.top; UpdateRect.top -= Window->ClientRect.top - Window->WindowRect.top;
UpdateRect.bottom -= Window->ClientRect.top - Window->WindowRect.top; UpdateRect.bottom -= Window->ClientRect.top - Window->WindowRect.top;
IntRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); IntRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
} }
/* Return current position */ /* Return current position */
return Info->nPos; return Info->nPos;
@ -431,44 +428,38 @@ IntGetScrollBarInfo(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi)
LPSCROLLINFO psi; LPSCROLLINFO psi;
switch(idObject) switch(idObject)
{ {
case OBJID_HSCROLL: case OBJID_HSCROLL:
if(Window->pHScroll)
{
Bar = SB_HORZ; Bar = SB_HORZ;
sbi = Window->pHScroll; sbi = Window->pHScroll;
break; break;
} case OBJID_VSCROLL:
/* fall through */
case OBJID_VSCROLL:
if(Window->pVScroll)
{
Bar = SB_VERT; Bar = SB_VERT;
sbi = Window->pVScroll; sbi = Window->pVScroll;
break; break;
} case OBJID_CLIENT:
/* fall through */
case OBJID_CLIENT:
/* FIXME
Send a SBM_GETSCROLLBARINFO message if Window is not a system scrollbar.
If the window doesn't handle the message return FALSE.
*/
return FALSE;
if(Window->wExtra)
{
Bar = SB_CTL; Bar = SB_CTL;
sbi = Window->wExtra; if (Window->ExtraDataSize < sizeof(SCROLLBARINFO) + sizeof(SCROLLINFO))
{
sbi = NULL;
}
else
{
sbi = (PSCROLLBARINFO) Window->ExtraData;
}
break; break;
} default:
/* fall through */ SetLastWin32Error(ERROR_INVALID_PARAMETER);
default: return FALSE;
}
if (NULL == sbi)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
psi = (LPSCROLLINFO)((PSCROLLBARINFO)(sbi + 1)); psi = (LPSCROLLINFO)(sbi + 1);
IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar)); IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar));
IntCalculateThumb(Window, Bar, sbi, psi); IntCalculateThumb(Window, Bar, sbi, psi);