source: trunk/src/user32/new/scroll.cpp@ 2418

Last change on this file since 2418 was 2418, checked in by sandervl, 26 years ago

client positioning + scrollbar fixes

File size: 50.5 KB
Line 
1/* $Id: scroll.cpp,v 1.9 2000-01-12 15:14:16 sandervl Exp $ */
2/*
3 * Scrollbar control
4 *
5 * Copyright 1999 Christoph Bratschi
6 *
7 * Copyright 1993 Martin Ayotte
8 * Copyright 1994, 1996 Alexandre Julliard
9 *
10 * WINE version: 991031
11 *
12 * Status: complete
13 * Version: 5.00
14 */
15
16#include <stdlib.h>
17#include <os2win.h>
18#include "controls.h"
19#include "scroll.h"
20#include "win32wbase.h"
21#include "oslibwin.h"
22#include "initterm.h"
23#include "pmframe.h"
24
25#define SCROLL_MIN_RECT 4 /* Minimum size of the rectangle between the arrows */
26#define SCROLL_MIN_THUMB 6 /* Minimum size of the thumb in pixels */
27
28#define SCROLL_ARROW_THUMB_OVERLAP 0 /* Overlap between arrows and thumb */
29
30#define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when holding the button down */
31#define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */
32#define SCROLL_BLINK_DELAY 1000
33
34#define SCROLL_TIMER 0 /* Scroll timer id */
35#define BLINK_TIMER 1
36
37 /* Scroll-bar hit testing */
38enum SCROLL_HITTEST
39{
40 SCROLL_NOWHERE, /* Outside the scroll bar */
41 SCROLL_TOP_ARROW, /* Top or left arrow */
42 SCROLL_TOP_RECT, /* Rectangle between the top arrow and the thumb */
43 SCROLL_THUMB, /* Thumb rectangle */
44 SCROLL_BOTTOM_RECT, /* Rectangle between the thumb and the bottom arrow */
45 SCROLL_BOTTOM_ARROW /* Bottom or right arrow */
46};
47
48 /* What to do in SetScrollInfo() */
49#define SA_SSI_HIDE 0x0001
50#define SA_SSI_SHOW 0x0002
51#define SA_SSI_REPAINT_INTERIOR 0x0004
52#define SA_SSI_REPAINT_ARROWS 0x0008
53#define SA_SSI_MOVE_THUMB 0x0010
54#define SA_SSI_REFRESH 0x0020
55
56 /* Thumb-tracking info */
57static HWND SCROLL_TrackingWin = 0;
58static INT SCROLL_TrackingBar = 0;
59static INT SCROLL_TrackingPos = 0;
60static INT SCROLL_TrackingVal = 0;
61 /* Focus info */
62static HWND SCROLL_FocusWin = 0;
63static BOOL SCROLL_HasFocus = FALSE;
64static BOOL SCROLL_Highlighted = FALSE;
65static BOOL SCROLL_Scrolling = FALSE;
66
67 /* Hit test code of the last button-down event */
68static enum SCROLL_HITTEST SCROLL_trackHitTest;
69static enum SCROLL_HITTEST SCROLL_lastHitTest;
70static BOOL SCROLL_trackVertical;
71
72 /* Is the moving thumb being displayed? */
73static BOOL SCROLL_MovingThumb = FALSE;
74
75// Get the infoPtr: works only with scrollbar handles
76
77static SCROLLBAR_INFO *SCROLL_GetInfoPtr( HWND hwnd, INT nBar )
78{
79 Win32BaseWindow *win32wnd;
80 HWND hwndFrame;
81
82 switch(nBar)
83 {
84 case SB_HORZ:
85 case SB_VERT:
86 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
87 if (!win32wnd) return NULL;
88 return win32wnd->getScrollInfo(nBar);
89
90 case SB_CTL:
91 return (SCROLLBAR_INFO*)GetInfoPtr(hwnd);
92 }
93
94 return NULL;
95}
96
97/* Scrollbar Functions */
98
99/***********************************************************************
100 * SCROLL_GetScrollBarRect
101 *
102 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
103 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
104 * 'arrowSize' returns the width or height of an arrow (depending on
105 * the orientation of the scrollbar), 'thumbSize' returns the size of
106 * the thumb, and 'thumbPos' returns the position of the thumb
107 * relative to the left or to the top.
108 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
109 */
110static BOOL SCROLL_GetScrollBarRect( HWND hwnd, INT nBar, RECT *lprect,
111 INT *arrowSize, INT *thumbSize,
112 INT *thumbPos )
113{
114 INT pixels;
115 BOOL vertical;
116 RECT rectClient;
117
118 switch(nBar)
119 {
120 case SB_HORZ:
121 {
122 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
123 RECT rectClient;
124
125 if (!win32wnd) return FALSE;
126 rectClient = *win32wnd->getClientRectPtr();
127 mapWin32Rect(win32wnd->getParent() ? win32wnd->getParent()->getOS2WindowHandle():OSLIB_HWND_DESKTOP,win32wnd->getOS2FrameWindowHandle(),&rectClient);
128 lprect->left = rectClient.left;
129 lprect->top = rectClient.bottom;
130 lprect->right = rectClient.right;
131 lprect->bottom = lprect->top+GetSystemMetrics(SM_CYHSCROLL);
132 if (win32wnd->getStyle() & WS_BORDER)
133 {
134 lprect->left--;
135 lprect->right++;
136 } else if (win32wnd->getStyle() & WS_VSCROLL)
137 lprect->right++;
138 vertical = FALSE;
139 break;
140 }
141
142 case SB_VERT:
143 {
144 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
145 RECT rectClient;
146
147 if (!win32wnd) return FALSE;
148 rectClient = *win32wnd->getClientRectPtr();
149 mapWin32Rect(win32wnd->getParent() ? win32wnd->getParent()->getOS2WindowHandle():OSLIB_HWND_DESKTOP,win32wnd->getOS2FrameWindowHandle(),&rectClient);
150 lprect->left = rectClient.right;
151 lprect->top = rectClient.top;
152 lprect->right = lprect->left+GetSystemMetrics(SM_CXVSCROLL);
153 lprect->bottom = rectClient.bottom;
154 if(win32wnd->getStyle() & WS_BORDER)
155 {
156 lprect->top--;
157 lprect->bottom++;
158 } else if (win32wnd->getStyle() & WS_HSCROLL)
159 lprect->bottom++;
160 vertical = TRUE;
161 break;
162 }
163
164 case SB_CTL:
165 {
166 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
167
168 GetClientRect( hwnd, lprect );
169 vertical = ((dwStyle & SBS_VERT) != 0);
170 break;
171 }
172
173 default:
174 return FALSE;
175 }
176
177 if (vertical) pixels = lprect->bottom - lprect->top;
178 else pixels = lprect->right - lprect->left;
179
180 if (pixels <= 2*GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT)
181 {
182 if (pixels > SCROLL_MIN_RECT)
183 *arrowSize = (pixels - SCROLL_MIN_RECT) / 2;
184 else
185 *arrowSize = 0;
186 *thumbPos = *thumbSize = 0;
187 }
188 else
189 {
190 SCROLLBAR_INFO *info = SCROLL_GetInfoPtr( hwnd, nBar );
191
192 *arrowSize = GetSystemMetrics(SM_CXVSCROLL);
193 pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
194
195 if (info->Page)
196 {
197 *thumbSize = pixels * info->Page / (info->MaxVal-info->MinVal+1);
198 if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
199 }
200 else *thumbSize = GetSystemMetrics(SM_CXVSCROLL);
201
202 if (((pixels -= *thumbSize ) < 0) ||
203 ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
204 {
205 /* Rectangle too small or scrollbar disabled -> no thumb */
206 *thumbPos = *thumbSize = 0;
207 }
208 else
209 {
210 INT max = info->MaxVal - MAX( info->Page-1, 0 );
211 if (info->MinVal >= max)
212 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
213 else
214 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
215 + pixels * (info->CurVal-info->MinVal) / (max - info->MinVal);
216 }
217 }
218 return vertical;
219}
220
221/***********************************************************************
222 * SCROLL_PtInRectEx
223 */
224static BOOL SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical )
225{
226 RECT rect = *lpRect;
227
228 if (vertical)
229 {
230 INT w = lpRect->right-lpRect->left;
231
232 rect.left -= w;
233 rect.right += w;
234 rect.top -= w;
235 rect.bottom += w;
236 } else
237 {
238 INT h = lpRect->bottom-lpRect->top;
239
240 rect.top -= h;
241 rect.bottom += h;
242 rect.left -= h;
243 rect.right += h;
244 }
245
246 return PtInRect( &rect, pt );
247}
248
249/***********************************************************************
250 * SCROLL_HitTest
251 *
252 * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
253 */
254static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, INT nBar,
255 POINT pt, BOOL bDragging )
256{
257 INT arrowSize, thumbSize, thumbPos;
258 RECT rect;
259 SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
260
261 if (!infoPtr) return SCROLL_NOWHERE;
262
263 BOOL vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
264 &arrowSize, &thumbSize, &thumbPos );
265
266 if ( (bDragging && !SCROLL_PtInRectEx( &rect, pt, vertical )) ||
267 (!PtInRect( &rect, pt )) ) return SCROLL_NOWHERE;
268
269 if (vertical)
270 {
271 if (pt.y < rect.top + arrowSize) return (infoPtr->flags & ESB_DISABLE_LTUP) ? SCROLL_NOWHERE:SCROLL_TOP_ARROW;
272 if (pt.y >= rect.bottom - arrowSize) return (infoPtr->flags & ESB_DISABLE_RTDN) ? SCROLL_NOWHERE:SCROLL_BOTTOM_ARROW;
273 if (!thumbPos) return ((infoPtr->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ? SCROLL_NOWHERE:SCROLL_TOP_RECT;
274 pt.y -= rect.top;
275 if (pt.y < thumbPos) return SCROLL_TOP_RECT;
276 if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
277 }
278 else /* horizontal */
279 {
280 if (pt.x < rect.left + arrowSize) return (infoPtr->flags & ESB_DISABLE_LTUP) ? SCROLL_NOWHERE:SCROLL_TOP_ARROW;
281 if (pt.x >= rect.right - arrowSize) return (infoPtr->flags & ESB_DISABLE_RTDN) ? SCROLL_NOWHERE:SCROLL_BOTTOM_ARROW;
282 if (!thumbPos) return ((infoPtr->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ? SCROLL_NOWHERE:SCROLL_TOP_RECT;
283 pt.x -= rect.left;
284 if (pt.x < thumbPos) return SCROLL_TOP_RECT;
285 if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
286 }
287 return SCROLL_THUMB;
288}
289
290static void SCROLL_DrawTopArrow(HDC hdc,SCROLLBAR_INFO *infoPtr,RECT *rect,INT arrowSize,BOOL vertical,BOOL top_pressed)
291{
292 RECT r;
293
294 r = *rect;
295 if( vertical )
296 r.bottom = r.top + arrowSize;
297 else
298 r.right = r.left + arrowSize;
299
300 DrawFrameControl( hdc, &r, DFC_SCROLL,
301 (vertical ? DFCS_SCROLLUP : DFCS_SCROLLLEFT)
302 | (top_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0 )
303 | (infoPtr->flags&ESB_DISABLE_LTUP ? DFCS_INACTIVE : 0 ) );
304}
305
306static void SCROLL_DrawBottomArrow(HDC hdc,SCROLLBAR_INFO *infoPtr,RECT *rect,INT arrowSize,BOOL vertical,BOOL bottom_pressed)
307{
308 RECT r;
309
310 r = *rect;
311 if( vertical )
312 r.top = r.bottom-arrowSize;
313 else
314 r.left = r.right-arrowSize;
315
316 DrawFrameControl( hdc, &r, DFC_SCROLL,
317 (vertical ? DFCS_SCROLLDOWN : DFCS_SCROLLRIGHT)
318 | (bottom_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0 )
319 | (infoPtr->flags&ESB_DISABLE_RTDN ? DFCS_INACTIVE : 0) );
320}
321
322/***********************************************************************
323 * SCROLL_DrawArrows
324 *
325 * Draw the scroll bar arrows.
326 */
327static void SCROLL_DrawArrows( HDC hdc, SCROLLBAR_INFO *infoPtr,
328 RECT *rect, INT arrowSize, BOOL vertical,
329 BOOL top_pressed, BOOL bottom_pressed )
330{
331 SCROLL_DrawTopArrow(hdc,infoPtr,rect,arrowSize,vertical,top_pressed);
332 SCROLL_DrawBottomArrow(hdc,infoPtr,rect,arrowSize,vertical,bottom_pressed);
333}
334
335static void SCROLL_DrawInterior( HWND hwnd, HDC hdc, INT nBar,
336 RECT *rect, INT arrowSize,
337 INT thumbSize, INT thumbPos,
338 UINT flags, BOOL vertical,
339 BOOL top_selected, BOOL bottom_selected )
340{
341 RECT r;
342 HPEN hSavePen;
343 HBRUSH hSaveBrush,hBrush;
344
345 /* Select the correct brush and pen */
346
347 /* Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
348 * The window-owned scrollbars need to call DEFWND_ControlColor
349 * to correctly setup default scrollbar colors
350 */
351 if (nBar == SB_CTL) {
352 hBrush = (HBRUSH)SendMessageA( GetParent(hwnd), WM_CTLCOLORSCROLLBAR,
353 (WPARAM)hdc,(LPARAM)hwnd);
354 } else {
355 hBrush = (HBRUSH)SendMessageA( hwnd, WM_CTLCOLORSCROLLBAR,
356 (WPARAM)hdc,(LPARAM)hwnd);
357
358 }
359
360 hSavePen = SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
361 hSaveBrush = SelectObject( hdc, hBrush );
362
363 /* Calculate the scroll rectangle */
364
365 r = *rect;
366 if (vertical)
367 {
368 r.top += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
369 r.bottom -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
370 }
371 else
372 {
373 r.left += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
374 r.right -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
375 }
376
377 /* Draw the scroll rectangles and thumb */
378 if (!thumbPos) /* No thumb to draw */
379 {
380 PatBlt( hdc, r.left, r.top,
381 r.right - r.left, r.bottom - r.top,
382 PATCOPY );
383
384 /* cleanup and return */
385 SelectObject( hdc, hSavePen );
386 SelectObject( hdc, hSaveBrush );
387 return;
388 }
389
390 if (vertical)
391 {
392 PatBlt( hdc, r.left, r.top,
393 r.right - r.left,
394 thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP),
395 top_selected ? 0x0f0000 : PATCOPY );
396 r.top += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
397 PatBlt( hdc, r.left, r.top + thumbSize,
398 r.right - r.left,
399 r.bottom - r.top - thumbSize,
400 bottom_selected ? 0x0f0000 : PATCOPY );
401 r.bottom = r.top + thumbSize;
402 }
403 else /* horizontal */
404 {
405 PatBlt( hdc, r.left, r.top,
406 thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP),
407 r.bottom - r.top,
408 top_selected ? 0x0f0000 : PATCOPY );
409 r.left += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
410 PatBlt( hdc, r.left + thumbSize, r.top,
411 r.right - r.left - thumbSize,
412 r.bottom - r.top,
413 bottom_selected ? 0x0f0000 : PATCOPY );
414 r.right = r.left + thumbSize;
415 }
416
417 /* Draw the thumb */
418
419 DrawEdge(hdc,&r,EDGE_RAISED,BF_RECT | BF_ADJUST);
420 FillRect(hdc,&r,(SCROLL_FocusWin == hwnd && SCROLL_Highlighted && !SCROLL_Scrolling) ? GetSysColorBrush(COLOR_3DSHADOW):GetSysColorBrush(COLOR_BTNFACE));
421
422 /* cleanup */
423 SelectObject( hdc, hSavePen );
424 SelectObject( hdc, hSaveBrush );
425}
426
427/***********************************************************************
428 * SCROLL_DrawMovingThumb
429 *
430 * Draw the moving thumb rectangle.
431 */
432static void SCROLL_DrawMovingThumb( HDC hdc, RECT *rect, BOOL vertical,
433 INT arrowSize, INT thumbSize )
434{
435 INT pos = SCROLL_TrackingPos;
436 INT max_size;
437
438 if( vertical )
439 max_size = rect->bottom - rect->top;
440 else
441 max_size = rect->right - rect->left;
442
443 max_size -= (arrowSize-SCROLL_ARROW_THUMB_OVERLAP) + thumbSize;
444
445 if( pos < (arrowSize-SCROLL_ARROW_THUMB_OVERLAP) )
446 pos = (arrowSize-SCROLL_ARROW_THUMB_OVERLAP);
447 else if( pos > max_size )
448 pos = max_size;
449
450 SCROLL_DrawInterior( SCROLL_TrackingWin, hdc, SCROLL_TrackingBar,
451 rect, arrowSize, thumbSize, pos,
452 0, vertical, FALSE, FALSE );
453}
454
455/***********************************************************************
456 * SCROLL_ClipPos
457 */
458static POINT SCROLL_ClipPos( LPRECT lpRect, POINT pt )
459{
460 if( pt.x < lpRect->left )
461 pt.x = lpRect->left;
462 else
463 if( pt.x >= lpRect->right )
464 pt.x = lpRect->right-1;
465
466 if( pt.y < lpRect->top )
467 pt.y = lpRect->top;
468 else
469 if( pt.y >= lpRect->bottom )
470 pt.y = lpRect->bottom-1;
471
472 return pt;
473}
474
475/***********************************************************************
476 * SCROLL_GetThumbVal
477 *
478 * Compute the current scroll position based on the thumb position in pixels
479 * from the top of the scroll-bar.
480 */
481static UINT SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT *rect,
482 BOOL vertical, INT pos )
483{
484 INT thumbSize;
485 INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
486
487 if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
488 return infoPtr->MinVal;
489
490 if (infoPtr->Page)
491 {
492 thumbSize = pixels * infoPtr->Page/(infoPtr->MaxVal-infoPtr->MinVal+1);
493 if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB;
494 }
495 else thumbSize = GetSystemMetrics(SM_CXVSCROLL);
496
497 if ((pixels -= thumbSize) <= 0) return infoPtr->MinVal;
498
499 pos = MAX( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) );
500 if (pos > pixels) pos = pixels;
501
502 if (!infoPtr->Page) pos *= infoPtr->MaxVal - infoPtr->MinVal;
503 else pos *= infoPtr->MaxVal - infoPtr->MinVal - infoPtr->Page + 1;
504 return infoPtr->MinVal + ((pos + pixels / 2) / pixels);
505}
506
507void SCROLL_GetSizeBox(HWND hwnd,DWORD dwStyle,PRECT rect)
508{
509 RECT clientRect;
510 INT cx = GetSystemMetrics(SM_CXVSCROLL);
511 INT cy = GetSystemMetrics(SM_CYHSCROLL);
512
513 GetClientRect(hwnd,&clientRect);
514
515 if (dwStyle & SBS_SIZEBOXTOPLEFTALIGN)
516 {
517 rect->left = 0;
518 rect->right = cx;
519 rect->bottom = cy;
520 rect->top = 0;
521 } else
522 {
523 rect->left = clientRect.right-cx;
524 rect->right = clientRect.right;
525 rect->bottom = clientRect.bottom;
526 rect->top = clientRect.bottom-cy;
527 }
528}
529
530void SCROLL_DrawSizeBox(HDC hdc,RECT rect)
531{
532 POINT p1,p2;
533 HPEN penDark = GetSysColorPen(COLOR_3DSHADOW);
534 HPEN penWhite = GetSysColorPen(COLOR_3DHILIGHT);
535 HPEN oldPen = SelectObject(hdc,penDark);
536 INT x;
537
538 p1.x = rect.right-1;
539 p1.y = rect.bottom;
540 p2.x = rect.right;
541 p2.y = rect.bottom-1;
542 for (x = 0;x < 3;x++)
543 {
544 SelectObject(hdc,penDark);
545 MoveToEx(hdc,p1.x,p1.y,NULL);
546 LineTo(hdc,p2.x,p2.y);
547 p1.x--;
548 p2.y--;
549 MoveToEx(hdc,p1.x,p1.y,NULL);
550 LineTo(hdc,p2.x,p2.y);
551 SelectObject(hdc,penWhite);
552 p1.x--;
553 p2.y--;
554 MoveToEx(hdc,p1.x,p1.y,NULL);
555 LineTo(hdc,p2.x,p2.y);
556 p1.x -= 2;
557 p2.y -= 2;
558 }
559
560 SelectObject(hdc,oldPen);
561}
562
563/***********************************************************************
564 * SCROLL_DrawScrollBar
565 *
566 * Redraw the whole scrollbar.
567 */
568void SCROLL_DrawScrollBar(HWND hwnd,HDC hdc,INT nBar,BOOL arrows,BOOL interior)
569{
570 INT arrowSize, thumbSize, thumbPos;
571 RECT rect;
572 BOOL vertical;
573 SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr( hwnd, nBar );
574
575 if (!infoPtr) return;
576 if (nBar == SB_CTL)
577 {
578 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
579
580 if (dwStyle & (SBS_SIZEBOX | SBS_SIZEGRIP))
581 {
582 RECT rect;
583 HBRUSH hBrush;
584
585 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
586 hBrush = GetSysColorBrush(COLOR_3DFACE);
587 GetClientRect(hwnd,&rect);
588 FillRect(hdc,&rect,hBrush);
589
590 if (dwStyle & SBS_SIZEGRIP)
591 {
592 SCROLL_GetSizeBox(hwnd,dwStyle,&rect);
593 SCROLL_DrawSizeBox(hdc,rect);
594 }
595
596 ReleaseDC(hwnd,hdc);
597
598 return;
599 }
600 }
601
602 vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
603 &arrowSize, &thumbSize, &thumbPos );
604
605 /* Draw the arrows */
606
607 if (arrows && arrowSize)
608 {
609 if( vertical == SCROLL_trackVertical && GetCapture() == hwnd )
610 SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
611 (SCROLL_trackHitTest == SCROLL_TOP_ARROW),
612 (SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW) );
613 else
614 SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
615 FALSE, FALSE );
616 }
617
618 if (SCROLL_MovingThumb &&
619 (SCROLL_TrackingWin == hwnd) &&
620 (SCROLL_TrackingBar == nBar))
621 SCROLL_DrawMovingThumb( hdc, &rect, vertical, arrowSize, thumbSize );
622 else if( interior )
623 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
624 thumbPos, infoPtr->flags, vertical, SCROLL_trackHitTest == SCROLL_TOP_RECT && SCROLL_lastHitTest == SCROLL_TOP_RECT,SCROLL_trackHitTest == SCROLL_BOTTOM_RECT && SCROLL_lastHitTest == SCROLL_BOTTOM_RECT);
625}
626
627/***********************************************************************
628 * SCROLL_RefreshScrollBar
629 *
630 * Repaint the scroll bar interior after a SetScrollRange() or
631 * SetScrollPos() call.
632 */
633static void SCROLL_RefreshScrollBar( HWND hwnd, INT nBar,
634 BOOL arrows, BOOL interior )
635{
636 HDC hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0:DCX_WINDOW));
637
638 if (!hdc) return;
639
640 SCROLL_DrawScrollBar( hwnd, hdc, nBar, arrows, interior );
641 ReleaseDC( hwnd, hdc );
642}
643
644/* Message Handler */
645
646LRESULT SCROLL_NCCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
647{
648 SCROLLBAR_INFO *infoPtr = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
649
650 infoPtr->MinVal = infoPtr->CurVal = infoPtr->Page = 0;
651 infoPtr->MaxVal = 100;
652 infoPtr->flags = ESB_ENABLE_BOTH;
653
654 SetInfoPtr(hwnd,(DWORD)infoPtr);
655
656 return TRUE;
657}
658
659LRESULT SCROLL_Create(HWND hwnd,WPARAM wParam,LPARAM lParam)
660{
661 CREATESTRUCTA *lpCreat = (CREATESTRUCTA *)lParam;
662
663 if (!(lpCreat->style & (SBS_SIZEBOX | SBS_SIZEGRIP)) && (lpCreat->style & (SBS_LEFTALIGN | SBS_RIGHTALIGN)))
664 {
665 if (lpCreat->style & SBS_VERT)
666 {
667 INT w,h;
668
669 w = GetSystemMetrics(SM_CXVSCROLL);
670 h = lpCreat->cy;
671
672 if (lpCreat->style & SBS_LEFTALIGN)
673 MoveWindow(hwnd,lpCreat->x,lpCreat->y,w,h,FALSE);
674 else if (lpCreat->style & SBS_RIGHTALIGN)
675 MoveWindow(hwnd,lpCreat->x+lpCreat->cx-w,lpCreat->y,w,h,FALSE);
676 } else /* SBS_HORZ */
677 {
678 INT w,h;
679
680 w = lpCreat->cx;
681 h = GetSystemMetrics(SM_CYHSCROLL);
682
683 if (lpCreat->style & SBS_TOPALIGN)
684 MoveWindow(hwnd,lpCreat->x,lpCreat->y,w,h,FALSE);
685 else if (lpCreat->style & SBS_BOTTOMALIGN)
686 MoveWindow(hwnd,lpCreat->x,lpCreat->y+lpCreat->cy-h,w,h,FALSE);
687 }
688 }
689
690 return 0;
691}
692
693/***********************************************************************
694 * SCROLL_HandleScrollEvent
695 *
696 * Handle a mouse or timer event for the scrollbar.
697 * 'pt' is the location of the mouse event in client (for SB_CTL) or
698 * windows coordinates.
699 */
700LRESULT SCROLL_HandleScrollEvent(HWND hwnd,WPARAM wParam,LPARAM lParam,INT nBar,UINT msg)
701{
702 static POINT prevPt; /* Previous mouse position for timer events */
703 static UINT trackThumbPos; /* Thumb position when tracking started. */
704 static BOOL thumbTrackSent;
705 static INT lastClickPos; /* Position in the scroll-bar of the last button-down event. */
706 static INT lastMousePos; /* Position in the scroll-bar of the last mouse event. */
707 static BOOL timerRunning;
708
709 enum SCROLL_HITTEST hittest;
710 HWND hwndOwner, hwndCtl;
711 BOOL vertical;
712 INT arrowSize, thumbSize, thumbPos;
713 RECT rect;
714 HDC hdc;
715 POINT pt;
716 LRESULT res = 0;
717
718 SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
719 if (!infoPtr) return res;
720
721 if (nBar == SB_CTL)
722 {
723 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
724
725 if ((dwStyle & (SBS_SIZEBOX | SBS_SIZEGRIP)))
726 {
727 if (!(dwStyle & SBS_SIZEGRIP)) return res;
728
729 if (msg == WM_NCHITTEST)
730 {
731 if (dwStyle & SBS_SIZEGRIP)
732 {
733 RECT rect;
734
735 pt.x = (SHORT)LOWORD(lParam);
736 pt.y = (SHORT)HIWORD(lParam);
737 ScreenToClient(hwnd,&pt);
738 SCROLL_GetSizeBox(hwnd,dwStyle,&rect);
739 if (PtInRect(&rect,pt))
740 {
741 if (dwStyle & SBS_SIZEBOXTOPLEFTALIGN)
742 return HTTOPLEFT;
743 else
744 return HTBOTTOMRIGHT;
745 }
746 }
747 return DefWindowProcA(hwnd,WM_NCHITTEST,wParam,lParam);
748 } else if (msg == WM_LBUTTONDOWN)
749 {
750 return DefWindowProcA(hwnd,WM_LBUTTONDOWN,wParam,lParam);
751 }
752
753 return res;
754 }
755 }
756
757 if (msg == WM_NCHITTEST) return DefWindowProcA(hwnd,WM_NCHITTEST,wParam,lParam);
758
759 vertical = SCROLL_GetScrollBarRect(hwnd,nBar,&rect,&arrowSize,&thumbSize,&thumbPos);
760 hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd):hwnd;
761
762 hwndCtl = (nBar == SB_CTL) ? hwnd:0;
763
764 switch (msg)
765 {
766 case WM_LBUTTONDOWN: /* Initialise mouse tracking */
767 pt.x = (SHORT)LOWORD(lParam);
768 pt.y = (SHORT)HIWORD(lParam);
769 SCROLL_trackVertical = vertical;
770 SCROLL_trackHitTest = hittest = SCROLL_HitTest(hwnd,nBar,pt,FALSE);
771 if (SCROLL_trackHitTest == SCROLL_NOWHERE)
772 {
773 MessageBeep(MB_ICONEXCLAMATION);
774
775 return res;
776 }
777 SCROLL_Scrolling = TRUE;
778 timerRunning = FALSE;
779 if ((SCROLL_FocusWin == hwnd) && SCROLL_Highlighted)
780 {
781 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0:DCX_WINDOW));
782 SCROLL_DrawScrollBar(hwnd,hdc,nBar,FALSE,TRUE);
783 ReleaseDC(hwnd,hdc);
784 }
785 lastClickPos = vertical ? pt.y:pt.x;
786 lastMousePos = lastClickPos;
787 trackThumbPos = thumbPos;
788 prevPt = pt;
789 if (nBar == SB_CTL) SetFocus(hwnd);
790 SetCapture(hwnd);
791 break;
792
793 case WM_MOUSEMOVE:
794 if (SCROLL_Scrolling)
795 {
796 pt.x = (SHORT)LOWORD(lParam);
797 pt.y = (SHORT)HIWORD(lParam);
798 hittest = SCROLL_HitTest(hwnd,nBar,pt,TRUE);
799 prevPt = pt;
800 } else return res;
801 break;
802
803 case WM_LBUTTONUP:
804 if (SCROLL_Scrolling)
805 {
806 pt.x = (SHORT)LOWORD(lParam);
807 pt.y = (SHORT)HIWORD(lParam);
808 hittest = SCROLL_NOWHERE;
809 ReleaseCapture();
810 SCROLL_Scrolling = FALSE;
811 } else return res;
812 break;
813
814 case WM_CAPTURECHANGED:
815 if (SCROLL_Scrolling)
816 {
817 hittest = SCROLL_NOWHERE;
818 SCROLL_Scrolling = FALSE;
819 } else return res;
820 break;
821
822 case WM_SETFOCUS:
823 if (nBar == SB_CTL)
824 {
825 SCROLL_FocusWin = hwnd;
826 SCROLL_HasFocus = TRUE;
827 SCROLL_Highlighted = FALSE;
828 SetSystemTimer(hwnd,BLINK_TIMER,SCROLL_BLINK_DELAY,(TIMERPROC)0);
829 }
830 return res;
831
832 case WM_KILLFOCUS:
833 if (SCROLL_FocusWin == hwnd)
834 {
835 SCROLL_FocusWin = 0;
836 SCROLL_HasFocus = FALSE;
837 if (SCROLL_Highlighted)
838 {
839 SCROLL_Highlighted = FALSE;
840 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0:DCX_WINDOW));
841 SCROLL_DrawScrollBar(hwnd,hdc,nBar,FALSE,TRUE);
842 ReleaseDC(hwnd,hdc);
843 }
844 KillSystemTimer(hwnd,BLINK_TIMER);
845 }
846 return res;
847
848 case WM_SYSTIMER:
849 if (wParam == SCROLL_TIMER)
850 {
851 pt = prevPt;
852 hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
853 break;
854 } else if (wParam == BLINK_TIMER)
855 {
856 SCROLL_Highlighted = ~SCROLL_Highlighted;
857 if (!SCROLL_Scrolling)
858 {
859 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
860 SCROLL_DrawScrollBar(hwnd,hdc,nBar,FALSE,TRUE);
861 ReleaseDC(hwnd,hdc);
862 }
863 return res;
864 } else return res;
865
866 default:
867 return res; /* Should never happen */
868 }
869
870 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
871
872 switch(SCROLL_trackHitTest)
873 {
874 case SCROLL_NOWHERE: /* No tracking in progress */
875 break;
876
877 case SCROLL_TOP_ARROW:
878 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
879 KillSystemTimer(hwnd,SCROLL_TIMER);
880 else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && msg == WM_SYSTIMER))
881 {
882 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
883 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
884 (TIMERPROC)0 );
885 if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
886 }
887
888 if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
889 {
890 SCROLL_DrawTopArrow(hdc,infoPtr,&rect,arrowSize,vertical,(hittest == SCROLL_trackHitTest));
891 SCROLL_lastHitTest = hittest;
892 }
893 if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
894 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_LINEUP,hwndCtl);
895
896 break;
897
898 case SCROLL_TOP_RECT:
899 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
900 KillSystemTimer(hwnd,SCROLL_TIMER);
901 else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && (msg == WM_SYSTIMER)))
902 {
903 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
904 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
905 (TIMERPROC)0 );
906 if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
907 }
908
909 if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
910 {
911 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
912 thumbPos, infoPtr->flags, vertical,
913 (hittest == SCROLL_trackHitTest), FALSE );
914 SCROLL_lastHitTest = hittest;
915 }
916
917 if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
918 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_PAGEUP,hwndCtl);
919
920 break;
921
922 case SCROLL_THUMB:
923 if (msg == WM_LBUTTONDOWN)
924 {
925 SCROLL_TrackingWin = hwnd;
926 SCROLL_TrackingBar = nBar;
927 SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos;
928 SCROLL_TrackingVal = infoPtr->CurVal;
929 SCROLL_MovingThumb = TRUE;
930 thumbTrackSent = FALSE;
931 SCROLL_DrawMovingThumb(hdc, &rect, vertical, arrowSize, thumbSize);
932 } else if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
933 {
934 UINT val;
935 INT oldPos = infoPtr->CurVal;
936
937 SCROLL_MovingThumb = FALSE;
938 SCROLL_TrackingWin = 0;
939 SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */
940 val = SCROLL_GetThumbVal( infoPtr, &rect, vertical,
941 trackThumbPos + lastMousePos - lastClickPos );
942
943 if ((val != infoPtr->CurVal) || thumbTrackSent)
944 SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
945 MAKEWPARAM( SB_THUMBPOSITION, val ), hwndCtl );
946
947 if (oldPos == infoPtr->CurVal)
948 {
949 vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
950 &arrowSize, &thumbSize, &thumbPos );
951 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
952 thumbPos, infoPtr->flags, vertical,
953 FALSE, FALSE );
954 }
955
956 ReleaseDC(hwnd,hdc);
957 return res;
958 } else if (msg == WM_MOUSEMOVE)
959 {
960 UINT pos;
961
962 if (!SCROLL_PtInRectEx( &rect, pt, vertical )) pos = lastClickPos;
963 else
964 {
965 pt = SCROLL_ClipPos( &rect, pt );
966 pos = vertical ? pt.y:pt.x;
967 }
968 if (pos != lastMousePos)
969 {
970 lastMousePos = pos;
971 SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos;
972 SCROLL_TrackingVal = SCROLL_GetThumbVal( infoPtr, &rect,
973 vertical,
974 SCROLL_TrackingPos );
975 SCROLL_DrawMovingThumb( hdc, &rect, vertical,
976 arrowSize, thumbSize );
977 SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
978 MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal),
979 hwndCtl );
980 thumbTrackSent = TRUE;
981 }
982 }
983 break;
984
985 case SCROLL_BOTTOM_RECT:
986 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
987 KillSystemTimer(hwnd,SCROLL_TIMER);
988 else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && (msg == WM_SYSTIMER)))
989 {
990 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
991 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
992 (TIMERPROC)0 );
993 if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
994 }
995
996 if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
997 {
998 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
999 thumbPos, infoPtr->flags, vertical,
1000 FALSE, (hittest == SCROLL_trackHitTest) );
1001 SCROLL_lastHitTest = hittest;
1002 }
1003
1004 if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
1005 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_PAGEDOWN,hwndCtl);
1006
1007 break;
1008
1009 case SCROLL_BOTTOM_ARROW:
1010 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
1011 KillSystemTimer(hwnd,SCROLL_TIMER);
1012 else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && (msg == WM_SYSTIMER)))
1013 {
1014 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
1015 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
1016 (TIMERPROC)0 );
1017 if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
1018 }
1019
1020 if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
1021 {
1022 SCROLL_DrawBottomArrow(hdc,infoPtr,&rect,arrowSize,vertical,(hittest == SCROLL_trackHitTest));
1023 SCROLL_lastHitTest = hittest;
1024 }
1025 if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
1026 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_LINEDOWN,hwndCtl);
1027
1028 break;
1029 }
1030
1031 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
1032 {
1033 SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */
1034
1035 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_ENDSCROLL,hwndCtl);
1036 }
1037
1038 ReleaseDC( hwnd, hdc );
1039
1040 return res;
1041}
1042
1043/***********************************************************************
1044 * SCROLL_HandleKbdEvent
1045 *
1046 * Handle a keyboard event (only for SB_CTL scrollbars).
1047 */
1048LRESULT SCROLL_KeyDown(HWND hwnd,WPARAM wParam,LPARAM lParam)
1049{
1050 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
1051 UINT msg;
1052
1053 if (dwStyle & (SBS_SIZEBOX | SBS_SIZEGRIP)) return 0;
1054
1055 switch(wParam)
1056 {
1057 case VK_PRIOR: msg = SB_PAGEUP; break;
1058 case VK_NEXT: msg = SB_PAGEDOWN; break;
1059 case VK_HOME: msg = SB_TOP; break;
1060 case VK_END: msg = SB_BOTTOM; break;
1061 case VK_UP: msg = SB_LINEUP; break;
1062 case VK_DOWN: msg = SB_LINEDOWN; break;
1063 default:
1064 return 0;
1065 }
1066 SendMessageA( GetParent(hwnd),
1067 (dwStyle & SBS_VERT) ? WM_VSCROLL : WM_HSCROLL,
1068 msg, hwnd );
1069
1070 return 0;
1071}
1072
1073LRESULT SCROLL_Paint(HWND hwnd,WPARAM wParam,LPARAM lParam,INT nBar)
1074{
1075 PAINTSTRUCT ps;
1076 HDC hdc = wParam ? (HDC)wParam:BeginPaint( hwnd, &ps );
1077
1078 SCROLL_DrawScrollBar( hwnd, hdc, nBar, TRUE, TRUE );
1079 if (!wParam) EndPaint( hwnd, &ps );
1080
1081 return 0;
1082}
1083
1084LRESULT SCROLL_SetRange(HWND hwnd,WPARAM wParam,LPARAM lParam,INT nBar,BOOL redraw)
1085{
1086 SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
1087 INT oldPos = infoPtr->CurVal;
1088
1089 SetScrollRange(hwnd,nBar,wParam,lParam,redraw);
1090 return (oldPos != infoPtr->CurVal) ? infoPtr->CurVal:0;
1091}
1092
1093/* Window Procedures */
1094
1095/***********************************************************************
1096 * ScrollBarWndProc
1097 */
1098LRESULT WINAPI ScrollBarWndProc( HWND hwnd, UINT message, WPARAM wParam,
1099 LPARAM lParam )
1100{
1101 switch(message)
1102 {
1103 case WM_NCCREATE:
1104 return SCROLL_NCCreate(hwnd,wParam,lParam);
1105
1106 case WM_CREATE:
1107 return SCROLL_Create(hwnd,wParam,lParam);
1108
1109 case WM_LBUTTONDOWN:
1110 case WM_LBUTTONUP:
1111 case WM_NCHITTEST:
1112 case WM_CAPTURECHANGED:
1113 case WM_MOUSEMOVE:
1114 case WM_SYSTIMER:
1115 case WM_SETFOCUS:
1116 case WM_KILLFOCUS:
1117 return SCROLL_HandleScrollEvent(hwnd,wParam,lParam,SB_CTL,message);
1118
1119 case WM_KEYDOWN:
1120 return SCROLL_KeyDown(hwnd,wParam,lParam);
1121
1122 case WM_ERASEBKGND:
1123 return 1;
1124
1125 case WM_GETDLGCODE:
1126 return DLGC_WANTARROWS; /* Windows returns this value */
1127
1128 case WM_PAINT:
1129 return SCROLL_Paint(hwnd,wParam,lParam,SB_CTL);
1130
1131 case SBM_SETPOS:
1132 return SetScrollPos( hwnd, SB_CTL, wParam, (BOOL)lParam );
1133
1134 case SBM_GETPOS:
1135 return GetScrollPos( hwnd, SB_CTL );
1136
1137 case SBM_SETRANGE:
1138 return SCROLL_SetRange(hwnd,wParam,lParam,SB_CTL,FALSE);
1139
1140 case SBM_GETRANGE:
1141 GetScrollRange( hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam );
1142 return 0;
1143
1144 case SBM_ENABLE_ARROWS:
1145 return EnableScrollBar( hwnd, SB_CTL, wParam );
1146
1147 case SBM_SETRANGEREDRAW:
1148 return SCROLL_SetRange(hwnd,wParam,lParam,SB_CTL,TRUE);
1149
1150 case SBM_SETSCROLLINFO:
1151 return SetScrollInfo(hwnd,SB_CTL,(SCROLLINFO*)lParam,wParam);
1152
1153 case SBM_GETSCROLLINFO:
1154 return GetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam );
1155
1156 case 0x00e5:
1157 case 0x00e7:
1158 case 0x00e8:
1159 case 0x00eb:
1160 case 0x00ec:
1161 case 0x00ed:
1162 case 0x00ee:
1163 case 0x00ef:
1164 //ERR("unknown Win32 msg %04x wp=%08x lp=%08lx\n",
1165 // message, wParam, lParam );
1166 break;
1167
1168 default:
1169 return DefWindowProcA( hwnd, message, wParam, lParam );
1170 }
1171
1172 return 0;
1173}
1174
1175/* Scrollbar API */
1176
1177/*************************************************************************
1178 * SetScrollInfo (USER32.501)
1179 * SetScrollInfo32 can be used to set the position, upper bound,
1180 * lower bound, and page size of a scrollbar control.
1181 *
1182 * RETURNS
1183 * Scrollbar position
1184 *
1185 * NOTE
1186 * For 100 lines of text to be displayed in a window of 25 lines,
1187 * one would for instance use info->nMin=0, info->nMax=75
1188 * (corresponding to the 76 different positions of the window on
1189 * the text), and info->nPage=25.
1190 */
1191INT WINAPI SetScrollInfo(HWND hwnd,INT nBar,const SCROLLINFO *info,BOOL bRedraw)
1192{
1193 /* Update the scrollbar state and set action flags according to
1194 * what has to be done graphics wise. */
1195
1196 SCROLLBAR_INFO *infoPtr;
1197 UINT new_flags;
1198 INT action = 0;
1199
1200 dprintf(("USER32: SetScrollInfo"));
1201
1202 if (!(infoPtr = SCROLL_GetInfoPtr(hwnd,nBar))) return 0;
1203 if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return 0;
1204 if ((info->cbSize != sizeof(*info)) &&
1205 (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return 0;
1206
1207 /* Set the page size */
1208 if (info->fMask & SIF_PAGE)
1209 {
1210 if( infoPtr->Page != info->nPage )
1211 {
1212 infoPtr->Page = info->nPage;
1213 action |= SA_SSI_REPAINT_INTERIOR;
1214 }
1215 }
1216
1217 /* Set the scroll pos */
1218 if (info->fMask & SIF_POS)
1219 {
1220 //dsprintf(scroll, " pos=%d", info->nPos );
1221 if( infoPtr->CurVal != info->nPos )
1222 {
1223 infoPtr->CurVal = info->nPos;
1224 action |= SA_SSI_MOVE_THUMB;
1225 }
1226 }
1227
1228 /* Set the scroll range */
1229 if (info->fMask & SIF_RANGE)
1230 {
1231 /* Invalid range -> range is set to (0,0) */
1232 if ((info->nMin > info->nMax) ||
1233 ((UINT)(info->nMax - info->nMin) >= 0x80000000))
1234 {
1235 infoPtr->MinVal = 0;
1236 infoPtr->MaxVal = 0;
1237 }
1238 else
1239 {
1240 if( infoPtr->MinVal != info->nMin ||
1241 infoPtr->MaxVal != info->nMax )
1242 {
1243 action |= SA_SSI_REPAINT_INTERIOR;
1244 infoPtr->MinVal = info->nMin;
1245 infoPtr->MaxVal = info->nMax;
1246 }
1247 }
1248 }
1249
1250 /* Make sure the page size is valid */
1251
1252 if (infoPtr->Page < 0) infoPtr->Page = 0;
1253 else if (infoPtr->Page > infoPtr->MaxVal - infoPtr->MinVal + 1 )
1254 infoPtr->Page = infoPtr->MaxVal - infoPtr->MinVal + 1;
1255
1256 /* Make sure the pos is inside the range */
1257
1258 if (infoPtr->CurVal < infoPtr->MinVal)
1259 infoPtr->CurVal = infoPtr->MinVal;
1260 else if (infoPtr->CurVal > infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
1261 infoPtr->CurVal = infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 );
1262
1263 //TRACE(" new values: page=%d pos=%d min=%d max=%d\n",
1264 // infoPtr->Page, infoPtr->CurVal,
1265 // infoPtr->MinVal, infoPtr->MaxVal );
1266
1267 /* Check if the scrollbar should be hidden or disabled */
1268 if (info->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
1269 {
1270 new_flags = infoPtr->flags;
1271 if (infoPtr->MinVal >= infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
1272 {
1273 /* Hide or disable scroll-bar */
1274 if (info->fMask & SIF_DISABLENOSCROLL)
1275 {
1276 new_flags = ESB_DISABLE_BOTH;
1277 action |= SA_SSI_REFRESH;
1278 } else if (nBar != SB_CTL)
1279 {
1280 action = SA_SSI_HIDE;
1281 infoPtr->flags = 0;
1282 goto done;
1283 }
1284 } else /* Show and enable scroll-bar */
1285 {
1286 new_flags = 0;
1287 if (nBar != SB_CTL) action |= SA_SSI_SHOW;
1288 if (infoPtr->flags) action |= SA_SSI_REFRESH;
1289 }
1290
1291 if (infoPtr->flags != new_flags) /* check arrow flags */
1292 {
1293 infoPtr->flags = new_flags;
1294 action |= SA_SSI_REPAINT_ARROWS;
1295 }
1296 }
1297
1298done:
1299 /* Update scrollbar */
1300
1301 if( action & SA_SSI_HIDE )
1302 ShowScrollBar(hwnd,nBar,FALSE);
1303 else
1304 {
1305 if(action & SA_SSI_SHOW)
1306 ShowScrollBar(hwnd,nBar,TRUE);
1307
1308 if (bRedraw)
1309 {
1310 if (action & SA_SSI_REFRESH)
1311 SCROLL_RefreshScrollBar(hwnd,nBar,TRUE,TRUE);
1312 else
1313 {
1314 if (action & (SA_SSI_REPAINT_INTERIOR | SA_SSI_MOVE_THUMB))
1315 SCROLL_RefreshScrollBar(hwnd,nBar,FALSE,TRUE);
1316 if (action & SA_SSI_REPAINT_ARROWS)
1317 SCROLL_RefreshScrollBar(hwnd,nBar,TRUE,FALSE);
1318 }
1319 }
1320 }
1321
1322 /* Return current position */
1323
1324 return infoPtr->CurVal;
1325}
1326/*************************************************************************
1327 * GetScrollInfo (USER32.284)
1328 * GetScrollInfo32 can be used to retrieve the position, upper bound,
1329 * lower bound, and page size of a scrollbar control.
1330 *
1331 * RETURNS STD
1332 */
1333BOOL WINAPI GetScrollInfo(
1334 HWND hwnd /* [I] Handle of window */ ,
1335 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
1336 LPSCROLLINFO info /* [IO] (info.fMask [I] specifies which values are to retrieve) */)
1337{
1338 SCROLLBAR_INFO *infoPtr;
1339
1340 dprintf(("USER32: GetScrollInfo"));
1341
1342 if (!(infoPtr = SCROLL_GetInfoPtr(hwnd,nBar))) return FALSE;
1343 if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return FALSE;
1344 if ((info->cbSize != sizeof(*info)) &&
1345 (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return FALSE;
1346
1347 if (info->fMask & SIF_PAGE) info->nPage = infoPtr->Page;
1348 if (info->fMask & SIF_POS) info->nPos = infoPtr->CurVal;
1349 if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info)))
1350 info->nTrackPos = (SCROLL_MovingThumb && SCROLL_TrackingWin == hwnd && SCROLL_TrackingBar == nBar) ? SCROLL_TrackingVal:infoPtr->CurVal;
1351
1352 if (info->fMask & SIF_RANGE)
1353 {
1354 info->nMin = infoPtr->MinVal;
1355 info->nMax = infoPtr->MaxVal;
1356 }
1357 return (info->fMask & SIF_ALL) != 0;
1358}
1359/*************************************************************************
1360 * SetScrollPos (USER32.502)
1361 *
1362 * RETURNS
1363 * Success: Scrollbar position
1364 * Failure: 0
1365 *
1366 * REMARKS
1367 * Note the ambiguity when 0 is returned. Use GetLastError
1368 * to make sure there was an error (and to know which one).
1369 */
1370INT WINAPI SetScrollPos(
1371 HWND hwnd /* [I] Handle of window whose scrollbar will be affected */,
1372 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
1373 INT nPos /* [I] New value */,
1374 BOOL bRedraw /* [I] Should scrollbar be redrawn afterwards ? */ )
1375{
1376 SCROLLINFO info;
1377 SCROLLBAR_INFO *infoPtr;
1378 INT oldPos;
1379
1380 dprintf(("SetScrollPos %x %d %d %d", hwnd, nBar, nPos, bRedraw));
1381 if (!(infoPtr = SCROLL_GetInfoPtr(hwnd,nBar))) return 0;
1382 oldPos = infoPtr->CurVal;
1383 info.cbSize = sizeof(info);
1384 info.nPos = nPos;
1385 info.fMask = SIF_POS;
1386 SetScrollInfo( hwnd, nBar, &info, bRedraw );
1387 return oldPos;
1388}
1389/*************************************************************************
1390 * GetScrollPos (USER32.285)
1391 *
1392 * RETURNS
1393 * Success: Current position
1394 * Failure: 0
1395 *
1396 * REMARKS
1397 * Note the ambiguity when 0 is returned. Use GetLastError
1398 * to make sure there was an error (and to know which one).
1399 */
1400INT WINAPI GetScrollPos(
1401 HWND hwnd, /* [I] Handle of window */
1402 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */)
1403{
1404 SCROLLBAR_INFO *infoPtr;
1405
1406 dprintf(("GetScrollPos %x %d", hwnd, nBar));
1407
1408 infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
1409 if (!infoPtr) return 0;
1410
1411 return infoPtr->CurVal;
1412}
1413
1414/*************************************************************************
1415 * SetScrollRange (USER32.503)
1416 *
1417 * RETURNS STD
1418 */
1419BOOL WINAPI SetScrollRange(
1420 HWND hwnd, /* [I] Handle of window whose scrollbar will be affected */
1421 INT nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
1422 INT MinVal, /* [I] New minimum value */
1423 INT MaxVal, /* [I] New maximum value */
1424 BOOL bRedraw /* [I] Should scrollbar be redrawn afterwards ? */)
1425{
1426 SCROLLINFO info;
1427
1428 dprintf(("SetScrollRange %x %x %d %d %d", hwnd, nBar, MinVal, MaxVal, bRedraw));
1429 info.cbSize = sizeof(info);
1430 info.nMin = MinVal;
1431 info.nMax = MaxVal;
1432 info.fMask = SIF_RANGE;
1433 SetScrollInfo( hwnd, nBar, &info, bRedraw );
1434 return TRUE;
1435}
1436
1437/*************************************************************************
1438 * GetScrollRange (USER32.286)
1439 *
1440 * RETURNS STD
1441 */
1442BOOL WINAPI GetScrollRange(
1443 HWND hwnd, /* [I] Handle of window */
1444 INT nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
1445 LPINT lpMin, /* [O] Where to store minimum value */
1446 LPINT lpMax /* [O] Where to store maximum value */)
1447{
1448 SCROLLBAR_INFO *infoPtr;
1449
1450 infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
1451 if (!infoPtr)
1452 {
1453 if (lpMin) lpMin = 0;
1454 if (lpMax) lpMax = 0;
1455 return FALSE;
1456 }
1457 if (lpMin) *lpMin = infoPtr->MinVal;
1458 if (lpMax) *lpMax = infoPtr->MaxVal;
1459 return TRUE;
1460}
1461
1462/*************************************************************************
1463 * ShowScrollBar (USER32.532)
1464 *
1465 * RETURNS STD
1466 */
1467BOOL WINAPI ShowScrollBar(
1468 HWND hwnd, /* [I] Handle of window whose scrollbar(s) will be affected */
1469 INT nBar, /* [I] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */
1470 BOOL fShow /* [I] TRUE = show, FALSE = hide */)
1471{
1472 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
1473// BOOL fShowH = (nBar == SB_HORZ) ? 0:fShow,fShowV = (nBar == SB_VERT) ? 0:fShow;
1474 BOOL fShowH = (nBar == SB_HORZ) ? fShow : 0;
1475 BOOL fShowV = (nBar == SB_VERT) ? fShow : 0;
1476
1477 dprintf(("ShowScrollBar %04x %d %d\n", hwnd, nBar, fShow));
1478 if (!win32wnd) return FALSE;
1479
1480 switch(nBar)
1481 {
1482 case SB_CTL:
1483 ShowWindow(hwnd,fShow ? SW_SHOW:SW_HIDE);
1484 return TRUE;
1485
1486 case SB_BOTH:
1487 case SB_HORZ:
1488 if (fShow)
1489 {
1490 fShowH = !(win32wnd->getStyle() & WS_HSCROLL);
1491 win32wnd->setStyle(win32wnd->getStyle() | WS_HSCROLL);
1492 }
1493 else /* hide it */
1494 {
1495 fShowH = (win32wnd->getStyle() & WS_HSCROLL);
1496 win32wnd->setStyle(win32wnd->getStyle() & ~WS_HSCROLL);
1497 }
1498 if( nBar == SB_HORZ )
1499 {
1500 fShowV = FALSE;
1501 break;
1502 }
1503 /* fall through */
1504
1505 case SB_VERT:
1506 if (fShowV)
1507 {
1508 fShowV = !(win32wnd->getStyle() & WS_VSCROLL);
1509 win32wnd->setStyle(win32wnd->getStyle() | WS_VSCROLL);
1510 }
1511 else /* hide it */
1512 {
1513 fShowV = (win32wnd->getStyle() & WS_VSCROLL);
1514 win32wnd->setStyle(win32wnd->getStyle() & ~WS_VSCROLL);
1515 }
1516 if ( nBar == SB_VERT )
1517 fShowH = FALSE;
1518 break;
1519
1520 default:
1521 return TRUE; /* Nothing to do! */
1522 }
1523
1524 if( fShowH || fShowV ) /* frame has been changed, let the window redraw itself */
1525 {
1526 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
1527 | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
1528 }
1529
1530 return TRUE;
1531}
1532
1533/*************************************************************************
1534 * EnableScrollBar (USER32.171)
1535 */
1536BOOL WINAPI EnableScrollBar( HWND hwnd, INT nBar, UINT flags)
1537{
1538 BOOL bFineWithMe;
1539 SCROLLBAR_INFO *infoPtr;
1540
1541 dprintf(("EnableScrollBar %04x %d %d\n", hwnd, nBar, flags));
1542
1543 flags &= ESB_DISABLE_BOTH;
1544
1545 if (nBar == SB_BOTH)
1546 {
1547 if (!(infoPtr = SCROLL_GetInfoPtr( hwnd, SB_VERT ))) return FALSE;
1548 if (!(bFineWithMe = (infoPtr->flags == flags)) )
1549 {
1550 infoPtr->flags = flags;
1551 SCROLL_RefreshScrollBar( hwnd, SB_VERT, TRUE, TRUE );
1552 }
1553 nBar = SB_HORZ;
1554 }
1555 else
1556 bFineWithMe = TRUE;
1557
1558 if (!(infoPtr = SCROLL_GetInfoPtr( hwnd, nBar ))) return FALSE;
1559 if (bFineWithMe && infoPtr->flags == flags) return FALSE;
1560 infoPtr->flags = flags;
1561
1562 SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
1563 return TRUE;
1564}
1565
1566//CB: not listed in user32.exp -> don't know the id!
1567
1568BOOL WINAPI GetScrollBarInfo(HWND hwnd,LONG idObject,PSCROLLBARINFO psbi)
1569{
1570 if (!psbi || (psbi->cbSize != sizeof(SCROLLBARINFO)))
1571 {
1572 SetLastError(ERROR_INVALID_PARAMETER);
1573
1574 return FALSE;
1575 }
1576
1577 INT nBar,arrowSize;
1578
1579 switch (idObject)
1580 {
1581 case OBJID_CLIENT:
1582 nBar = SB_CTL;
1583 break;
1584
1585 case OBJID_HSCROLL:
1586 nBar = SB_HORZ;
1587 break;
1588
1589 case OBJID_VSCROLL:
1590 nBar = SB_VERT;
1591 break;
1592
1593 default:
1594 return FALSE;
1595 }
1596
1597 SCROLL_GetScrollBarRect(hwnd,nBar,&psbi->rcScrollBar,&arrowSize,&psbi->dxyLineButton,&psbi->xyThumbTop);
1598 psbi->xyThumbBottom = psbi->xyThumbTop+psbi->dxyLineButton;
1599 psbi->bogus = 0; //CB: undocumented!
1600 psbi->rgstate[0] = IsWindowVisible(hwnd) ? STATE_SYSTEM_INVISIBLE:0;
1601 psbi->rgstate[1] = psbi->rgstate[2] = psbi->rgstate[3] = psbi->rgstate[4] = psbi->rgstate[5] = psbi->rgstate[0]; //CB: todo
1602
1603 return TRUE;
1604}
1605//******************************************************************************
1606//******************************************************************************
1607BOOL SCROLLBAR_Register()
1608{
1609 WNDCLASSA wndClass;
1610
1611//SvL: Don't check this now
1612// if (GlobalFindAtomA(SCROLLBARCLASSNAME)) return FALSE;
1613
1614 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
1615 wndClass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW | CS_PARENTDC;
1616 wndClass.lpfnWndProc = (WNDPROC)ScrollBarWndProc;
1617 wndClass.cbClsExtra = 0;
1618 wndClass.cbWndExtra = sizeof(SCROLLBAR_INFO);
1619 wndClass.hCursor = LoadCursorA(0,IDC_ARROWA);
1620 wndClass.hbrBackground = (HBRUSH)0;
1621 wndClass.lpszClassName = SCROLLBARCLASSNAME;
1622
1623 return RegisterClassA(&wndClass);
1624}
1625//******************************************************************************
1626//******************************************************************************
1627BOOL SCROLLBAR_Unregister()
1628{
1629 if (GlobalFindAtomA(SCROLLBARCLASSNAME))
1630 return UnregisterClassA(SCROLLBARCLASSNAME,(HINSTANCE)NULL);
1631 else return FALSE;
1632}
1633//******************************************************************************
1634//******************************************************************************
1635
Note: See TracBrowser for help on using the repository browser.