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

Last change on this file since 1194 was 1184, checked in by cbratschi, 26 years ago

resource and other fixes

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