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

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

hook + scrollbar bugfixes

File size: 55.3 KB
Line 
1/* $Id: scroll.cpp,v 1.8 1999-10-15 09:26:23 sandervl Exp $ */
2/*
3 * Scrollbar control
4 *
5 * Copyright 1999 Christoph Bratschi (ported from WINE)
6 *
7 * Copyright 1993 Martin Ayotte
8 * Copyright 1994, 1996 Alexandre Julliard
9 *
10 * 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//SvL: BUGFIX: Send WM_NCCREATE to defwndproc, return value 0 cancels window creation!
1117// if (message >= WM_USER)
1118 //WARN("unknown msg %04x wp=%04x lp=%08lx\n",
1119 // message, wParam, lParam );
1120 return DefWindowProcA( hwnd, message, wParam, lParam );
1121 }
1122 return 0;
1123}
1124
1125
1126/*************************************************************************
1127 * SetScrollInfo32 (USER32.501)
1128 * SetScrollInfo32 can be used to set the position, upper bound,
1129 * lower bound, and page size of a scrollbar control.
1130 *
1131 * RETURNS
1132 * Scrollbar position
1133 *
1134 * NOTE
1135 * For 100 lines of text to be displayed in a window of 25 lines,
1136 * one would for instance use info->nMin=0, info->nMax=75
1137 * (corresponding to the 76 different positions of the window on
1138 * the text), and info->nPage=25.
1139 */
1140INT WINAPI SetScrollInfo(
1141 HWND hwnd /* [I] Handle of window whose scrollbar will be affected */,
1142 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
1143 const SCROLLINFO *info /* [I] Specifies what to change and new values */,
1144 BOOL bRedraw /* [I] Should scrollbar be redrawn afterwards ? */)
1145{
1146 Win32BaseWindow *window;
1147 INT action;
1148 INT retVal;
1149
1150 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
1151 if(!window && nBar != SB_CTL) {
1152 dprintf(("SetScrollInfo window not found!"));
1153 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1154 return FALSE;
1155 }
1156 if(window) {
1157 return window->setScrollInfo(nBar, (SCROLLINFO *)info, bRedraw);
1158 }
1159
1160 retVal = SCROLL_SetScrollInfo( hwnd, nBar, info, &action );
1161 if( action & SA_SSI_HIDE )
1162 SCROLL_ShowScrollBar( hwnd, nBar, FALSE, FALSE );
1163 else
1164 {
1165 if( action & SA_SSI_SHOW )
1166 if( SCROLL_ShowScrollBar( hwnd, nBar, TRUE, TRUE ) )
1167 return retVal; /* SetWindowPos() already did the painting */
1168
1169 if( bRedraw && (action & SA_SSI_REFRESH))
1170 SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
1171 else if( action & SA_SSI_REPAINT_ARROWS )
1172 SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, FALSE );
1173 }
1174 return retVal;
1175}
1176//******************************************************************************
1177//******************************************************************************
1178INT SCROLL_SetScrollInfo( HWND hwnd, INT nBar,
1179 const SCROLLINFO *info, INT *action )
1180{
1181 /* Update the scrollbar state and set action flags according to
1182 * what has to be done graphics wise. */
1183
1184 SCROLLBAR_INFO *infoPtr;
1185 UINT new_flags;
1186
1187 *action = 0;
1188
1189 if (!(infoPtr = SCROLL_GetScrollInfo(hwnd, nBar))) return 0;
1190 if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return 0;
1191 if ((info->cbSize != sizeof(*info)) &&
1192 (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return 0;
1193
1194 /* Set the page size */
1195 if (info->fMask & SIF_PAGE)
1196 {
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 /* Invalid range -> range is set to (0,0) */
1219 if ((info->nMin > info->nMax) ||
1220 ((UINT)(info->nMax - info->nMin) >= 0x80000000))
1221 {
1222 infoPtr->MinVal = 0;
1223 infoPtr->MaxVal = 0;
1224 }
1225 else
1226 {
1227 if( infoPtr->MinVal != info->nMin ||
1228 infoPtr->MaxVal != info->nMax )
1229 {
1230 *action |= SA_SSI_REFRESH;
1231 infoPtr->MinVal = info->nMin;
1232 infoPtr->MaxVal = info->nMax;
1233 }
1234 }
1235 }
1236
1237 /* Make sure the page size is valid */
1238
1239 if (infoPtr->Page < 0) infoPtr->Page = 0;
1240 else if (infoPtr->Page > infoPtr->MaxVal - infoPtr->MinVal + 1 )
1241 infoPtr->Page = infoPtr->MaxVal - infoPtr->MinVal + 1;
1242
1243 /* Make sure the pos is inside the range */
1244
1245 if (infoPtr->CurVal < infoPtr->MinVal)
1246 infoPtr->CurVal = infoPtr->MinVal;
1247 else if (infoPtr->CurVal > infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
1248 infoPtr->CurVal = infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 );
1249
1250 //TRACE(" new values: page=%d pos=%d min=%d max=%d\n",
1251 // infoPtr->Page, infoPtr->CurVal,
1252 // infoPtr->MinVal, infoPtr->MaxVal );
1253
1254 /* Check if the scrollbar should be hidden or disabled */
1255 if (info->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
1256 {
1257 new_flags = infoPtr->flags;
1258 if (infoPtr->MinVal >= infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
1259 {
1260 /* Hide or disable scroll-bar */
1261 if (info->fMask & SIF_DISABLENOSCROLL)
1262 {
1263 new_flags = ESB_DISABLE_BOTH;
1264 *action |= SA_SSI_REFRESH;
1265 }
1266 else if (nBar != SB_CTL)
1267 {
1268 *action = SA_SSI_HIDE;
1269 goto done;
1270 }
1271 }
1272 else /* Show and enable scroll-bar */
1273 {
1274 new_flags = 0;
1275 if (nBar != SB_CTL)
1276 *action |= SA_SSI_SHOW;
1277 }
1278
1279 if (infoPtr->flags != new_flags) /* check arrow flags */
1280 {
1281 infoPtr->flags = new_flags;
1282 *action |= SA_SSI_REPAINT_ARROWS;
1283 }
1284 }
1285
1286done:
1287 /* Return current position */
1288
1289 return infoPtr->CurVal;
1290}
1291/*************************************************************************
1292 * GetScrollInfo32 (USER32.284)
1293 * GetScrollInfo32 can be used to retrieve the position, upper bound,
1294 * lower bound, and page size of a scrollbar control.
1295 *
1296 * RETURNS STD
1297 */
1298BOOL WINAPI GetScrollInfo(
1299 HWND hwnd /* [I] Handle of window */ ,
1300 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
1301 LPSCROLLINFO info /* [IO] (info.fMask [I] specifies which values are to retrieve) */)
1302{
1303 SCROLLBAR_INFO *infoPtr;
1304
1305 if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
1306 if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return FALSE;
1307 if ((info->cbSize != sizeof(*info)) &&
1308 (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return FALSE;
1309
1310 if (info->fMask & SIF_PAGE) info->nPage = infoPtr->Page;
1311 if (info->fMask & SIF_POS) info->nPos = infoPtr->CurVal;
1312 if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info)))
1313 info->nTrackPos = (SCROLL_TrackingWin==hwnd) ? SCROLL_TrackingVal : infoPtr->CurVal;
1314 if (info->fMask & SIF_RANGE)
1315 {
1316 info->nMin = infoPtr->MinVal;
1317 info->nMax = infoPtr->MaxVal;
1318 }
1319 return (info->fMask & SIF_ALL) != 0;
1320}
1321/*************************************************************************
1322 * SetScrollPos32 (USER32.502)
1323 *
1324 * RETURNS
1325 * Success: Scrollbar position
1326 * Failure: 0
1327 *
1328 * REMARKS
1329 * Note the ambiguity when 0 is returned. Use GetLastError
1330 * to make sure there was an error (and to know which one).
1331 */
1332INT WINAPI SetScrollPos(
1333 HWND hwnd /* [I] Handle of window whose scrollbar will be affected */,
1334 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
1335 INT nPos /* [I] New value */,
1336 BOOL bRedraw /* [I] Should scrollbar be redrawn afterwards ? */ )
1337{
1338 SCROLLINFO info;
1339 SCROLLBAR_INFO *infoPtr;
1340 INT oldPos;
1341
1342 dprintf(("SetScrollPos %x %d %d %d", hwnd, nBar, nPos, bRedraw));
1343 if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return 0;
1344 oldPos = infoPtr->CurVal;
1345 info.cbSize = sizeof(info);
1346 info.nPos = nPos;
1347 info.fMask = SIF_POS;
1348 SetScrollInfo( hwnd, nBar, &info, bRedraw );
1349 return oldPos;
1350}
1351/*************************************************************************
1352 * GetScrollPos32 (USER32.285)
1353 *
1354 * RETURNS
1355 * Success: Current position
1356 * Failure: 0
1357 *
1358 * REMARKS
1359 * Note the ambiguity when 0 is returned. Use GetLastError
1360 * to make sure there was an error (and to know which one).
1361 */
1362INT WINAPI GetScrollPos(
1363 HWND hwnd, /* [I] Handle of window */
1364 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */)
1365{
1366 SCROLLBAR_INFO *infoPtr;
1367
1368 dprintf(("GetScrollPos %x %d", hwnd, nBar));
1369
1370 infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
1371 if (!infoPtr) return 0;
1372
1373 return infoPtr->CurVal;
1374}
1375/*************************************************************************
1376 * SetScrollRange32 (USER32.503)
1377 *
1378 * RETURNS STD
1379 */
1380BOOL WINAPI SetScrollRange(
1381 HWND hwnd, /* [I] Handle of window whose scrollbar will be affected */
1382 INT nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
1383 INT MinVal, /* [I] New minimum value */
1384 INT MaxVal, /* [I] New maximum value */
1385 BOOL bRedraw /* [I] Should scrollbar be redrawn afterwards ? */)
1386{
1387 SCROLLINFO info;
1388
1389 dprintf(("SetScrollRange %x %x %d %d %d", hwnd, nBar, MinVal, MaxVal, bRedraw));
1390 info.cbSize = sizeof(info);
1391 info.nMin = MinVal;
1392 info.nMax = MaxVal;
1393 info.fMask = SIF_RANGE;
1394 SetScrollInfo( hwnd, nBar, &info, bRedraw );
1395 return TRUE;
1396}
1397/*************************************************************************
1398 * SCROLL_SetNCSbState
1399 *
1400 * Updates both scrollbars at the same time. Used by MDI CalcChildScroll().
1401 */
1402INT SCROLL_SetNCSbState(HWND hwnd, int vMin, int vMax, int vPos,
1403 int hMin, int hMax, int hPos)
1404{
1405 INT vA, hA;
1406 SCROLLINFO vInfo, hInfo;
1407
1408 vInfo.cbSize = hInfo.cbSize = sizeof(SCROLLINFO);
1409 vInfo.nMin = vMin; hInfo.nMin = hMin;
1410 vInfo.nMax = vMax; hInfo.nMax = hMax;
1411 vInfo.nPos = vPos; hInfo.nPos = hPos;
1412 vInfo.fMask = hInfo.fMask = SIF_RANGE | SIF_POS;
1413
1414 SCROLL_SetScrollInfo( hwnd, SB_VERT, &vInfo, &vA );
1415 SCROLL_SetScrollInfo( hwnd, SB_HORZ, &hInfo, &hA );
1416
1417 if( !SCROLL_ShowScrollBar( hwnd, SB_BOTH,
1418 (hA & SA_SSI_SHOW),(vA & SA_SSI_SHOW) ) )
1419 {
1420 /* SetWindowPos() wasn't called, just redraw the scrollbars if needed */
1421 if( vA & SA_SSI_REFRESH )
1422 SCROLL_RefreshScrollBar( hwnd, SB_VERT, FALSE, TRUE );
1423
1424 if( hA & SA_SSI_REFRESH )
1425 SCROLL_RefreshScrollBar( hwnd, SB_HORZ, FALSE, TRUE );
1426 }
1427 return 0;
1428}
1429
1430
1431/*************************************************************************
1432 * GetScrollRange32 (USER32.286)
1433 *
1434 * RETURNS STD
1435 */
1436BOOL WINAPI GetScrollRange(
1437 HWND hwnd, /* [I] Handle of window */
1438 INT nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
1439 LPINT lpMin, /* [O] Where to store minimum value */
1440 LPINT lpMax /* [O] Where to store maximum value */)
1441{
1442 SCROLLBAR_INFO *infoPtr;
1443
1444 infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
1445 if (!infoPtr)
1446 {
1447 if (lpMin) lpMin = 0;
1448 if (lpMax) lpMax = 0;
1449 return FALSE;
1450 }
1451 if (lpMin) *lpMin = infoPtr->MinVal;
1452 if (lpMax) *lpMax = infoPtr->MaxVal;
1453 return TRUE;
1454}
1455/*************************************************************************
1456 * SCROLL_ShowScrollBar()
1457 *
1458 * Back-end for ShowScrollBar(). Returns FALSE if no action was taken.
1459 * NOTE: fShowV/fShowH must be zero when nBar is SB_HORZ/SB_VERT.
1460 */
1461BOOL SCROLL_ShowScrollBar(HWND hwnd, INT nBar,
1462 BOOL fShowH, BOOL fShowV )
1463{
1464 BOOL retvalue = FALSE;
1465 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
1466
1467 //TRACE("hwnd=%04x bar=%d horz=%d, vert=%d\n",
1468 // hwnd, nBar, fShowH, fShowV );
1469
1470 switch(nBar)
1471 {
1472 case SB_CTL:
1473 ShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE );
1474 retvalue = TRUE;
1475 goto END;
1476
1477 case SB_BOTH:
1478 case SB_HORZ:
1479 if (fShowH)
1480 {
1481 fShowH = !(dwStyle & WS_HSCROLL);
1482 dwStyle |= WS_HSCROLL;
1483 }
1484 else /* hide it */
1485 {
1486 fShowH = (dwStyle & WS_HSCROLL);
1487 dwStyle &= ~WS_HSCROLL;
1488 }
1489 SetWindowLongA(hwnd,GWL_STYLE,dwStyle);
1490 if( nBar == SB_HORZ ) {
1491 fShowV = FALSE;
1492 break;
1493 }
1494 /* fall through */
1495
1496 case SB_VERT:
1497 if (fShowV)
1498 {
1499 fShowV = !(dwStyle & WS_VSCROLL);
1500 dwStyle |= WS_VSCROLL;
1501 }
1502 else /* hide it */
1503 {
1504 fShowV = (dwStyle & WS_VSCROLL);
1505 dwStyle &= ~WS_VSCROLL;
1506 }
1507 SetWindowLongA(hwnd,GWL_STYLE,dwStyle);
1508 if ( nBar == SB_VERT )
1509 fShowH = FALSE;
1510 break;
1511
1512 default:
1513 retvalue = FALSE; /* Nothing to do! */
1514 goto END;
1515 }
1516
1517 if( fShowH || fShowV ) /* frame has been changed, let the window redraw itself */
1518 {
1519 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
1520 | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
1521 retvalue = TRUE;
1522 goto END;
1523 }
1524
1525 retvalue = FALSE; /* no frame changes */
1526END:
1527 return retvalue;
1528}
1529
1530
1531/*************************************************************************
1532 * ShowScrollBar32 (USER32.532)
1533 *
1534 * RETURNS STD
1535 */
1536BOOL WINAPI ShowScrollBar(
1537 HWND hwnd, /* [I] Handle of window whose scrollbar(s) will be affected */
1538 INT nBar, /* [I] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */
1539 BOOL fShow /* [I] TRUE = show, FALSE = hide */)
1540{
1541 Win32BaseWindow *window;
1542
1543 dprintf(("ShowScrollBar %04x %d %d\n", hwnd, nBar, fShow));
1544
1545 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
1546 if(!window && nBar != SB_CTL) {
1547 dprintf(("ShowScrollBar window not found!"));
1548 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1549 return 0;
1550 }
1551 if(nBar != SB_CTL || (window->getStyle() & (WM_HSCROLL|WM_VSCROLL) != 0))
1552 {
1553 BOOL rc;
1554
1555 if(nBar == SB_HORZ || nBar == SB_BOTH)
1556 rc = OSLibWinShowScrollBar(window->getOS2FrameWindowHandle(),
1557 window->getHorzScrollHandle(),
1558 OSLIB_HSCROLL, fShow);
1559
1560 if(nBar == SB_VERT || ( rc == TRUE && nBar == SB_BOTH))
1561 rc = OSLibWinShowScrollBar(window->getOS2FrameWindowHandle(),
1562 window->getVertScrollHandle(),
1563 OSLIB_VSCROLL, fShow);
1564
1565 return rc;
1566 }
1567
1568 SCROLL_ShowScrollBar( hwnd, nBar, (nBar == SB_VERT) ? 0 : fShow,
1569 (nBar == SB_HORZ) ? 0 : fShow );
1570 return TRUE;
1571}
1572/*************************************************************************
1573 * EnableScrollBar32 (USER32.171)
1574 */
1575BOOL WINAPI EnableScrollBar( HWND hwnd, INT nBar, UINT flags)
1576{
1577 Win32BaseWindow *window;
1578 BOOL bFineWithMe;
1579 SCROLLBAR_INFO *infoPtr;
1580
1581 dprintf(("EnableScrollBar %04x %d %d\n", hwnd, nBar, flags));
1582
1583 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
1584 if(!window && nBar != SB_CTL) {
1585 dprintf(("EnableScrollBar window not found!"));
1586 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1587 return 0;
1588 }
1589 if(nBar != SB_CTL || (window->getStyle() & (WM_HSCROLL|WM_VSCROLL) != 0))
1590 {
1591 BOOL fEnable, rc;
1592
1593 //hwnd = parent window with default scrollbar(s)
1594 switch(flags) {
1595 case ESB_ENABLE_BOTH:
1596 fEnable = TRUE;
1597 break;
1598 case ESB_DISABLE_BOTH:
1599 case ESB_DISABLE_RTDN:
1600 case ESB_DISABLE_LTUP:
1601 fEnable = FALSE;
1602 break;
1603 default:
1604 SetLastError(ERROR_INVALID_PARAMETER);
1605 return 0;
1606 }
1607 if(nBar == SB_HORZ || nBar == SB_BOTH)
1608 rc = OSLibWinEnableScrollBar(window->getOS2FrameWindowHandle(), OSLIB_HSCROLL, fEnable);
1609
1610 if(nBar == SB_VERT || ( rc == TRUE && nBar == SB_BOTH))
1611 rc = OSLibWinEnableScrollBar(window->getOS2FrameWindowHandle(), OSLIB_VSCROLL, fEnable);
1612
1613 return rc;
1614 }
1615 flags &= ESB_DISABLE_BOTH;
1616
1617 if (nBar == SB_BOTH)
1618 {
1619 if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, SB_VERT ))) return FALSE;
1620 if (!(bFineWithMe = (infoPtr->flags == flags)) )
1621 {
1622 infoPtr->flags = flags;
1623 SCROLL_RefreshScrollBar( hwnd, SB_VERT, TRUE, TRUE );
1624 }
1625 nBar = SB_HORZ;
1626 }
1627 else
1628 bFineWithMe = TRUE;
1629
1630 if (!(infoPtr = SCROLL_GetScrollInfo( hwnd, nBar ))) return FALSE;
1631 if (bFineWithMe && infoPtr->flags == flags) return FALSE;
1632 infoPtr->flags = flags;
1633
1634 SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
1635 return TRUE;
1636}
1637//******************************************************************************
1638//******************************************************************************
1639BOOL SCROLLBAR_Register()
1640{
1641 WNDCLASSA wndClass;
1642
1643 if (GlobalFindAtomA(SCROLLBARCLASSNAME)) return FALSE;
1644
1645 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
1646 wndClass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW | CS_PARENTDC;
1647 wndClass.lpfnWndProc = (WNDPROC)ScrollBarWndProc;
1648 wndClass.cbClsExtra = 0;
1649 wndClass.cbWndExtra = sizeof(SCROLLBAR_INFO);
1650 wndClass.hCursor = LoadCursorA(0,IDC_ARROWA);
1651 wndClass.hbrBackground = (HBRUSH)0;
1652 wndClass.lpszClassName = SCROLLBARCLASSNAME;
1653
1654 return RegisterClassA(&wndClass);
1655}
1656//******************************************************************************
1657//******************************************************************************
1658BOOL SCROLLBAR_Unregister()
1659{
1660 if (GlobalFindAtomA(SCROLLBARCLASSNAME))
1661 return UnregisterClassA(SCROLLBARCLASSNAME,(HINSTANCE)NULL);
1662 else return FALSE;
1663}
1664//******************************************************************************
1665//******************************************************************************
1666
Note: See TracBrowser for help on using the repository browser.