Small fix.
[wine/multimedia.git] / controls / scroll.c
blob0cade01a66c61e00d1eef038f0c74e1f24e72f45
1 /*
2 * Scrollbar control
4 * Copyright 1993 Martin Ayotte
5 * Copyright 1994, 1996 Alexandre Julliard
6 */
8 #include <stdlib.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include "windows.h"
12 #include "sysmetrics.h"
13 #include "scroll.h"
14 #include "graphics.h"
15 #include "heap.h"
16 #include "win.h"
17 #include "debug.h"
20 static HBITMAP32 hUpArrow = 0;
21 static HBITMAP32 hDnArrow = 0;
22 static HBITMAP32 hLfArrow = 0;
23 static HBITMAP32 hRgArrow = 0;
24 static HBITMAP32 hUpArrowD = 0;
25 static HBITMAP32 hDnArrowD = 0;
26 static HBITMAP32 hLfArrowD = 0;
27 static HBITMAP32 hRgArrowD = 0;
28 static HBITMAP32 hUpArrowI = 0;
29 static HBITMAP32 hDnArrowI = 0;
30 static HBITMAP32 hLfArrowI = 0;
31 static HBITMAP32 hRgArrowI = 0;
33 #define TOP_ARROW(flags,pressed) \
34 (((flags)&ESB_DISABLE_UP) ? hUpArrowI : ((pressed) ? hUpArrowD:hUpArrow))
35 #define BOTTOM_ARROW(flags,pressed) \
36 (((flags)&ESB_DISABLE_DOWN) ? hDnArrowI : ((pressed) ? hDnArrowD:hDnArrow))
37 #define LEFT_ARROW(flags,pressed) \
38 (((flags)&ESB_DISABLE_LEFT) ? hLfArrowI : ((pressed) ? hLfArrowD:hLfArrow))
39 #define RIGHT_ARROW(flags,pressed) \
40 (((flags)&ESB_DISABLE_RIGHT) ? hRgArrowI : ((pressed) ? hRgArrowD:hRgArrow))
43 /* Minimum size of the rectangle between the arrows */
44 #define SCROLL_MIN_RECT 4
46 /* Minimum size of the thumb in pixels */
47 #define SCROLL_MIN_THUMB 6
49 /* Overlap between arrows and thumb */
50 #define SCROLL_ARROW_THUMB_OVERLAP 1
52 /* Delay (in ms) before first repetition when holding the button down */
53 #define SCROLL_FIRST_DELAY 200
55 /* Delay (in ms) between scroll repetitions */
56 #define SCROLL_REPEAT_DELAY 50
58 /* Scroll timer id */
59 #define SCROLL_TIMER 0
61 /* Scroll-bar hit testing */
62 enum SCROLL_HITTEST
64 SCROLL_NOWHERE, /* Outside the scroll bar */
65 SCROLL_TOP_ARROW, /* Top or left arrow */
66 SCROLL_TOP_RECT, /* Rectangle between the top arrow and the thumb */
67 SCROLL_THUMB, /* Thumb rectangle */
68 SCROLL_BOTTOM_RECT, /* Rectangle between the thumb and the bottom arrow */
69 SCROLL_BOTTOM_ARROW /* Bottom or right arrow */
72 /* Thumb-tracking info */
73 static HWND32 SCROLL_TrackingWin = 0;
74 static INT32 SCROLL_TrackingBar = 0;
75 static INT32 SCROLL_TrackingPos = 0;
76 static INT32 SCROLL_TrackingVal = 0;
78 /* Is the moving thumb being displayed? */
79 static BOOL32 SCROLL_MovingThumb = FALSE;
81 /***********************************************************************
82 * SCROLL_LoadBitmaps
84 static void SCROLL_LoadBitmaps(void)
86 hUpArrow = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_UPARROW) );
87 hDnArrow = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_DNARROW) );
88 hLfArrow = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_LFARROW) );
89 hRgArrow = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_RGARROW) );
90 hUpArrowD = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_UPARROWD) );
91 hDnArrowD = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_DNARROWD) );
92 hLfArrowD = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_LFARROWD) );
93 hRgArrowD = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_RGARROWD) );
94 hUpArrowI = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_UPARROWI) );
95 hDnArrowI = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_DNARROWI) );
96 hLfArrowI = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_LFARROWI) );
97 hRgArrowI = LoadBitmap32A( 0, MAKEINTRESOURCE32A(OBM_RGARROWI) );
101 /***********************************************************************
102 * SCROLL_GetPtrScrollInfo
104 static SCROLLBAR_INFO *SCROLL_GetPtrScrollInfo( WND* wndPtr, INT32 nBar )
106 SCROLLBAR_INFO *infoPtr;
108 if (!wndPtr) return NULL;
109 switch(nBar)
111 case SB_HORZ: infoPtr = (SCROLLBAR_INFO *)wndPtr->pHScroll; break;
112 case SB_VERT: infoPtr = (SCROLLBAR_INFO *)wndPtr->pVScroll; break;
113 case SB_CTL: infoPtr = (SCROLLBAR_INFO *)wndPtr->wExtra; break;
114 default: return NULL;
117 if (!infoPtr) /* Create the info structure if needed */
119 if ((infoPtr = HeapAlloc( SystemHeap, 0, sizeof(SCROLLBAR_INFO) )))
121 infoPtr->MinVal = infoPtr->CurVal = infoPtr->Page = 0;
122 infoPtr->MaxVal = 100;
123 infoPtr->flags = ESB_ENABLE_BOTH;
124 if (nBar == SB_HORZ) wndPtr->pHScroll = infoPtr;
125 else wndPtr->pVScroll = infoPtr;
127 if (!hUpArrow) SCROLL_LoadBitmaps();
129 return infoPtr;
133 /***********************************************************************
134 * SCROLL_GetScrollInfo
136 static SCROLLBAR_INFO *SCROLL_GetScrollInfo( HWND32 hwnd, INT32 nBar )
138 WND *wndPtr = WIN_FindWndPtr( hwnd );
139 return SCROLL_GetPtrScrollInfo( wndPtr, nBar );
143 /***********************************************************************
144 * SCROLL_GetScrollBarRect
146 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
147 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
148 * 'arrowSize' returns the width or height of an arrow (depending on
149 * the orientation of the scrollbar), 'thumbSize' returns the size of
150 * the thumb, and 'thumbPos' returns the position of the thumb
151 * relative to the left or to the top.
152 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
154 static BOOL32 SCROLL_GetScrollBarRect( HWND32 hwnd, INT32 nBar, RECT32 *lprect,
155 INT32 *arrowSize, INT32 *thumbSize,
156 INT32 *thumbPos )
158 INT32 pixels;
159 BOOL32 vertical;
160 WND *wndPtr = WIN_FindWndPtr( hwnd );
162 switch(nBar)
164 case SB_HORZ:
165 lprect->left = wndPtr->rectClient.left - wndPtr->rectWindow.left;
166 lprect->top = wndPtr->rectClient.bottom - wndPtr->rectWindow.top;
167 lprect->right = wndPtr->rectClient.right - wndPtr->rectWindow.left;
168 lprect->bottom = lprect->top + SYSMETRICS_CYHSCROLL;
169 if(wndPtr->dwStyle & WS_BORDER) {
170 lprect->left--;
171 lprect->right++;
172 } else if(wndPtr->dwStyle & WS_VSCROLL)
173 lprect->right++;
174 vertical = FALSE;
175 break;
177 case SB_VERT:
178 lprect->left = wndPtr->rectClient.right - wndPtr->rectWindow.left;
179 lprect->top = wndPtr->rectClient.top - wndPtr->rectWindow.top;
180 lprect->right = lprect->left + SYSMETRICS_CXVSCROLL;
181 lprect->bottom = wndPtr->rectClient.bottom - wndPtr->rectWindow.top;
182 if(wndPtr->dwStyle & WS_BORDER) {
183 lprect->top--;
184 lprect->bottom++;
185 } else if(wndPtr->dwStyle & WS_HSCROLL)
186 lprect->bottom++;
187 vertical = TRUE;
188 break;
190 case SB_CTL:
191 GetClientRect32( hwnd, lprect );
192 vertical = ((wndPtr->dwStyle & SBS_VERT) != 0);
193 break;
195 default:
196 return FALSE;
199 if (vertical) pixels = lprect->bottom - lprect->top;
200 else pixels = lprect->right - lprect->left;
202 if (pixels <= 2*SYSMETRICS_CXVSCROLL + SCROLL_MIN_RECT)
204 if (pixels > SCROLL_MIN_RECT)
205 *arrowSize = (pixels - SCROLL_MIN_RECT) / 2;
206 else
207 *arrowSize = 0;
208 *thumbPos = *thumbSize = 0;
210 else
212 SCROLLBAR_INFO *info = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
214 *arrowSize = SYSMETRICS_CXVSCROLL;
215 pixels -= (2 * (SYSMETRICS_CXVSCROLL - SCROLL_ARROW_THUMB_OVERLAP));
217 if (info->Page)
219 *thumbSize = pixels * info->Page / (info->MaxVal-info->MinVal+1);
220 if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
222 else *thumbSize = SYSMETRICS_CXVSCROLL;
224 if (((pixels -= *thumbSize ) < 0) ||
225 ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
227 /* Rectangle too small or scrollbar disabled -> no thumb */
228 *thumbPos = *thumbSize = 0;
230 else
232 INT32 max = info->MaxVal - MAX( info->Page-1, 0 );
233 if (info->MinVal >= max)
234 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
235 else
236 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
237 + pixels * (info->CurVal-info->MinVal) / (max - info->MinVal);
240 return vertical;
244 /***********************************************************************
245 * SCROLL_GetThumbVal
247 * Compute the current scroll position based on the thumb position in pixels
248 * from the top of the scroll-bar.
250 static UINT32 SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT32 *rect,
251 BOOL32 vertical, INT32 pos )
253 INT32 thumbSize;
254 INT32 pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
256 if ((pixels -= 2*(SYSMETRICS_CXVSCROLL - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
257 return infoPtr->MinVal;
259 if (infoPtr->Page)
261 thumbSize = pixels * infoPtr->Page/(infoPtr->MaxVal-infoPtr->MinVal+1);
262 if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB;
264 else thumbSize = SYSMETRICS_CXVSCROLL;
266 if ((pixels -= thumbSize) <= 0) return infoPtr->MinVal;
268 pos = MAX( 0, pos - (SYSMETRICS_CXVSCROLL - SCROLL_ARROW_THUMB_OVERLAP) );
269 if (pos > pixels) pos = pixels;
271 if (!infoPtr->Page) pos *= infoPtr->MaxVal - infoPtr->MinVal;
272 else pos *= infoPtr->MaxVal - infoPtr->MinVal - infoPtr->Page + 1;
273 return infoPtr->MinVal + ((pos + pixels / 2) / pixels);
277 /***********************************************************************
278 * SCROLL_HitTest
280 * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
282 static enum SCROLL_HITTEST SCROLL_HitTest( HWND32 hwnd, INT32 nBar,
283 POINT32 pt )
285 INT32 arrowSize, thumbSize, thumbPos;
286 RECT32 rect;
288 BOOL32 vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
289 &arrowSize, &thumbSize, &thumbPos );
290 if (!PtInRect32( &rect, pt )) return SCROLL_NOWHERE;
292 if (vertical)
294 if (pt.y < rect.top + arrowSize) return SCROLL_TOP_ARROW;
295 if (pt.y >= rect.bottom - arrowSize) return SCROLL_BOTTOM_ARROW;
296 if (!thumbPos) return SCROLL_TOP_RECT;
297 pt.y -= rect.top;
298 if (pt.y < thumbPos) return SCROLL_TOP_RECT;
299 if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
300 return SCROLL_THUMB;
302 else /* horizontal */
304 if (pt.x < rect.left + arrowSize) return SCROLL_TOP_ARROW;
305 if (pt.x >= rect.right - arrowSize) return SCROLL_BOTTOM_ARROW;
306 if (!thumbPos) return SCROLL_TOP_RECT;
307 pt.x -= rect.left;
308 if (pt.x < thumbPos) return SCROLL_TOP_RECT;
309 if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
310 return SCROLL_THUMB;
315 /***********************************************************************
316 * SCROLL_DrawArrows
318 * Draw the scroll bar arrows.
320 static void SCROLL_DrawArrows( HDC32 hdc, SCROLLBAR_INFO *infoPtr,
321 RECT32 *rect, INT32 arrowSize, BOOL32 vertical,
322 BOOL32 top_pressed, BOOL32 bottom_pressed )
324 HDC32 hdcMem = CreateCompatibleDC32( hdc );
325 HBITMAP32 hbmpPrev = SelectObject32( hdcMem, vertical ?
326 TOP_ARROW(infoPtr->flags, top_pressed)
327 : LEFT_ARROW(infoPtr->flags, top_pressed));
328 SetStretchBltMode32( hdc, STRETCH_DELETESCANS );
329 StretchBlt32( hdc, rect->left, rect->top,
330 vertical ? rect->right-rect->left : arrowSize,
331 vertical ? arrowSize : rect->bottom-rect->top,
332 hdcMem, 0, 0,
333 SYSMETRICS_CXVSCROLL, SYSMETRICS_CYHSCROLL,
334 SRCCOPY );
336 SelectObject32( hdcMem, vertical ?
337 BOTTOM_ARROW( infoPtr->flags, bottom_pressed )
338 : RIGHT_ARROW( infoPtr->flags, bottom_pressed ) );
339 if (vertical)
340 StretchBlt32( hdc, rect->left, rect->bottom - arrowSize,
341 rect->right - rect->left, arrowSize,
342 hdcMem, 0, 0,
343 SYSMETRICS_CXVSCROLL, SYSMETRICS_CYHSCROLL,
344 SRCCOPY );
345 else
346 StretchBlt32( hdc, rect->right - arrowSize, rect->top,
347 arrowSize, rect->bottom - rect->top,
348 hdcMem, 0, 0,
349 SYSMETRICS_CXVSCROLL, SYSMETRICS_CYHSCROLL,
350 SRCCOPY );
351 SelectObject32( hdcMem, hbmpPrev );
352 DeleteDC32( hdcMem );
356 /***********************************************************************
357 * SCROLL_DrawMovingThumb
359 * Draw the moving thumb rectangle.
361 static void SCROLL_DrawMovingThumb( HDC32 hdc, RECT32 *rect, BOOL32 vertical,
362 INT32 arrowSize, INT32 thumbSize )
364 RECT32 r = *rect;
365 if (vertical)
367 r.top += SCROLL_TrackingPos;
368 if (r.top < rect->top + arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
369 r.top = rect->top + arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
370 if (r.top + thumbSize >
371 rect->bottom - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP))
372 r.top = rect->bottom - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
373 - thumbSize;
374 r.bottom = r.top + thumbSize;
376 else
378 r.left += SCROLL_TrackingPos;
379 if (r.left < rect->left + arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
380 r.left = rect->left + arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
381 if (r.left + thumbSize >
382 rect->right - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP))
383 r.left = rect->right - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP)
384 - thumbSize;
385 r.right = r.left + thumbSize;
387 DrawFocusRect32( hdc, &r );
388 SCROLL_MovingThumb = !SCROLL_MovingThumb;
392 /***********************************************************************
393 * SCROLL_DrawInterior
395 * Draw the scroll bar interior (everything except the arrows).
397 static void SCROLL_DrawInterior( HWND32 hwnd, HDC32 hdc, INT32 nBar,
398 RECT32 *rect, INT32 arrowSize,
399 INT32 thumbSize, INT32 thumbPos,
400 UINT32 flags, BOOL32 vertical,
401 BOOL32 top_selected, BOOL32 bottom_selected )
403 RECT32 r;
405 /* Select the correct brush and pen */
407 SelectObject32( hdc, GetSysColorPen32(COLOR_WINDOWFRAME) );
408 if ((flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)
410 /* This ought to be the color of the parent window */
411 SelectObject32( hdc, GetSysColorBrush32(COLOR_WINDOW) );
413 else
415 if (nBar == SB_CTL) /* Only scrollbar controls send WM_CTLCOLOR */
417 HBRUSH32 hbrush = SendMessage32A(GetParent32(hwnd),
418 WM_CTLCOLORSCROLLBAR, hdc, hwnd );
419 SelectObject32( hdc, hbrush );
421 else SelectObject32( hdc, GetSysColorBrush32(COLOR_SCROLLBAR) );
424 /* Calculate the scroll rectangle */
426 r = *rect;
427 if (vertical)
429 r.top += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
430 r.bottom -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
432 else
434 r.left += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
435 r.right -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
438 /* Draw the scroll bar frame */
440 GRAPH_DrawRectangle( hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, 0);
442 /* Draw the scroll rectangles and thumb */
444 if (!thumbPos) /* No thumb to draw */
446 PatBlt32( hdc, r.left+1, r.top+1, r.right - r.left - 2,
447 r.bottom - r.top - 2, PATCOPY );
448 return;
451 if (vertical)
453 PatBlt32( hdc, r.left + 1, r.top + 1,
454 r.right - r.left - 2,
455 thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - 1,
456 top_selected ? 0x0f0000 : PATCOPY );
457 r.top += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
458 PatBlt32( hdc, r.left + 1, r.top + thumbSize,
459 r.right - r.left - 2,
460 r.bottom - r.top - thumbSize - 1,
461 bottom_selected ? 0x0f0000 : PATCOPY );
462 r.bottom = r.top + thumbSize;
464 else /* horizontal */
466 PatBlt32( hdc, r.left + 1, r.top + 1,
467 thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP) - 1,
468 r.bottom - r.top - 2,
469 top_selected ? 0x0f0000 : PATCOPY );
470 r.left += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
471 PatBlt32( hdc, r.left + thumbSize, r.top + 1,
472 r.right - r.left - thumbSize - 1,
473 r.bottom - r.top - 2,
474 bottom_selected ? 0x0f0000 : PATCOPY );
475 r.right = r.left + thumbSize;
478 /* Draw the thumb */
480 SelectObject32( hdc, GetSysColorBrush32(COLOR_BTNFACE) );
481 Rectangle32( hdc, r.left, r.top, r.right, r.bottom );
482 InflateRect32( &r, -1, -1 );
483 GRAPH_DrawReliefRect( hdc, &r, 1, 2, FALSE );
484 if (SCROLL_MovingThumb &&
485 (SCROLL_TrackingWin == hwnd) &&
486 (SCROLL_TrackingBar == nBar))
488 SCROLL_DrawMovingThumb( hdc, rect, vertical, arrowSize, thumbSize );
489 SCROLL_MovingThumb = TRUE;
494 /***********************************************************************
495 * SCROLL_DrawScrollBar
497 * Redraw the whole scrollbar.
499 void SCROLL_DrawScrollBar( HWND32 hwnd, HDC32 hdc, INT32 nBar, BOOL32 arrows )
501 INT32 arrowSize, thumbSize, thumbPos;
502 RECT32 rect;
503 BOOL32 vertical;
504 WND *wndPtr = WIN_FindWndPtr( hwnd );
505 SCROLLBAR_INFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
507 if (!wndPtr || !infoPtr ||
508 ((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) ||
509 ((nBar == SB_HORZ) && !(wndPtr->dwStyle & WS_HSCROLL))) return;
511 vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
512 &arrowSize, &thumbSize, &thumbPos );
514 /* Draw the arrows */
516 if (arrows && arrowSize) SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize,
517 vertical, FALSE, FALSE );
519 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
520 thumbPos, infoPtr->flags, vertical, FALSE, FALSE );
524 /***********************************************************************
525 * SCROLL_RefreshScrollBar
527 * Repaint the scroll bar interior after a SetScrollRange() or
528 * SetScrollPos() call.
530 static void SCROLL_RefreshScrollBar( HWND32 hwnd, INT32 nBar, BOOL32 arrows )
532 HDC32 hdc = GetDCEx32( hwnd, 0,
533 DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW) );
534 if (!hdc) return;
535 SCROLL_DrawScrollBar( hwnd, hdc, nBar, arrows );
536 ReleaseDC32( hwnd, hdc );
540 /***********************************************************************
541 * SCROLL_HandleKbdEvent
543 * Handle a keyboard event (only for SB_CTL scrollbars).
545 static void SCROLL_HandleKbdEvent( HWND32 hwnd, WPARAM32 wParam )
547 WND *wndPtr = WIN_FindWndPtr( hwnd );
548 WPARAM32 msg;
550 switch(wParam)
552 case VK_PRIOR: msg = SB_PAGEUP; break;
553 case VK_NEXT: msg = SB_PAGEDOWN; break;
554 case VK_HOME: msg = SB_TOP; break;
555 case VK_END: msg = SB_BOTTOM; break;
556 case VK_UP: msg = SB_LINEUP; break;
557 case VK_DOWN: msg = SB_LINEDOWN; break;
558 default:
559 return;
561 SendMessage32A( GetParent32(hwnd),
562 (wndPtr->dwStyle & SBS_VERT) ? WM_VSCROLL : WM_HSCROLL,
563 msg, hwnd );
567 /***********************************************************************
568 * SCROLL_HandleScrollEvent
570 * Handle a mouse or timer event for the scrollbar.
571 * 'pt' is the location of the mouse event in client (for SB_CTL) or
572 * windows coordinates.
574 void SCROLL_HandleScrollEvent( HWND32 hwnd, INT32 nBar, UINT32 msg, POINT32 pt)
576 /* Previous mouse position for timer events */
577 static POINT32 prevPt;
578 /* Hit test code of the last button-down event */
579 static enum SCROLL_HITTEST trackHitTest;
580 /* Thumb position when tracking started. */
581 static UINT32 trackThumbPos;
582 /* Position in the scroll-bar of the last button-down event. */
583 static INT32 lastClickPos;
584 /* Position in the scroll-bar of the last mouse event. */
585 static INT32 lastMousePos;
587 enum SCROLL_HITTEST hittest;
588 HWND32 hwndOwner, hwndCtl;
589 BOOL32 vertical;
590 INT32 arrowSize, thumbSize, thumbPos;
591 RECT32 rect;
592 HDC32 hdc;
594 SCROLLBAR_INFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
595 if (!infoPtr) return;
596 if ((trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN)) return;
598 hdc = GetDCEx32( hwnd, 0, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
599 vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
600 &arrowSize, &thumbSize, &thumbPos );
601 hwndOwner = (nBar == SB_CTL) ? GetParent32(hwnd) : hwnd;
602 hwndCtl = (nBar == SB_CTL) ? hwnd : 0;
604 switch(msg)
606 case WM_LBUTTONDOWN: /* Initialise mouse tracking */
607 trackHitTest = hittest = SCROLL_HitTest( hwnd, nBar, pt );
608 lastClickPos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
609 lastMousePos = lastClickPos;
610 trackThumbPos = thumbPos;
611 prevPt = pt;
612 SetCapture32( hwnd );
613 if (nBar == SB_CTL) SetFocus32( hwnd );
614 break;
616 case WM_MOUSEMOVE:
617 hittest = SCROLL_HitTest( hwnd, nBar, pt );
618 prevPt = pt;
619 break;
621 case WM_LBUTTONUP:
622 hittest = SCROLL_NOWHERE;
623 ReleaseCapture();
624 break;
626 case WM_SYSTIMER:
627 pt = prevPt;
628 hittest = SCROLL_HitTest( hwnd, nBar, pt );
629 break;
631 default:
632 return; /* Should never happen */
635 TRACE(scroll, "Event: hwnd=%04x bar=%d msg=%x pt=%d,%d hit=%d\n",
636 hwnd, nBar, msg, pt.x, pt.y, hittest );
638 switch(trackHitTest)
640 case SCROLL_NOWHERE: /* No tracking in progress */
641 break;
643 case SCROLL_TOP_ARROW:
644 SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
645 (hittest == trackHitTest), FALSE );
646 if (hittest == trackHitTest)
648 if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
650 SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
651 SB_LINEUP, hwndCtl );
652 SetSystemTimer32( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
653 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
654 (TIMERPROC32)0 );
657 else KillSystemTimer32( hwnd, SCROLL_TIMER );
658 break;
660 case SCROLL_TOP_RECT:
661 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
662 thumbPos, infoPtr->flags, vertical,
663 (hittest == trackHitTest), FALSE );
664 if (hittest == trackHitTest)
666 if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
668 SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
669 SB_PAGEUP, hwndCtl );
670 SetSystemTimer32( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
671 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
672 (TIMERPROC32)0 );
675 else KillSystemTimer32( hwnd, SCROLL_TIMER );
676 break;
678 case SCROLL_THUMB:
679 if (msg == WM_LBUTTONDOWN)
681 SCROLL_TrackingWin = hwnd;
682 SCROLL_TrackingBar = nBar;
683 SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos;
684 SCROLL_DrawMovingThumb(hdc, &rect, vertical, arrowSize, thumbSize);
686 else if (msg == WM_LBUTTONUP)
688 SCROLL_TrackingWin = 0;
689 SCROLL_MovingThumb = FALSE;
690 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
691 thumbPos, infoPtr->flags, vertical,
692 FALSE, FALSE );
694 else /* WM_MOUSEMOVE */
696 UINT32 pos;
698 if (!PtInRect32( &rect, pt )) pos = lastClickPos;
699 else pos = vertical ? (pt.y - rect.top) : (pt.x - rect.left);
700 if (pos != lastMousePos)
702 SCROLL_DrawMovingThumb( hdc, &rect, vertical,
703 arrowSize, thumbSize );
704 lastMousePos = pos;
705 SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos;
706 SCROLL_TrackingVal = SCROLL_GetThumbVal( infoPtr, &rect,
707 vertical,
708 SCROLL_TrackingPos );
709 SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
710 MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal),
711 hwndCtl );
712 SCROLL_DrawMovingThumb( hdc, &rect, vertical,
713 arrowSize, thumbSize );
716 break;
718 case SCROLL_BOTTOM_RECT:
719 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
720 thumbPos, infoPtr->flags, vertical,
721 FALSE, (hittest == trackHitTest) );
722 if (hittest == trackHitTest)
724 if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
726 SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
727 SB_PAGEDOWN, hwndCtl );
728 SetSystemTimer32( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
729 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
730 (TIMERPROC32)0 );
733 else KillSystemTimer32( hwnd, SCROLL_TIMER );
734 break;
736 case SCROLL_BOTTOM_ARROW:
737 SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
738 FALSE, (hittest == trackHitTest) );
739 if (hittest == trackHitTest)
741 if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER))
743 SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
744 SB_LINEDOWN, hwndCtl );
745 SetSystemTimer32( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
746 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
747 (TIMERPROC32)0 );
750 else KillSystemTimer32( hwnd, SCROLL_TIMER );
751 break;
754 if (msg == WM_LBUTTONUP)
756 if (trackHitTest == SCROLL_THUMB)
758 UINT32 val = SCROLL_GetThumbVal( infoPtr, &rect, vertical,
759 trackThumbPos + lastMousePos - lastClickPos );
760 SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
761 MAKEWPARAM( SB_THUMBPOSITION, val ), hwndCtl );
763 else
764 SendMessage32A( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
765 SB_ENDSCROLL, hwndCtl );
766 trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */
769 ReleaseDC32( hwnd, hdc );
773 /***********************************************************************
774 * ScrollBarWndProc
776 LRESULT WINAPI ScrollBarWndProc( HWND32 hwnd, UINT32 message, WPARAM32 wParam,
777 LPARAM lParam )
779 switch(message)
781 case WM_CREATE:
783 CREATESTRUCT32A *lpCreat = (CREATESTRUCT32A *)lParam;
784 if (lpCreat->style & SBS_SIZEBOX)
786 FIXME(scroll, "Unimplemented style SBS_SIZEBOX.\n" );
787 return 0;
790 if (lpCreat->style & SBS_VERT)
792 if (lpCreat->style & SBS_LEFTALIGN)
793 MoveWindow32( hwnd, lpCreat->x, lpCreat->y,
794 SYSMETRICS_CXVSCROLL+1, lpCreat->cy, FALSE );
795 else if (lpCreat->style & SBS_RIGHTALIGN)
796 MoveWindow32( hwnd,
797 lpCreat->x+lpCreat->cx-SYSMETRICS_CXVSCROLL-1,
798 lpCreat->y,
799 SYSMETRICS_CXVSCROLL+1, lpCreat->cy, FALSE );
801 else /* SBS_HORZ */
803 if (lpCreat->style & SBS_TOPALIGN)
804 MoveWindow32( hwnd, lpCreat->x, lpCreat->y,
805 lpCreat->cx, SYSMETRICS_CYHSCROLL+1, FALSE );
806 else if (lpCreat->style & SBS_BOTTOMALIGN)
807 MoveWindow32( hwnd,
808 lpCreat->x,
809 lpCreat->y+lpCreat->cy-SYSMETRICS_CYHSCROLL-1,
810 lpCreat->cx, SYSMETRICS_CYHSCROLL+1, FALSE );
813 if (!hUpArrow) SCROLL_LoadBitmaps();
814 TRACE(scroll, "ScrollBar creation, hwnd=%04x\n", hwnd );
815 return 0;
817 case WM_LBUTTONDOWN:
818 case WM_LBUTTONUP:
819 case WM_MOUSEMOVE:
820 case WM_SYSTIMER:
822 POINT32 pt;
823 CONV_POINT16TO32( (POINT16 *)&lParam, &pt );
824 SCROLL_HandleScrollEvent( hwnd, SB_CTL, message, pt );
826 break;
828 case WM_KEYDOWN:
829 SCROLL_HandleKbdEvent( hwnd, wParam );
830 break;
832 case WM_ERASEBKGND:
833 return 1;
835 case WM_GETDLGCODE:
836 return DLGC_WANTARROWS; /* Windows returns this value */
838 case WM_PAINT:
840 PAINTSTRUCT32 ps;
841 HDC32 hdc = BeginPaint32( hwnd, &ps );
842 SCROLL_DrawScrollBar( hwnd, hdc, SB_CTL, TRUE );
843 EndPaint32( hwnd, &ps );
845 break;
847 case SBM_SETPOS16:
848 case SBM_SETPOS32:
849 return SetScrollPos32( hwnd, SB_CTL, wParam, (BOOL32)lParam );
851 case SBM_GETPOS16:
852 case SBM_GETPOS32:
853 return GetScrollPos32( hwnd, SB_CTL );
855 case SBM_SETRANGE16:
856 SetScrollRange32( hwnd, SB_CTL, LOWORD(lParam), HIWORD(lParam),
857 wParam /* FIXME: Is this correct? */ );
858 return 0;
860 case SBM_SETRANGE32:
861 SetScrollRange32( hwnd, SB_CTL, wParam, lParam, FALSE );
862 return 0; /* FIXME: return previous position */
864 case SBM_GETRANGE16:
865 FIXME(scroll, "don't know how to handle SBM_GETRANGE16 (wp=%04x,lp=%08lx)\n", wParam, lParam );
866 return 0;
868 case SBM_GETRANGE32:
869 GetScrollRange32( hwnd, SB_CTL, (LPINT32)wParam, (LPINT32)lParam );
870 return 0;
872 case SBM_ENABLE_ARROWS16:
873 case SBM_ENABLE_ARROWS32:
874 return EnableScrollBar32( hwnd, SB_CTL, wParam );
876 case SBM_SETRANGEREDRAW32:
877 SetScrollRange32( hwnd, SB_CTL, wParam, lParam, TRUE );
878 return 0; /* FIXME: return previous position */
880 case SBM_SETSCROLLINFO32:
881 return SetScrollInfo32( hwnd, SB_CTL, (SCROLLINFO *)lParam, wParam );
883 case SBM_GETSCROLLINFO32:
884 return GetScrollInfo32( hwnd, SB_CTL, (SCROLLINFO *)lParam );
886 case 0x00e5:
887 case 0x00e7:
888 case 0x00e8:
889 case 0x00eb:
890 case 0x00ec:
891 case 0x00ed:
892 case 0x00ee:
893 case 0x00ef:
894 ERR(scroll, "unknown Win32 msg %04x wp=%08x lp=%08lx\n",
895 message, wParam, lParam );
896 break;
898 default:
899 if (message >= WM_USER)
900 WARN(scroll, "unknown msg %04x wp=%04x lp=%08lx\n",
901 message, wParam, lParam );
902 return DefWindowProc32A( hwnd, message, wParam, lParam );
904 return 0;
908 /*************************************************************************
909 * SetScrollInfo16 (USER.475)
911 INT16 WINAPI SetScrollInfo16( HWND16 hwnd, INT16 nBar, const SCROLLINFO *info,
912 BOOL16 bRedraw )
914 return (INT16)SetScrollInfo32( hwnd, nBar, info, bRedraw );
918 /*************************************************************************
919 * SetScrollInfo32 (USER32.501)
920 * SetScrollInfo32 can be used to set the position, upper bound,
921 * lower bound, and page size of a scrollbar control.
923 * RETURNS
924 * Scrollbar position
926 * NOTE
927 * For 100 lines of text to be displayed in a window of 25 lines,
928 * one would for instance use info->nMin=0, info->nMax=75
929 * (corresponding to the 76 different positions of the window on
930 * the text), and info->nPage=25.
932 INT32 WINAPI SetScrollInfo32(
933 HWND32 hwnd /* [I] Handle of window whose scrollbar will be affected */,
934 INT32 nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
935 const SCROLLINFO *info /* [I] Specifies what to change and new values */,
936 BOOL32 bRedraw /* [I] Should scrollbar be redrawn afterwards ? */)
938 SCROLLBAR_INFO *infoPtr;
939 UINT32 new_flags;
940 BOOL32 repaint_arrows = FALSE;
941 dbg_decl_str(scroll, 256);
943 if (!(infoPtr = SCROLL_GetScrollInfo(hwnd, nBar))) return 0;
944 if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return 0;
945 if ((info->cbSize != sizeof(*info)) &&
946 (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return 0;
948 /* Set the page size */
950 if (info->fMask & SIF_PAGE)
952 dsprintf(scroll, " page=%d", info->nPage );
953 infoPtr->Page = info->nPage;
956 /* Set the scroll pos */
958 if (info->fMask & SIF_POS)
960 dsprintf(scroll, " pos=%d", info->nPos );
961 infoPtr->CurVal = info->nPos;
964 /* Set the scroll range */
966 if (info->fMask & SIF_RANGE)
968 dsprintf(scroll, " min=%d max=%d", info->nMin, info->nMax );
970 /* Invalid range -> range is set to (0,0) */
971 if ((info->nMin > info->nMax) ||
972 ((UINT32)(info->nMax - info->nMin) >= 0x80000000))
974 infoPtr->MinVal = 0;
975 infoPtr->MaxVal = 0;
977 else
979 infoPtr->MinVal = info->nMin;
980 infoPtr->MaxVal = info->nMax;
984 TRACE(scroll, "hwnd=%04x bar=%d %s\n",
985 hwnd, nBar, dbg_str(scroll));
987 /* Make sure the page size is valid */
989 if (infoPtr->Page < 0) infoPtr->Page = 0;
990 else if (infoPtr->Page > infoPtr->MaxVal - infoPtr->MinVal + 1 )
991 infoPtr->Page = infoPtr->MaxVal - infoPtr->MinVal + 1;
993 /* Make sure the pos is inside the range */
995 if (infoPtr->CurVal < infoPtr->MinVal)
996 infoPtr->CurVal = infoPtr->MinVal;
997 else if (infoPtr->CurVal > infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
998 infoPtr->CurVal = infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 );
1000 TRACE(scroll, " new values: page=%d pos=%d min=%d max=%d\n",
1001 infoPtr->Page, infoPtr->CurVal,
1002 infoPtr->MinVal, infoPtr->MaxVal );
1004 /* Check if the scrollbar should be hidden or disabled */
1006 if (info->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
1008 new_flags = infoPtr->flags;
1009 if (infoPtr->MinVal >= infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
1011 /* Hide or disable scroll-bar */
1012 if (info->fMask & SIF_DISABLENOSCROLL)
1013 new_flags = ESB_DISABLE_BOTH;
1014 else if (nBar != SB_CTL)
1016 ShowScrollBar32( hwnd, nBar, FALSE );
1017 bRedraw = FALSE; /* No need to repaint anything */
1020 else /* Show and enable scroll-bar */
1022 new_flags = 0;
1023 if (nBar != SB_CTL) ShowScrollBar32( hwnd, nBar, TRUE );
1026 if (infoPtr->flags != new_flags)
1028 infoPtr->flags = new_flags;
1029 repaint_arrows = TRUE;
1033 if (bRedraw || repaint_arrows)
1034 SCROLL_RefreshScrollBar( hwnd, nBar, repaint_arrows );
1036 /* Return current position */
1038 return infoPtr->CurVal;
1042 /*************************************************************************
1043 * GetScrollInfo16 (USER.476)
1045 BOOL16 WINAPI GetScrollInfo16( HWND16 hwnd, INT16 nBar, LPSCROLLINFO info )
1047 return GetScrollInfo32( hwnd, nBar, info );
1051 /*************************************************************************
1052 * GetScrollInfo32 (USER32.284)
1053 * GetScrollInfo32 can be used to retrieve the position, upper bound,
1054 * lower bound, and page size of a scrollbar control.
1056 * RETURNS STD
1058 BOOL32 WINAPI GetScrollInfo32(
1059 HWND32 hwnd /* [I] Handle of window */ ,
1060 INT32 nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
1061 LPSCROLLINFO info /* [IO] (info.fMask [I] specifies which values are to retrieve) */)
1063 SCROLLBAR_INFO *infoPtr;
1065 if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
1066 if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return FALSE;
1067 if ((info->cbSize != sizeof(*info)) &&
1068 (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return FALSE;
1070 if (info->fMask & SIF_PAGE) info->nPage = infoPtr->Page;
1071 if (info->fMask & SIF_POS) info->nPos = infoPtr->CurVal;
1072 if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info)))
1073 info->nTrackPos = (SCROLL_TrackingWin==hwnd) ? SCROLL_TrackingVal : 0;
1074 if (info->fMask & SIF_RANGE)
1076 info->nMin = infoPtr->MinVal;
1077 info->nMax = infoPtr->MaxVal;
1079 return (info->fMask & SIF_ALL) != 0;
1083 /*************************************************************************
1084 * SetScrollPos16 (USER.62)
1086 INT16 WINAPI SetScrollPos16( HWND16 hwnd, INT16 nBar, INT16 nPos,
1087 BOOL16 bRedraw )
1089 return (INT16)SetScrollPos32( hwnd, nBar, nPos, bRedraw );
1093 /*************************************************************************
1094 * SetScrollPos32 (USER32.502)
1096 * RETURNS
1097 * Success: Scrollbar position
1098 * Failure: 0
1100 * REMARKS
1101 * Note the ambiguity when 0 is returned. Use GetLastError
1102 * to make sure there was an error (and to know which one).
1104 INT32 WINAPI SetScrollPos32(
1105 HWND32 hwnd /* [I] Handle of window whose scrollbar will be affected */,
1106 INT32 nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
1107 INT32 nPos /* [I] New value */,
1108 BOOL32 bRedraw /* [I] Should scrollbar be redrawn afterwards ? */ )
1110 SCROLLINFO info;
1111 SCROLLBAR_INFO *infoPtr;
1112 INT32 oldPos;
1114 if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0;
1115 oldPos = infoPtr->CurVal;
1116 info.cbSize = sizeof(info);
1117 info.nPos = nPos;
1118 info.fMask = SIF_POS;
1119 SetScrollInfo32( hwnd, nBar, &info, bRedraw );
1120 return oldPos;
1124 /*************************************************************************
1125 * GetScrollPos16 (USER.63)
1127 INT16 WINAPI GetScrollPos16( HWND16 hwnd, INT16 nBar )
1129 return (INT16)GetScrollPos32( hwnd, nBar );
1133 /*************************************************************************
1134 * GetScrollPos32 (USER32.285)
1136 * RETURNS
1137 * Success: Current position
1138 * Failure: 0
1140 * REMARKS
1141 * Note the ambiguity when 0 is returned. Use GetLastError
1142 * to make sure there was an error (and to know which one).
1144 INT32 WINAPI GetScrollPos32(
1145 HWND32 hwnd, /* [I] Handle of window */
1146 INT32 nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */)
1148 SCROLLBAR_INFO *infoPtr;
1150 if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0;
1151 return infoPtr->CurVal;
1155 /*************************************************************************
1156 * SetScrollRange16 (USER.64)
1158 void WINAPI SetScrollRange16( HWND16 hwnd, INT16 nBar,
1159 INT16 MinVal, INT16 MaxVal, BOOL16 bRedraw )
1161 /* Invalid range -> range is set to (0,0) */
1162 if ((INT32)MaxVal - (INT32)MinVal > 0x7fff) MinVal = MaxVal = 0;
1163 SetScrollRange32( hwnd, nBar, MinVal, MaxVal, bRedraw );
1167 /*************************************************************************
1168 * SetScrollRange32 (USER32.503)
1170 * RETURNS STD
1172 BOOL32 WINAPI SetScrollRange32(
1173 HWND32 hwnd, /* [I] Handle of window whose scrollbar will be affected */
1174 INT32 nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
1175 INT32 MinVal, /* [I] New minimum value */
1176 INT32 MaxVal, /* [I] New maximum value */
1177 BOOL32 bRedraw /* [I] Should scrollbar be redrawn afterwards ? */)
1179 SCROLLINFO info;
1181 info.cbSize = sizeof(info);
1182 info.nMin = MinVal;
1183 info.nMax = MaxVal;
1184 info.fMask = SIF_RANGE;
1185 SetScrollInfo32( hwnd, nBar, &info, bRedraw );
1186 return TRUE;
1190 /*************************************************************************
1191 * SCROLL_SetNCSbState
1193 * This is for CalcChildScroll in windows/mdi.c
1195 DWORD SCROLL_SetNCSbState(WND* wndPtr, int vMin, int vMax, int vPos,
1196 int hMin, int hMax, int hPos)
1198 SCROLLBAR_INFO *infoPtr = SCROLL_GetPtrScrollInfo(wndPtr, SB_VERT);
1200 wndPtr->dwStyle |= (WS_VSCROLL | WS_HSCROLL);
1202 if( vMin >= vMax )
1203 { vMin = vMax;
1204 wndPtr->dwStyle &= ~WS_VSCROLL; }
1205 if( vPos > vMax ) vPos = vMax; else if( vPos < vMin ) vPos = vMin;
1206 infoPtr->MinVal = vMin;
1207 infoPtr->MaxVal = vMax;
1208 infoPtr->CurVal = vPos;
1210 infoPtr = SCROLL_GetPtrScrollInfo(wndPtr, SB_HORZ);
1212 if( hMin >= hMax )
1213 { hMin = hMax;
1214 wndPtr->dwStyle &= ~WS_HSCROLL; }
1215 if( hPos > hMax ) hPos = hMax; else if( hPos < hMin ) hPos = hMin;
1216 infoPtr->MinVal = hMin;
1217 infoPtr->MaxVal = hMax;
1218 infoPtr->CurVal = hPos;
1220 return wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL);
1224 /*************************************************************************
1225 * GetScrollRange16 (USER.65)
1227 BOOL16 WINAPI GetScrollRange16( HWND16 hwnd, INT16 nBar,
1228 LPINT16 lpMin, LPINT16 lpMax)
1230 INT32 min, max;
1231 BOOL16 ret = GetScrollRange32( hwnd, nBar, &min, &max );
1232 if (lpMin) *lpMin = min;
1233 if (lpMax) *lpMax = max;
1234 return ret;
1238 /*************************************************************************
1239 * GetScrollRange32 (USER32.286)
1241 * RETURNS STD
1243 BOOL32 WINAPI GetScrollRange32(
1244 HWND32 hwnd, /* [I] Handle of window */
1245 INT32 nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
1246 LPINT32 lpMin, /* [O] Where to store minimum value */
1247 LPINT32 lpMax /* [O] Where to store maximum value */)
1249 SCROLLBAR_INFO *infoPtr;
1251 if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar )))
1253 if (lpMin) lpMin = 0;
1254 if (lpMax) lpMax = 0;
1255 return FALSE;
1257 if (lpMin) *lpMin = infoPtr->MinVal;
1258 if (lpMax) *lpMax = infoPtr->MaxVal;
1259 return TRUE;
1263 /*************************************************************************
1264 * ShowScrollBar16 (USER.267)
1266 void WINAPI ShowScrollBar16( HWND16 hwnd, INT16 nBar, BOOL16 fShow )
1268 ShowScrollBar32( hwnd, nBar, fShow );
1272 /*************************************************************************
1273 * ShowScrollBar32 (USER32.532)
1275 * RETURNS STD
1277 BOOL32 WINAPI ShowScrollBar32(
1278 HWND32 hwnd, /* [I] Handle of window whose scrollbar(s) will be affected */
1279 INT32 nBar, /* [I] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */
1280 BOOL32 fShow /* [I] TRUE = show, FALSE = hide */)
1282 WND *wndPtr = WIN_FindWndPtr( hwnd );
1284 if (!wndPtr) return FALSE;
1285 TRACE(scroll, "hwnd=%04x bar=%d on=%d\n",
1286 hwnd, nBar, fShow );
1288 switch(nBar)
1290 case SB_CTL:
1291 ShowWindow32( hwnd, fShow ? SW_SHOW : SW_HIDE );
1292 return TRUE;
1294 case SB_HORZ:
1295 if (fShow)
1297 if (wndPtr->dwStyle & WS_HSCROLL) return TRUE;
1298 wndPtr->dwStyle |= WS_HSCROLL;
1300 else /* hide it */
1302 if (!(wndPtr->dwStyle & WS_HSCROLL)) return TRUE;
1303 wndPtr->dwStyle &= ~WS_HSCROLL;
1305 break;
1307 case SB_VERT:
1308 if (fShow)
1310 if (wndPtr->dwStyle & WS_VSCROLL) return TRUE;
1311 wndPtr->dwStyle |= WS_VSCROLL;
1313 else /* hide it */
1315 if (!(wndPtr->dwStyle & WS_VSCROLL)) return TRUE;
1316 wndPtr->dwStyle &= ~WS_VSCROLL;
1318 break;
1320 case SB_BOTH:
1321 if (fShow)
1323 if ((wndPtr->dwStyle & WS_HSCROLL)
1324 && (wndPtr->dwStyle & WS_VSCROLL)) return TRUE;
1325 wndPtr->dwStyle |= WS_HSCROLL | WS_VSCROLL;
1327 else /* hide it */
1329 if (!(wndPtr->dwStyle & WS_HSCROLL)
1330 && !(wndPtr->dwStyle & WS_VSCROLL)) return TRUE;
1331 wndPtr->dwStyle &= ~(WS_HSCROLL | WS_VSCROLL);
1333 break;
1335 default:
1336 return TRUE; /* Nothing to do! */
1338 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
1339 | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
1340 return TRUE;
1344 /*************************************************************************
1345 * EnableScrollBar16 (USER.482)
1347 BOOL16 WINAPI EnableScrollBar16( HWND16 hwnd, INT16 nBar, UINT16 flags )
1349 return EnableScrollBar32( hwnd, nBar, flags );
1353 /*************************************************************************
1354 * EnableScrollBar32 (USER32.171)
1356 BOOL32 WINAPI EnableScrollBar32( HWND32 hwnd, INT32 nBar, UINT32 flags )
1358 SCROLLBAR_INFO *infoPtr;
1360 if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
1361 TRACE(scroll, "%04x %d %d\n",
1362 hwnd, nBar, flags );
1363 flags &= ESB_DISABLE_BOTH;
1364 if (infoPtr->flags == flags) return FALSE;
1365 infoPtr->flags = flags;
1367 /* Redraw the whole scroll bar */
1368 SCROLL_RefreshScrollBar( hwnd, nBar, TRUE );
1369 return TRUE;