Newer
Older
* Copyright 1993 Martin Ayotte
* Copyright 1994, 1996 Alexandre Julliard
#include "wine/winuser16.h"
static HBITMAP32 hUpArrow = 0;
static HBITMAP32 hDnArrow = 0;
static HBITMAP32 hLfArrow = 0;
static HBITMAP32 hRgArrow = 0;
static HBITMAP32 hUpArrowD = 0;
static HBITMAP32 hDnArrowD = 0;
static HBITMAP32 hLfArrowD = 0;
static HBITMAP32 hRgArrowD = 0;
static HBITMAP32 hUpArrowI = 0;
static HBITMAP32 hDnArrowI = 0;
static HBITMAP32 hLfArrowI = 0;
static HBITMAP32 hRgArrowI = 0;
#define TOP_ARROW(flags,pressed) \
(((flags)&ESB_DISABLE_UP) ? hUpArrowI : ((pressed) ? hUpArrowD:hUpArrow))
#define BOTTOM_ARROW(flags,pressed) \
(((flags)&ESB_DISABLE_DOWN) ? hDnArrowI : ((pressed) ? hDnArrowD:hDnArrow))
#define LEFT_ARROW(flags,pressed) \
(((flags)&ESB_DISABLE_LEFT) ? hLfArrowI : ((pressed) ? hLfArrowD:hLfArrow))
#define RIGHT_ARROW(flags,pressed) \
(((flags)&ESB_DISABLE_RIGHT) ? hRgArrowI : ((pressed) ? hRgArrowD:hRgArrow))
/* Minimum size of the rectangle between the arrows */
#define SCROLL_MIN_RECT 4
/* Overlap between arrows and thumb */
#define SCROLL_ARROW_THUMB_OVERLAP 1
/* Delay (in ms) before first repetition when holding the button down */
#define SCROLL_FIRST_DELAY 200
/* Delay (in ms) between scroll repetitions */
/* Scroll timer id */
#define SCROLL_TIMER 0
/* Scroll-bar hit testing */
enum SCROLL_HITTEST
{
SCROLL_NOWHERE, /* Outside the scroll bar */
SCROLL_TOP_ARROW, /* Top or left arrow */
SCROLL_TOP_RECT, /* Rectangle between the top arrow and the thumb */
SCROLL_THUMB, /* Thumb rectangle */
SCROLL_BOTTOM_RECT, /* Rectangle between the thumb and the bottom arrow */
SCROLL_BOTTOM_ARROW /* Bottom or right arrow */
};
/* What to do after SCROLL_SetScrollInfo() */
#define SA_SSI_HIDE 0x0001
#define SA_SSI_SHOW 0x0002
#define SA_SSI_REFRESH 0x0004
#define SA_SSI_REPAINT_ARROWS 0x0008
static HWND32 SCROLL_TrackingWin = 0;
static INT32 SCROLL_TrackingBar = 0;
static INT32 SCROLL_TrackingPos = 0;
static INT32 SCROLL_TrackingVal = 0;
/* Hit test code of the last button-down event */
static enum SCROLL_HITTEST SCROLL_trackHitTest;
static BOOL32 SCROLL_trackVertical;
/* Is the moving thumb being displayed? */
/* Local functions */
static BOOL32 SCROLL_ShowScrollBar( HWND32 hwnd, INT32 nBar,
BOOL32 fShowH, BOOL32 fShowV );
static INT32 SCROLL_SetScrollInfo( HWND32 hwnd, INT32 nBar,
const SCROLLINFO *info, INT32 *action );
/***********************************************************************
hUpArrow = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_UPARROW) );
hDnArrow = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_DNARROW) );
hLfArrow = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_LFARROW) );
hRgArrow = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_RGARROW) );
hUpArrowD = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_UPARROWD) );
hDnArrowD = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_DNARROWD) );
hLfArrowD = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_LFARROWD) );
hRgArrowD = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_RGARROWD) );
hUpArrowI = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_UPARROWI) );
hDnArrowI = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_DNARROWI) );
hLfArrowI = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_LFARROWI) );
hRgArrowI = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_RGARROWI) );
/***********************************************************************
static SCROLLBAR_INFO *SCROLL_GetPtrScrollInfo( WND* wndPtr, INT32 nBar )
case SB_HORZ: infoPtr = (SCROLLBAR_INFO *)wndPtr->pHScroll; break;
case SB_VERT: infoPtr = (SCROLLBAR_INFO *)wndPtr->pVScroll; break;
case SB_CTL: infoPtr = (SCROLLBAR_INFO *)wndPtr->wExtra; break;
if (!infoPtr) /* Create the info structure if needed */
if ((infoPtr = HeapAlloc( SystemHeap, 0, sizeof(SCROLLBAR_INFO) )))
infoPtr->MinVal = infoPtr->CurVal = infoPtr->Page = 0;
infoPtr->MaxVal = 100;
infoPtr->flags = ESB_ENABLE_BOTH;
if (nBar == SB_HORZ) wndPtr->pHScroll = infoPtr;
else wndPtr->pVScroll = infoPtr;
/***********************************************************************
* SCROLL_GetScrollInfo
*/
static SCROLLBAR_INFO *SCROLL_GetScrollInfo( HWND32 hwnd, INT32 nBar )
{
WND *wndPtr = WIN_FindWndPtr( hwnd );
return SCROLL_GetPtrScrollInfo( wndPtr, nBar );
}
/***********************************************************************
* SCROLL_GetScrollBarRect
*
* 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 BOOL32 SCROLL_GetScrollBarRect( HWND32 hwnd, INT32 nBar, RECT32 *lprect,
INT32 *arrowSize, INT32 *thumbSize,
INT32 *thumbPos )
WND *wndPtr = WIN_FindWndPtr( hwnd );
switch(nBar)
{
case SB_HORZ:
lprect->left = wndPtr->rectClient.left - wndPtr->rectWindow.left;
lprect->top = wndPtr->rectClient.bottom - wndPtr->rectWindow.top;
lprect->right = wndPtr->rectClient.right - wndPtr->rectWindow.left;
lprect->bottom = lprect->top + SYSMETRICS_CYHSCROLL;
if(wndPtr->dwStyle & WS_BORDER) {
lprect->left--;
lprect->right++;
} else if(wndPtr->dwStyle & WS_VSCROLL)
lprect->right++;
vertical = FALSE;
break;
case SB_VERT:
lprect->left = wndPtr->rectClient.right - wndPtr->rectWindow.left;
lprect->top = wndPtr->rectClient.top - wndPtr->rectWindow.top;
lprect->right = lprect->left + SYSMETRICS_CXVSCROLL;
lprect->bottom = wndPtr->rectClient.bottom - wndPtr->rectWindow.top;
if(wndPtr->dwStyle & WS_BORDER) {
lprect->top--;
lprect->bottom++;
} else if(wndPtr->dwStyle & WS_HSCROLL)
lprect->bottom++;
vertical = ((wndPtr->dwStyle & SBS_VERT) != 0);
break;
}
if (vertical) pixels = lprect->bottom - lprect->top;
else pixels = lprect->right - lprect->left;
if (pixels <= 2*SYSMETRICS_CXVSCROLL + SCROLL_MIN_RECT)
if (pixels > SCROLL_MIN_RECT)
*arrowSize = (pixels - SCROLL_MIN_RECT) / 2;
else
*arrowSize = 0;
*thumbPos = *thumbSize = 0;
SCROLLBAR_INFO *info = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
pixels -= (2 * (SYSMETRICS_CXVSCROLL - SCROLL_ARROW_THUMB_OVERLAP));
if (info->Page)
{
*thumbSize = pixels * info->Page / (info->MaxVal-info->MinVal+1);
if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
}
else *thumbSize = SYSMETRICS_CXVSCROLL;
((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
{
/* Rectangle too small or scrollbar disabled -> no thumb */
*thumbPos = *thumbSize = 0;
}
{
INT32 max = info->MaxVal - MAX( info->Page-1, 0 );
if (info->MinVal >= max)
*thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
*thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
+ pixels * (info->CurVal-info->MinVal) / (max - info->MinVal);
/***********************************************************************
* SCROLL_GetThumbVal
*
* Compute the current scroll position based on the thumb position in pixels
* from the top of the scroll-bar.
*/
static UINT32 SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT32 *rect,
BOOL32 vertical, INT32 pos )
INT32 thumbSize;
INT32 pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
if ((pixels -= 2*(SYSMETRICS_CXVSCROLL - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
return infoPtr->MinVal;
if (infoPtr->Page)
{
thumbSize = pixels * infoPtr->Page/(infoPtr->MaxVal-infoPtr->MinVal+1);
if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB;
}
else thumbSize = SYSMETRICS_CXVSCROLL;
if ((pixels -= thumbSize) <= 0) return infoPtr->MinVal;
pos = MAX( 0, pos - (SYSMETRICS_CXVSCROLL - SCROLL_ARROW_THUMB_OVERLAP) );
if (!infoPtr->Page) pos *= infoPtr->MaxVal - infoPtr->MinVal;
else pos *= infoPtr->MaxVal - infoPtr->MinVal - infoPtr->Page + 1;
return infoPtr->MinVal + ((pos + pixels / 2) / pixels);
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
/***********************************************************************
* SCROLL_PtInRectEx
*/
static BOOL32 SCROLL_PtInRectEx( LPRECT32 lpRect, POINT32 pt, BOOL32 vertical )
{
RECT32 rect = *lpRect;
if (vertical)
{
rect.left -= lpRect->right - lpRect->left;
rect.right += lpRect->right - lpRect->left;
}
else
{
rect.top -= lpRect->bottom - lpRect->top;
rect.bottom += lpRect->bottom - lpRect->top;
}
return PtInRect32( &rect, pt );
}
/***********************************************************************
* SCROLL_ClipPos
*/
static POINT32 SCROLL_ClipPos( LPRECT32 lpRect, POINT32 pt )
{
if( pt.x < lpRect->left )
pt.x = lpRect->left;
else
if( pt.x > lpRect->right )
pt.x = lpRect->right;
if( pt.y < lpRect->top )
pt.y = lpRect->top;
else
if( pt.y > lpRect->bottom )
pt.y = lpRect->bottom;
return pt;
}
/***********************************************************************
* SCROLL_HitTest
*
* Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
*/
static enum SCROLL_HITTEST SCROLL_HitTest( HWND32 hwnd, INT32 nBar,
POINT32 pt, BOOL32 bDragging )
INT32 arrowSize, thumbSize, thumbPos;
RECT32 rect;
BOOL32 vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
&arrowSize, &thumbSize, &thumbPos );
if ( (bDragging && !SCROLL_PtInRectEx( &rect, pt, vertical )) ||
(!PtInRect32( &rect, pt )) ) return SCROLL_NOWHERE;
if (pt.y < rect.top + arrowSize) return SCROLL_TOP_ARROW;
if (pt.y >= rect.bottom - arrowSize) return SCROLL_BOTTOM_ARROW;
if (!thumbPos) return SCROLL_TOP_RECT;
pt.y -= rect.top;
if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
if (pt.x < rect.left + arrowSize) return SCROLL_TOP_ARROW;
if (pt.x >= rect.right - arrowSize) return SCROLL_BOTTOM_ARROW;
if (!thumbPos) return SCROLL_TOP_RECT;
pt.x -= rect.left;
if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
return SCROLL_THUMB;
/***********************************************************************
* SCROLL_DrawArrows
*
* Draw the scroll bar arrows.
*/
static void SCROLL_DrawArrows( HDC32 hdc, SCROLLBAR_INFO *infoPtr,
RECT32 *rect, INT32 arrowSize, BOOL32 vertical,
BOOL32 top_pressed, BOOL32 bottom_pressed )
HBITMAP32 hbmpPrev = SelectObject32( hdcMem, vertical ?
TOP_ARROW(infoPtr->flags, top_pressed)
: LEFT_ARROW(infoPtr->flags, top_pressed));
vertical ? rect->right-rect->left : arrowSize,
vertical ? arrowSize : rect->bottom-rect->top,
SelectObject32( hdcMem, vertical ?
BOTTOM_ARROW( infoPtr->flags, bottom_pressed )
: RIGHT_ARROW( infoPtr->flags, bottom_pressed ) );
StretchBlt32( hdc, rect->left, rect->bottom - arrowSize,
rect->right - rect->left, arrowSize,
StretchBlt32( hdc, rect->right - arrowSize, rect->top,
arrowSize, rect->bottom - rect->top,
/***********************************************************************
* SCROLL_DrawMovingThumb
*
* Draw the moving thumb rectangle.
*/
static void SCROLL_DrawMovingThumb( HDC32 hdc, RECT32 *rect, BOOL32 vertical,
INT32 arrowSize, INT32 thumbSize )
if (r.top < rect->top + arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
r.top = rect->top + arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
if (r.top + thumbSize >
rect->bottom - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP))
r.top = rect->bottom - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
- thumbSize;
r.bottom = r.top + thumbSize;
if (r.left < rect->left + arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
r.left = rect->left + arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
if (r.left + thumbSize >
rect->right - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP))
r.left = rect->right - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
- thumbSize;
r.right = r.left + thumbSize;
DrawFocusRect32( hdc, &r );
SCROLL_MovingThumb = !SCROLL_MovingThumb;
/***********************************************************************
* SCROLL_DrawInterior
*
* Draw the scroll bar interior (everything except the arrows).
*/
static void SCROLL_DrawInterior( HWND32 hwnd, HDC32 hdc, INT32 nBar,
RECT32 *rect, INT32 arrowSize,
INT32 thumbSize, INT32 thumbPos,
UINT32 flags, BOOL32 vertical,
BOOL32 top_selected, BOOL32 bottom_selected )
SelectObject32( hdc, GetSysColorPen32(COLOR_WINDOWFRAME) );
if ((flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)
{
/* This ought to be the color of the parent window */
SelectObject32( hdc, GetSysColorBrush32(COLOR_WINDOW) );
{
if (nBar == SB_CTL) /* Only scrollbar controls send WM_CTLCOLOR */
{
HBRUSH32 hbrush = SendMessage32A(GetParent32(hwnd),
WM_CTLCOLORSCROLLBAR, hdc, hwnd );
else SelectObject32( hdc, GetSysColorBrush32(COLOR_SCROLLBAR) );
/* Calculate the scroll rectangle */
r = *rect;
if (vertical)
{
r.top += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
r.bottom -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
r.left += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
r.right -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
Rectangle32( hdc, r.left, r.top, r.right, r.bottom );
/* Draw the scroll rectangles and thumb */
if (!thumbPos) /* No thumb to draw */
{
PatBlt32( hdc, r.left+1, r.top+1, r.right - r.left - 2,
r.bottom - r.top - 2, PATCOPY );
PatBlt32( hdc, r.left + 1, r.top + 1,
r.right - r.left - 2,
thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - 1,
r.top += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
PatBlt32( hdc, r.left + 1, r.top + thumbSize,
thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - 1,
r.bottom - r.top - 2,
top_selected ? 0x0f0000 : PATCOPY );
r.left += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
PatBlt32( hdc, r.left + thumbSize, r.top + 1,
r.right - r.left - thumbSize - 1,
r.bottom - r.top - 2,
bottom_selected ? 0x0f0000 : PATCOPY );
SelectObject32( hdc, GetSysColorBrush32(COLOR_BTNFACE) );
Rectangle32( hdc, r.left, r.top, r.right, r.bottom );
r.top++, r.left++;
DrawEdge32( hdc, &r, EDGE_RAISED, BF_RECT );
if (SCROLL_MovingThumb &&
(SCROLL_TrackingWin == hwnd) &&
(SCROLL_TrackingBar == nBar))
{
SCROLL_DrawMovingThumb( hdc, rect, vertical, arrowSize, thumbSize );
SCROLL_MovingThumb = TRUE;
}
/***********************************************************************
* SCROLL_DrawScrollBar
*
* Redraw the whole scrollbar.
*/
void SCROLL_DrawScrollBar( HWND32 hwnd, HDC32 hdc, INT32 nBar,
BOOL32 arrows, BOOL32 interior )
INT32 arrowSize, thumbSize, thumbPos;
RECT32 rect;
BOOL32 vertical;
SCROLLBAR_INFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
if (!wndPtr || !infoPtr ||
((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) ||
((nBar == SB_HORZ) && !(wndPtr->dwStyle & WS_HSCROLL))) return;
if (!WIN_IsWindowDrawable( wndPtr, FALSE )) return;
vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
if (arrows && arrowSize)
{
if( vertical == SCROLL_trackVertical && GetCapture32() == hwnd )
SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
(SCROLL_trackHitTest == SCROLL_TOP_ARROW),
(SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW) );
else
SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
FALSE, FALSE );
}
if( interior )
SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
/***********************************************************************
* SCROLL_RefreshScrollBar
*
* Repaint the scroll bar interior after a SetScrollRange() or
* SetScrollPos() call.
*/
static void SCROLL_RefreshScrollBar( HWND32 hwnd, INT32 nBar,
BOOL32 arrows, BOOL32 interior )
HDC32 hdc = GetDCEx32( hwnd, 0,
DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW) );
SCROLL_DrawScrollBar( hwnd, hdc, nBar, arrows, interior );
/***********************************************************************
* SCROLL_HandleKbdEvent
*
* Handle a keyboard event (only for SB_CTL scrollbars).
static void SCROLL_HandleKbdEvent( HWND32 hwnd, WPARAM32 wParam )
switch(wParam)
{
case VK_PRIOR: msg = SB_PAGEUP; break;
case VK_NEXT: msg = SB_PAGEDOWN; break;
case VK_HOME: msg = SB_TOP; break;
case VK_END: msg = SB_BOTTOM; break;
case VK_UP: msg = SB_LINEUP; break;
case VK_DOWN: msg = SB_LINEDOWN; break;
default:
return;
}
(wndPtr->dwStyle & SBS_VERT) ? WM_VSCROLL : WM_HSCROLL,
msg, hwnd );
/***********************************************************************
* SCROLL_HandleScrollEvent
*
* Handle a mouse or timer event for the scrollbar.
* 'pt' is the location of the mouse event in client (for SB_CTL) or
* windows coordinates.
void SCROLL_HandleScrollEvent( HWND32 hwnd, INT32 nBar, UINT32 msg, POINT32 pt)
/* Position in the scroll-bar of the last button-down event. */
/* Position in the scroll-bar of the last mouse event. */
HWND32 hwndOwner, hwndCtl;
BOOL32 vertical;
INT32 arrowSize, thumbSize, thumbPos;
RECT32 rect;
HDC32 hdc;
SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
if ((SCROLL_trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN))
return;
hdc = GetDCEx32( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
hwndOwner = (nBar == SB_CTL) ? GetParent32(hwnd) : hwnd;
hwndCtl = (nBar == SB_CTL) ? hwnd : 0;
switch(msg)
{
case WM_LBUTTONDOWN: /* Initialise mouse tracking */
SCROLL_trackVertical = vertical;
SCROLL_trackHitTest = hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
lastClickPos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
lastMousePos = lastClickPos;
trackThumbPos = thumbPos;
prevPt = pt;
hittest = SCROLL_HitTest( hwnd, nBar, pt, TRUE );
prevPt = pt;
break;
case WM_LBUTTONUP:
hittest = SCROLL_NOWHERE;
ReleaseCapture();
break;
case WM_SYSTIMER:
pt = prevPt;
hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
break;
default:
return; /* Should never happen */
}
TRACE(scroll, "Event: hwnd=%04x bar=%d msg=%x pt=%ld,%ld hit=%d\n",
switch(SCROLL_trackHitTest)
{
case SCROLL_NOWHERE: /* No tracking in progress */
break;
case SCROLL_TOP_ARROW:
SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
(hittest == SCROLL_trackHitTest), FALSE );
if (hittest == SCROLL_trackHitTest)
{
if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SB_LINEUP, hwndCtl );
SetSystemTimer32( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
(TIMERPROC32)0 );
SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
thumbPos, infoPtr->flags, vertical,
(hittest == SCROLL_trackHitTest), FALSE );
if (hittest == SCROLL_trackHitTest)
{
if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SB_PAGEUP, hwndCtl );
SetSystemTimer32( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
(TIMERPROC32)0 );
break;
case SCROLL_THUMB:
if (msg == WM_LBUTTONDOWN)
SCROLL_TrackingWin = hwnd;
SCROLL_TrackingBar = nBar;
SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos;
SCROLL_DrawMovingThumb(hdc, &rect, vertical, arrowSize, thumbSize);
SCROLL_TrackingWin = 0;
SCROLL_MovingThumb = FALSE;
SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
thumbPos, infoPtr->flags, vertical,
FALSE, FALSE );
if (!SCROLL_PtInRectEx( &rect, pt, vertical )) pos = lastClickPos;
else
{
pt = SCROLL_ClipPos( &rect, pt );
pos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
}
SCROLL_DrawMovingThumb( hdc, &rect, vertical,
arrowSize, thumbSize );
SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos;
SCROLL_TrackingVal = SCROLL_GetThumbVal( infoPtr, &rect,
vertical,
SCROLL_TrackingPos );
SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal),
hwndCtl );
SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
thumbPos, infoPtr->flags, vertical,
FALSE, (hittest == SCROLL_trackHitTest) );
if (hittest == SCROLL_trackHitTest)
{
if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SB_PAGEDOWN, hwndCtl );
SetSystemTimer32( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
(TIMERPROC32)0 );
break;
case SCROLL_BOTTOM_ARROW:
SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
FALSE, (hittest == SCROLL_trackHitTest) );
if (hittest == SCROLL_trackHitTest)
{
if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SB_LINEDOWN, hwndCtl );
SetSystemTimer32( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
(TIMERPROC32)0 );
hittest = SCROLL_trackHitTest;
SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */
if (hittest == SCROLL_THUMB)
UINT32 val = SCROLL_GetThumbVal( infoPtr, &rect, vertical,
SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
/***********************************************************************
* ScrollBarWndProc
*/
LRESULT WINAPI ScrollBarWndProc( HWND32 hwnd, UINT32 message, WPARAM32 wParam,
LPARAM lParam )
CREATESTRUCT32A *lpCreat = (CREATESTRUCT32A *)lParam;
FIXME(scroll, "Unimplemented style SBS_SIZEBOX.\n" );
return 0;
}
if (lpCreat->style & SBS_VERT)
{
if (lpCreat->style & SBS_LEFTALIGN)
MoveWindow32( hwnd, lpCreat->x, lpCreat->y,
SYSMETRICS_CXVSCROLL+1, lpCreat->cy, FALSE );
MoveWindow32( hwnd,
lpCreat->x+lpCreat->cx-SYSMETRICS_CXVSCROLL-1,
lpCreat->y,
SYSMETRICS_CXVSCROLL+1, lpCreat->cy, FALSE );
}
else /* SBS_HORZ */
{
if (lpCreat->style & SBS_TOPALIGN)
MoveWindow32( hwnd, lpCreat->x, lpCreat->y,
lpCreat->cx, SYSMETRICS_CYHSCROLL+1, FALSE );
MoveWindow32( hwnd,
lpCreat->x,
lpCreat->y+lpCreat->cy-SYSMETRICS_CYHSCROLL-1,
lpCreat->cx, SYSMETRICS_CYHSCROLL+1, FALSE );
TRACE(scroll, "ScrollBar creation, hwnd=%04x\n", hwnd );
return 0;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
case WM_SYSTIMER:
{
POINT32 pt;
CONV_POINT16TO32( (POINT16 *)&lParam, &pt );
SCROLL_HandleScrollEvent( hwnd, SB_CTL, message, pt );
}
break;
case WM_KEYDOWN:
SCROLL_HandleKbdEvent( hwnd, wParam );
break;
case WM_ERASEBKGND:
return 1;
case WM_GETDLGCODE:
return DLGC_WANTARROWS; /* Windows returns this value */
PAINTSTRUCT32 ps;
HDC32 hdc = BeginPaint32( hwnd, &ps );
SCROLL_DrawScrollBar( hwnd, hdc, SB_CTL, TRUE, TRUE );
case SBM_SETPOS16:
case SBM_SETPOS32:
return SetScrollPos32( hwnd, SB_CTL, wParam, (BOOL32)lParam );
case SBM_GETPOS16:
case SBM_GETPOS32:
return GetScrollPos32( hwnd, SB_CTL );
case SBM_SETRANGE16:
SetScrollRange32( hwnd, SB_CTL, LOWORD(lParam), HIWORD(lParam),
wParam /* FIXME: Is this correct? */ );
case SBM_SETRANGE32:
SetScrollRange32( hwnd, SB_CTL, wParam, lParam, FALSE );
return 0; /* FIXME: return previous position */
FIXME(scroll, "don't know how to handle SBM_GETRANGE16 (wp=%04x,lp=%08lx)\n", wParam, lParam );
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
return 0;
case SBM_GETRANGE32:
GetScrollRange32( hwnd, SB_CTL, (LPINT32)wParam, (LPINT32)lParam );
return 0;
case SBM_ENABLE_ARROWS16:
case SBM_ENABLE_ARROWS32:
return EnableScrollBar32( hwnd, SB_CTL, wParam );
case SBM_SETRANGEREDRAW32:
SetScrollRange32( hwnd, SB_CTL, wParam, lParam, TRUE );
return 0; /* FIXME: return previous position */
case SBM_SETSCROLLINFO32:
return SetScrollInfo32( hwnd, SB_CTL, (SCROLLINFO *)lParam, wParam );
case SBM_GETSCROLLINFO32:
return GetScrollInfo32( hwnd, SB_CTL, (SCROLLINFO *)lParam );
case 0x00e5:
case 0x00e7:
case 0x00e8:
case 0x00eb:
case 0x00ec:
case 0x00ed:
case 0x00ee:
case 0x00ef:
ERR(scroll, "unknown Win32 msg %04x wp=%08x lp=%08lx\n",
message, wParam, lParam );
WARN(scroll, "unknown msg %04x wp=%04x lp=%08lx\n",
message, wParam, lParam );
return DefWindowProc32A( hwnd, message, wParam, lParam );
/*************************************************************************
INT16 WINAPI SetScrollInfo16( HWND16 hwnd, INT16 nBar, const SCROLLINFO *info,
BOOL16 bRedraw )
{
return (INT16)SetScrollInfo32( hwnd, nBar, info, bRedraw );
}
/*************************************************************************
* SetScrollInfo32 can be used to set the position, upper bound,
* lower bound, and page size of a scrollbar control.
*
* RETURNS
* Scrollbar position
*
* NOTE
* For 100 lines of text to be displayed in a window of 25 lines,
* one would for instance use info->nMin=0, info->nMax=75
* (corresponding to the 76 different positions of the window on