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

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

scrollbar updates

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