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

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

menu and frame changes

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