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

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

merged with WINE, other fixes

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