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

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

scrollbar WINE port

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