source: trunk/src/user32/scroll.cpp@ 1159

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

EB's fixes + scrollbar changes

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