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

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

wm_activate fixes, scrollbar fix, drawframe fix

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