Release 941030
[wine/multimedia.git] / controls / scroll.c
blob74be05004b1689ba7989a807538e9e48aa15fb80
1 /*
2 * Interface code to SCROLLBAR widget
4 * Copyright Martin Ayotte, 1993
6 * Small fixes and implemented SB_THUMBPOSITION
7 * by Peter Broadhurst, 940611
8 */
10 static char Copyright[] = "Copyright Martin Ayotte, 1993";
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include "windows.h"
17 #include "sysmetrics.h"
18 #include "scroll.h"
19 #include "heap.h"
20 #include "win.h"
21 #include "prototypes.h"
22 #include "stddebug.h"
23 /* #define DEBUG_SCROLL */
24 /* #undef DEBUG_SCROLL */
25 #include "debug.h"
28 HBITMAP hUpArrow = 0;
29 HBITMAP hDnArrow = 0;
30 HBITMAP hLfArrow = 0;
31 HBITMAP hRgArrow = 0;
32 HBITMAP hUpArrowD = 0;
33 HBITMAP hDnArrowD = 0;
34 HBITMAP hLfArrowD = 0;
35 HBITMAP hRgArrowD = 0;
37 /* windows/graphics.c */
38 extern void GRAPH_DrawReliefRect( HDC hdc, RECT *rect,
39 int thickness, BOOL pressed );
41 LPHEADSCROLL ScrollBarGetWindowAndStorage(HWND hWnd, WND **wndPtr);
42 LPHEADSCROLL ScrollBarGetStorageHeader(HWND hWnd);
43 LPHEADSCROLL GetScrollObjectStruct(HWND hWnd, int nBar);
44 void ScrollBarButtonDown(HWND hWnd, int nBar, int x, int y);
45 void ScrollBarButtonUp(HWND hWnd, int nBar, int x, int y);
46 void ScrollBarMouseMove(HWND hWnd, int nBar, WORD wParam, int x, int y);
47 void StdDrawScrollBar(HWND hWnd, HDC hDC, int nBar, LPRECT lprect, LPHEADSCROLL lphs);
48 int CreateScrollBarStruct(HWND hWnd);
49 void NC_CreateScrollBars(HWND hWnd);
50 LPHEADSCROLL AllocScrollBar(DWORD dwStyle, int width, int height);
53 /***********************************************************************
54 * WIDGETS_ScrollBarWndProc
56 LONG ScrollBarWndProc( HWND hWnd, WORD message, WORD wParam, LONG lParam )
58 WND *wndPtr;
59 LPHEADSCROLL lphs;
60 PAINTSTRUCT ps;
61 HDC hDC;
62 RECT rect;
63 LPCREATESTRUCT lpCreat;
64 POINT *pt;
65 pt=(POINT*)&lParam;
66 switch(message) {
67 case WM_CREATE:
68 lpCreat = (LPCREATESTRUCT)lParam;
69 if (lpCreat->style & SBS_VERT) {
70 if (lpCreat->style & SBS_LEFTALIGN)
71 SetWindowPos(hWnd, 0, 0, 0, 16, lpCreat->cy,
72 SWP_NOZORDER | SWP_NOMOVE);
73 if (lpCreat->style & SBS_RIGHTALIGN)
74 SetWindowPos(hWnd, 0, lpCreat->x + lpCreat->cx - 16,
75 lpCreat->y, 16, lpCreat->cy, SWP_NOZORDER);
77 if (lpCreat->style & SBS_HORZ) {
78 if (lpCreat->style & SBS_TOPALIGN)
79 SetWindowPos(hWnd, 0, 0, 0, lpCreat->cx, 16,
80 SWP_NOZORDER | SWP_NOMOVE);
81 if (lpCreat->style & SBS_BOTTOMALIGN)
82 SetWindowPos(hWnd, 0, lpCreat->x,
83 lpCreat->y + lpCreat->cy - 16,
84 lpCreat->cx, 16, SWP_NOZORDER);
86 CreateScrollBarStruct(hWnd);
87 dprintf_scroll(stddeb,"ScrollBar Creation !\n");
88 return 0;
89 case WM_DESTROY:
90 lphs = ScrollBarGetWindowAndStorage(hWnd, &wndPtr);
91 if (lphs == 0) return 0;
92 dprintf_scroll(stddeb,"ScrollBar WM_DESTROY %p !\n", lphs);
93 free(lphs);
94 *((LPHEADSCROLL *)&wndPtr->wExtra[1]) = 0;
95 return 0;
97 case WM_LBUTTONDOWN:
98 SetCapture(hWnd);
99 ScrollBarButtonDown(hWnd, SB_CTL, pt->x,pt->y);
100 break;
101 case WM_LBUTTONUP:
102 ReleaseCapture();
103 ScrollBarButtonUp(hWnd, SB_CTL, pt->x,pt->y);
104 break;
106 case WM_MOUSEMOVE:
107 ScrollBarMouseMove(hWnd, SB_CTL, wParam, pt->x,pt->y);
108 break;
109 case WM_KEYDOWN:
110 case WM_KEYUP:
111 case WM_CHAR:
112 lphs = ScrollBarGetWindowAndStorage(hWnd, &wndPtr);
113 return(SendMessage(wndPtr->hwndParent, message, wParam, lParam));
115 case WM_TIMER:
116 dprintf_scroll(stddeb,"ScrollBar WM_TIMER wParam=%X lParam=%lX !\n", wParam, lParam);
117 lphs = ScrollBarGetWindowAndStorage(hWnd, &wndPtr);
118 KillTimer(hWnd, wParam);
119 switch(lphs->ButtonDown) {
120 case 0:
121 lphs->TimerPending = FALSE;
122 return 0;
123 case 1:
124 case 3:
125 SendMessage(wndPtr->hwndParent, lphs->Direction,
126 SB_LINEUP, MAKELONG(0, hWnd));
127 break;
128 case 2:
129 case 4:
130 SendMessage(wndPtr->hwndParent, lphs->Direction,
131 SB_LINEDOWN, MAKELONG(0, hWnd));
132 break;
133 case 5:
134 SendMessage(wndPtr->hwndParent, lphs->Direction,
135 SB_PAGEUP, MAKELONG(0, hWnd));
136 break;
137 case 6:
138 SendMessage(wndPtr->hwndParent, lphs->Direction,
139 SB_PAGEDOWN, MAKELONG(0, hWnd));
140 break;
142 SetTimer(hWnd, 1, 100, NULL);
143 return 0;
145 case WM_SETREDRAW:
146 #ifdef DEBUG_SCROLL
147 printf("ScrollBar WM_SETREDRAW hWnd=%04X w=%04X !\n", hWnd, wParam);
148 #endif
149 lphs = ScrollBarGetStorageHeader(hWnd);
150 if (lphs == NULL) return 0;
151 lphs->bRedrawFlag = wParam;
152 break;
154 case WM_PAINT:
155 hDC = BeginPaint(hWnd, &ps);
156 lphs = ScrollBarGetStorageHeader(hWnd);
157 if (lphs != NULL && lphs->bRedrawFlag) {
158 GetClientRect(hWnd, &rect);
159 StdDrawScrollBar(hWnd, hDC, SB_CTL, &rect, lphs);
161 EndPaint(hWnd, &ps);
162 break;
163 default:
164 return DefWindowProc( hWnd, message, wParam, lParam );
166 return(0);
171 void ScrollBarButtonDown(HWND hWnd, int nBar, int x, int y)
173 LPHEADSCROLL lphs;
174 HWND hWndParent;
175 RECT rect;
176 int width, height;
177 LONG dwOwner;
178 lphs = GetScrollObjectStruct(hWnd, nBar);
179 if (nBar == SB_CTL) {
180 hWndParent = GetParent(hWnd);
181 dwOwner = MAKELONG(0, lphs->hWndOwner);
182 dprintf_scroll(stddeb,"ScrollBarButtonDown SB_CTL // x=%d y=%d\n", x, y);
184 else {
185 hWndParent = hWnd;
186 dwOwner = 0L;
187 dprintf_scroll(stddeb,"ScrollBarButtonDown SB_?SCROLL // x=%d y=%d\n", x, y);
190 SetFocus(lphs->hWndOwner);
192 CopyRect(&rect, &lphs->rect);
193 dprintf_scroll(stddeb,"ScrollDown / x=%d y=%d left=%d top=%d right=%d bottom=%d \n",
194 x, y, rect.left, rect.top, rect.right, rect.bottom);
195 if (lphs->Direction == WM_VSCROLL) {
196 width = rect.right - rect.left;
197 if (y <= lphs->rectUp.bottom) {
198 lphs->ButtonDown = 1;
199 InvalidateRect(lphs->hWndOwner, &lphs->rectUp, TRUE);
200 dprintf_scroll(stddeb,"ScrollBarButtonDown send SB_LINEUP\n");
201 SendMessage(hWndParent, lphs->Direction,
202 SB_LINEUP, dwOwner);
204 if (y >= lphs->rectDown.top) {
205 lphs->ButtonDown = 2;
206 InvalidateRect(lphs->hWndOwner, &lphs->rectDown, TRUE);
207 dprintf_scroll(stddeb,"ScrollBarButtonDown send SB_LINEDOWN\n");
208 SendMessage(hWndParent, lphs->Direction,
209 SB_LINEDOWN, dwOwner);
211 if (y > lphs->rectUp.bottom && y < (lphs->CurPix + width)) {
212 lphs->ButtonDown = 5;
213 dprintf_scroll(stddeb,"ScrollBarButtonDown send SB_PAGEUP\n");
214 SendMessage(hWndParent, lphs->Direction,
215 SB_PAGEUP, dwOwner);
217 if (y < lphs->rectDown.top && y > (lphs->CurPix + (width << 1))) {
218 lphs->ButtonDown = 6;
219 dprintf_scroll(stddeb,"ScrollBarButtonDown send SB_PAGEDOWN\n");
220 SendMessage(hWndParent, lphs->Direction,
221 SB_PAGEDOWN, dwOwner);
223 if (lphs->MaxPix > 0 && y > (lphs->CurPix + width) &&
224 y < (lphs->CurPix + (width << 1))) {
225 lphs->ThumbActive = TRUE;
226 dprintf_scroll(stddeb,"THUMB DOWN !\n");
229 else {
230 height = rect.bottom - rect.top;
231 if (x <= lphs->rectUp.right) {
232 lphs->ButtonDown = 3;
233 InvalidateRect(lphs->hWndOwner, &lphs->rectUp, TRUE);
234 dprintf_scroll(stddeb,"ScrollBarButtonDown send SB_LINEUP\n");
235 SendMessage(hWndParent, lphs->Direction,
236 SB_LINEUP, dwOwner);
238 if (x >= lphs->rectDown.left) {
239 lphs->ButtonDown = 4;
240 InvalidateRect(lphs->hWndOwner, &lphs->rectDown, TRUE);
241 dprintf_scroll(stddeb,"ScrollBarButtonDown send SB_LINEDOWN\n");
242 SendMessage(hWndParent, lphs->Direction,
243 SB_LINEDOWN, dwOwner);
245 if (x > lphs->rectUp.right && x < (lphs->CurPix + height)) {
246 lphs->ButtonDown = 5;
247 dprintf_scroll(stddeb,"ScrollBarButtonDown send SB_PAGEUP\n");
248 SendMessage(hWndParent, lphs->Direction,
249 SB_PAGEUP, dwOwner);
251 if (x < lphs->rectDown.left && x > (lphs->CurPix + (height << 1))) {
252 lphs->ButtonDown = 6;
253 dprintf_scroll(stddeb,"ScrollBarButtonDown send SB_PAGEDOWN\n");
254 SendMessage(hWndParent, lphs->Direction,
255 SB_PAGEDOWN, dwOwner);
257 if (lphs->MaxPix > 0 && x > (lphs->CurPix + height) &&
258 x < (lphs->CurPix + (height << 1))) {
259 lphs->ThumbActive = TRUE;
260 dprintf_scroll(stddeb,"THUMB DOWN !\n");
263 if (lphs->ButtonDown != 0) {
264 UpdateWindow(lphs->hWndOwner);
265 if (!lphs->TimerPending && nBar == SB_CTL) {
266 lphs->TimerPending = TRUE;
267 SetTimer(lphs->hWndOwner, 1, 500, NULL);
273 void ScrollBarButtonUp(HWND hWnd, int nBar, int x, int y)
275 LPHEADSCROLL lphs;
276 RECT rect;
277 HDC hDC;
278 dprintf_scroll(stddeb,"ScrollBarButtonUp // x=%d y=%d\n", x, y);
279 lphs = GetScrollObjectStruct(hWnd, nBar);
280 if(lphs->ThumbActive)
282 HWND hWndOwner,hWndParent;
283 if (nBar == SB_CTL) {
284 hWndParent = GetParent(hWnd);
285 hWndOwner = lphs->hWndOwner;
287 else {
288 hWndParent = hWnd;
289 hWndOwner = 0;
293 SendMessage(hWndParent, lphs->Direction,
294 SB_THUMBPOSITION, MAKELONG(lphs->ThumbVal, hWndOwner));
295 lphs->ThumbActive = FALSE;
298 if (lphs->ButtonDown != 0) {
299 lphs->ButtonDown = 0;
300 if (nBar == SB_CTL) {
301 GetClientRect(lphs->hWndOwner, &rect);
302 InvalidateRect(lphs->hWndOwner, &rect, TRUE);
303 UpdateWindow(lphs->hWndOwner);
305 else {
306 hDC = GetWindowDC(lphs->hWndOwner);
307 StdDrawScrollBar(lphs->hWndOwner, hDC, nBar, &lphs->rect, lphs);
308 ReleaseDC(lphs->hWndOwner, hDC);
314 void ScrollBarMouseMove(HWND hWnd, int nBar, WORD wParam, int x, int y)
316 LPHEADSCROLL lphs;
317 HWND hWndParent;
318 HWND hWndOwner;
320 if ((wParam & MK_LBUTTON) == 0) return;
321 lphs = GetScrollObjectStruct(hWnd, nBar);
322 if (lphs->ThumbActive == 0) return;
323 if (nBar == SB_CTL) {
324 hWndParent = GetParent(hWnd);
325 hWndOwner = lphs->hWndOwner;
326 dprintf_scroll(stddeb,"ScrollBarButtonMove SB_CTL // x=%d y=%d\n", x, y);
328 else {
329 hWndParent = hWnd;
330 hWndOwner = 0;
331 dprintf_scroll(stddeb,"ScrollBarButtonMove SB_?SCROLL // x=%d y=%d\n", x, y);
334 if(x<lphs->rect.left||x>lphs->rect.right||
335 y<lphs->rect.top||y>lphs->rect.bottom)
338 dprintf_scroll(stddeb,"Rejecting thumb position !\n");
339 lphs->ThumbVal=lphs->CurVal;/*revert to last set position*/
341 else
344 if (lphs->Direction == WM_VSCROLL) {
345 int butsiz = lphs->rect.right - lphs->rect.left;
346 y = y - butsiz - (butsiz >> 1);
348 else {
349 int butsiz = lphs->rect.bottom - lphs->rect.top;
350 y = x - butsiz - (butsiz >> 1);
352 if(y<0)y=0;
353 if(y>lphs->MaxPix)y=lphs->MaxPix;
354 lphs->ThumbVal = (y * (lphs->MaxVal - lphs->MinVal) /
355 lphs->MaxPix) + lphs->MinVal;
358 dprintf_scroll(stddeb,"Scroll WM_MOUSEMOVE val=%d pix=%d\n",
359 lphs->ThumbVal, y);
360 SendMessage(hWndParent, lphs->Direction,
361 SB_THUMBTRACK, MAKELONG(lphs->ThumbVal, hWndOwner));
365 LPHEADSCROLL ScrollBarGetWindowAndStorage(HWND hWnd, WND **wndPtr)
367 WND *Ptr;
368 LPHEADSCROLL lphs;
369 *(wndPtr) = Ptr = WIN_FindWndPtr(hWnd);
370 if (Ptr == 0) {
371 fprintf(stderr,"Bad Window handle on ScrollBar !\n");
372 return 0;
374 lphs = *((LPHEADSCROLL *)&Ptr->wExtra[1]);
375 return lphs;
379 LPHEADSCROLL ScrollBarGetStorageHeader(HWND hWnd)
381 WND *wndPtr;
382 LPHEADSCROLL lphs;
383 wndPtr = WIN_FindWndPtr(hWnd);
384 if (wndPtr == 0) {
385 fprintf(stderr,"Bad Window handle on ScrollBar !\n");
386 return 0;
388 lphs = *((LPHEADSCROLL *)&wndPtr->wExtra[1]);
389 return lphs;
394 void StdDrawScrollBar(HWND hWnd, HDC hDC, int nBar, LPRECT lprect, LPHEADSCROLL lphs)
396 HWND hWndParent;
397 HBRUSH hBrush;
398 HDC hMemDC;
399 HBITMAP hOldBmp;
400 BITMAP bm;
401 RECT rect;
402 UINT w, w2, h, h2;
404 if (lphs == NULL) return;
405 if (!lphs->bRedrawFlag) return;
406 dprintf_scroll(stddeb,"StdDrawScrollBar nBar=%04X !\n", nBar);
407 if (lphs->Direction == WM_VSCROLL)
408 dprintf_scroll(stddeb,"StdDrawScrollBar Vertical left=%d top=%d right=%d bottom=%d !\n",
409 lprect->left, lprect->top, lprect->right, lprect->bottom);
410 else
411 dprintf_scroll(stddeb,"StdDrawScrollBar Horizontal left=%d top=%d right=%d bottom=%d !\n",
412 lprect->left, lprect->top, lprect->right, lprect->bottom);
413 if (nBar == SB_CTL)
414 hWndParent = GetParent(hWnd);
415 else
416 hWndParent = lphs->hWndOwner;
417 hBrush = SendMessage(hWndParent, WM_CTLCOLOR, (WORD)hDC,
418 MAKELONG(hWnd, CTLCOLOR_SCROLLBAR));
419 if (hBrush == (HBRUSH)NULL) hBrush = GetStockObject(LTGRAY_BRUSH);
420 CopyRect(&lphs->rect, lprect);
421 CopyRect(&lphs->rectUp, lprect);
422 CopyRect(&lphs->rectDown, lprect);
423 CopyRect(&rect, lprect);
424 w = rect.right - rect.left;
425 h = rect.bottom - rect.top;
426 if (w == 0 || h == 0) return;
427 if (lphs->Direction == WM_VSCROLL) {
428 if (h > 3 * w)
429 lphs->MaxPix = h - 3 * w;
430 else
431 lphs->MaxPix = 0;
432 if (h > 2 * w)
433 h2 = w;
434 else
435 h2 = (h - 4) / 2;
436 lphs->rectUp.bottom = h2;
437 lphs->rectDown.top = rect.bottom - h2;
439 else {
440 if (w > 3 * h)
441 lphs->MaxPix = w - 3 * h;
442 else
443 lphs->MaxPix = 0;
444 if (w > 2 * h)
445 w2 = h;
446 else
447 w2 = (w - 4) / 2;
448 lphs->rectUp.right = w2;
449 lphs->rectDown.left = rect.right - w2;
451 if (lphs->MaxVal != lphs->MinVal)
452 lphs->CurPix = lphs->MaxPix * (lphs->CurVal - lphs->MinVal) /
453 (lphs->MaxVal - lphs->MinVal);
454 if(lphs->CurPix <0)lphs->CurPix=0;
455 if (lphs->CurPix > lphs->MaxPix) lphs->CurPix = lphs->MaxPix;
457 hMemDC = CreateCompatibleDC(hDC);
458 if (lphs->Direction == WM_VSCROLL) {
459 GetObject(hUpArrow, sizeof(BITMAP), (LPSTR)&bm);
460 if (lphs->ButtonDown == 1)
461 hOldBmp = SelectObject(hMemDC, hUpArrowD);
462 else
463 hOldBmp = SelectObject(hMemDC, hUpArrow);
464 StretchBlt(hDC, rect.left, rect.top, w, h2, hMemDC,
465 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
466 GetObject(hDnArrow, sizeof(BITMAP), (LPSTR)&bm);
467 if (lphs->ButtonDown == 2)
468 SelectObject(hMemDC, hDnArrowD);
469 else
470 SelectObject(hMemDC, hDnArrow);
471 StretchBlt(hDC, rect.left, rect.bottom - h2, w, h2, hMemDC,
472 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
473 rect.top += h2;
474 rect.bottom -= h2;
476 else {
477 GetObject(hLfArrow, sizeof(BITMAP), (LPSTR)&bm);
478 if (lphs->ButtonDown == 3)
479 hOldBmp = SelectObject(hMemDC, hLfArrowD);
480 else
481 hOldBmp = SelectObject(hMemDC, hLfArrow);
482 StretchBlt(hDC, rect.left, rect.top, w2, h, hMemDC,
483 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
484 GetObject(hRgArrow, sizeof(BITMAP), (LPSTR)&bm);
485 if (lphs->ButtonDown == 4)
486 SelectObject(hMemDC, hRgArrowD);
487 else
488 SelectObject(hMemDC, hRgArrow);
489 StretchBlt(hDC, rect.right - w2, rect.top, w2, h, hMemDC,
490 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
491 rect.left += w2;
492 rect.right -= w2;
494 SelectObject( hMemDC, hOldBmp );
495 DeleteDC(hMemDC);
496 FillRect(hDC, &rect, hBrush);
497 if (lphs->MaxPix != 0) {
498 if (lphs->Direction == WM_VSCROLL)
499 SetRect(&rect, rect.left, rect.top + lphs->CurPix,
500 rect.left + w, rect.top + lphs->CurPix + h2);
501 else
502 SetRect(&rect, rect.left + lphs->CurPix, rect.top,
503 rect.left + lphs->CurPix + w2, rect.top + h);
504 FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
505 InflateRect(&rect, -1, -1);
506 FillRect(hDC, &rect, GetStockObject(LTGRAY_BRUSH));
507 GRAPH_DrawReliefRect(hDC, &rect, 2, 0);
508 InflateRect(&rect, -3, -3);
509 GRAPH_DrawReliefRect(hDC, &rect, 1, 1);
515 int CreateScrollBarStruct(HWND hWnd)
517 int width, height;
518 WND *wndPtr;
519 LPHEADSCROLL lphs;
520 wndPtr = WIN_FindWndPtr(hWnd);
521 width = wndPtr->rectClient.right - wndPtr->rectClient.left;
522 height = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
523 if (width <= height)
524 lphs = AllocScrollBar(WS_VSCROLL, width, height);
525 else
526 lphs = AllocScrollBar(WS_HSCROLL, width, height);
527 dprintf_scroll(stddeb,"CreateScrollBarStruct %p !\n", lphs);
528 *((LPHEADSCROLL *)&wndPtr->wExtra[1]) = lphs;
529 lphs->hWndOwner = hWnd;
530 CopyRect(&lphs->rect, &wndPtr->rectClient);
531 return TRUE;
536 LPHEADSCROLL AllocScrollBar(DWORD dwStyle, int width, int height)
538 LPHEADSCROLL lphs;
539 if (hUpArrow == (HBITMAP)NULL)
540 hUpArrow = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_UPARROWI));
541 if (hDnArrow == (HBITMAP)NULL)
542 hDnArrow = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_DNARROWI));
543 if (hLfArrow == (HBITMAP)NULL)
544 hLfArrow = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_LFARROWI));
545 if (hRgArrow == (HBITMAP)NULL)
546 hRgArrow = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_RGARROWI));
547 if (hUpArrowD == (HBITMAP)NULL)
548 hUpArrowD = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_UPARROWD));
549 if (hDnArrowD == (HBITMAP)NULL)
550 hDnArrowD = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_DNARROWD));
551 if (hLfArrowD == (HBITMAP)NULL)
552 hLfArrowD = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_LFARROWD));
553 if (hRgArrowD == (HBITMAP)NULL)
554 hRgArrowD = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_RGARROWD));
555 lphs = (LPHEADSCROLL)malloc(sizeof(HEADSCROLL));
556 if (lphs == 0) {
557 fprintf(stderr,"Bad Memory Alloc on ScrollBar !\n");
558 return NULL;
560 lphs->bRedrawFlag = TRUE;
561 lphs->ThumbActive = FALSE;
562 lphs->TimerPending = FALSE;
563 lphs->ButtonDown = 0;
564 lphs->MinVal = 0;
565 lphs->MaxVal = 100;
566 lphs->CurVal = 0;
567 lphs->CurPix = 0;
568 SetRect(&lphs->rect, 0, 0, width, height);
569 if (dwStyle & WS_VSCROLL) {
570 if (height > 3 * width)
571 lphs->MaxPix = height - 3 * width;
572 else
573 lphs->MaxPix = 0;
574 lphs->Direction = WM_VSCROLL;
576 else {
577 if (width > 3 * height)
578 lphs->MaxPix = width - 3 * height;
579 else
580 lphs->MaxPix = 0;
581 lphs->Direction = WM_HSCROLL;
583 if (lphs->MaxPix < 1) lphs->MaxPix = 1;
584 return lphs;
588 void NC_CreateScrollBars(HWND hWnd)
590 RECT rect;
591 int width, height;
592 WND *wndPtr;
593 LPHEADSCROLL lphs;
594 wndPtr = WIN_FindWndPtr(hWnd);
595 GetWindowRect(hWnd, &rect);
596 width = rect.right - rect.left;
597 height = rect.bottom - rect.top;
598 if (wndPtr->dwStyle & WS_VSCROLL) {
599 if (wndPtr->dwStyle & WS_HSCROLL) height -= SYSMETRICS_CYHSCROLL;
600 lphs = AllocScrollBar(WS_VSCROLL, SYSMETRICS_CXVSCROLL, height);
601 dprintf_scroll(stddeb,"NC_CreateScrollBars Vertical %p !\n",
602 lphs);
603 lphs->rect.left = width - SYSMETRICS_CYVSCROLL;
604 lphs->rect.right = width;
605 lphs->hWndOwner = hWnd;
606 wndPtr->VScroll = lphs;
607 wndPtr->scroll_flags |= 0x0001;
608 if (wndPtr->dwStyle & WS_HSCROLL) height += SYSMETRICS_CYHSCROLL;
610 if (wndPtr->dwStyle & WS_HSCROLL) {
611 if (wndPtr->dwStyle & WS_VSCROLL) width -= SYSMETRICS_CYVSCROLL;
612 lphs = AllocScrollBar(WS_HSCROLL, width, SYSMETRICS_CYHSCROLL);
613 dprintf_scroll(stddeb,"NC_CreateScrollBars Horizontal %p !\n", lphs);
614 lphs->rect.top = height - SYSMETRICS_CYHSCROLL;
615 lphs->rect.bottom = height;
616 lphs->hWndOwner = hWnd;
617 wndPtr->HScroll = lphs;
618 wndPtr->scroll_flags |= 0x0002;
623 /*************************************************************************
624 * GetScrollObjectStruct [internal]
626 LPHEADSCROLL GetScrollObjectStruct(HWND hWnd, int nBar)
628 WND *wndPtr;
629 if (nBar != SB_CTL) {
630 wndPtr = WIN_FindWndPtr(hWnd);
631 if (nBar == SB_VERT) return (LPHEADSCROLL)wndPtr->VScroll;
632 if (nBar == SB_HORZ) return (LPHEADSCROLL)wndPtr->HScroll;
633 return NULL;
635 return ScrollBarGetStorageHeader(hWnd);
639 /*************************************************************************
640 * SetScrollPos [USER.62]
642 int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw)
644 LPHEADSCROLL lphs;
645 HDC hDC;
646 int nRet;
647 lphs = GetScrollObjectStruct(hWnd, nBar);
648 if (lphs == NULL) return 0;
649 nRet = lphs->CurVal;
650 lphs->CurVal = (short)nPos;
651 if (lphs->MaxVal != lphs->MinVal)
652 lphs->CurPix = lphs->MaxPix * (lphs->CurVal - lphs->MinVal) /
653 (lphs->MaxVal - lphs->MinVal);
654 if(lphs->CurPix <0)lphs->CurPix=0;
656 if (lphs->CurPix > lphs->MaxPix) lphs->CurPix = lphs->MaxPix;
657 dprintf_scroll(stddeb,"SetScrollPos val=%d pixval=%d pixmax%d\n",
658 (short)nPos, lphs->CurPix, lphs->MaxPix);
659 dprintf_scroll(stddeb,"SetScrollPos min=%d max=%d\n",
660 lphs->MinVal, lphs->MaxVal);
661 if ((bRedraw) && (IsWindowVisible(lphs->hWndOwner))) {
662 if (nBar == SB_CTL) {
663 InvalidateRect(lphs->hWndOwner, &lphs->rect, TRUE);
664 UpdateWindow(lphs->hWndOwner);
666 else {
667 if (lphs->rect.right != 0 && lphs->rect.bottom != 0) {
668 hDC = GetWindowDC(lphs->hWndOwner);
669 StdDrawScrollBar(lphs->hWndOwner, hDC, nBar, &lphs->rect, lphs);
670 ReleaseDC(lphs->hWndOwner, hDC);
674 return nRet;
679 /*************************************************************************
680 * GetScrollPos [USER.63]
682 int GetScrollPos(HWND hWnd, int nBar)
684 LPHEADSCROLL lphs;
685 lphs = GetScrollObjectStruct(hWnd, nBar);
686 if (lphs == NULL) return 0;
687 return lphs->CurVal;
692 /*************************************************************************
693 * SetScrollRange [USER.64]
695 void SetScrollRange(HWND hWnd, int nBar, int MinPos, int MaxPos, BOOL bRedraw)
697 LPHEADSCROLL lphs;
698 HDC hDC;
699 lphs = GetScrollObjectStruct(hWnd, nBar);
700 if (lphs == NULL) return;
702 /* should a bad range be rejected here?
704 lphs->MinVal = (short)MinPos;
705 lphs->MaxVal = (short)MaxPos;
706 if (lphs->MaxVal != lphs->MinVal)
707 lphs->CurPix = lphs->MaxPix * (lphs->CurVal - lphs->MinVal) /
708 (lphs->MaxVal - lphs->MinVal);
709 if(lphs->CurPix <0)lphs->CurPix=0;
710 if (lphs->CurPix > lphs->MaxPix) lphs->CurPix = lphs->MaxPix;
711 dprintf_scroll(stddeb,"SetScrollRange min=%d max=%d\n",
712 lphs->MinVal, lphs->MaxVal);
713 if ((bRedraw) && (IsWindowVisible(lphs->hWndOwner))) {
714 if (nBar == SB_CTL) {
715 InvalidateRect(lphs->hWndOwner, &lphs->rect, TRUE);
716 UpdateWindow(lphs->hWndOwner);
718 else {
719 if (lphs->rect.right != 0 && lphs->rect.bottom != 0) {
720 hDC = GetWindowDC(lphs->hWndOwner);
721 StdDrawScrollBar(lphs->hWndOwner, hDC, nBar, &lphs->rect, lphs);
722 ReleaseDC(lphs->hWndOwner, hDC);
730 /*************************************************************************
731 * GetScrollRange [USER.65]
733 void GetScrollRange(HWND hWnd, int nBar, LPINT lpMin, LPINT lpMax)
735 LPHEADSCROLL lphs;
736 lphs = GetScrollObjectStruct(hWnd, nBar);
737 if (lphs == NULL) return;
738 *lpMin = lphs->MinVal;
739 *lpMax = lphs->MaxVal;
744 /*************************************************************************
745 * ShowScrollBar [USER.267]
747 void ShowScrollBar(HWND hWnd, WORD wBar, BOOL bFlag)
749 WND *wndPtr;
750 dprintf_scroll(stddeb,"ShowScrollBar hWnd=%04X wBar=%d bFlag=%d\n",
751 hWnd, wBar, bFlag);
752 if (wBar == SB_CTL) {
753 if (bFlag)
754 ShowWindow(hWnd, SW_SHOW);
755 else
756 ShowWindow(hWnd, SW_HIDE);
757 return;
759 wndPtr = WIN_FindWndPtr(hWnd);
760 if ((wBar == SB_VERT) || (wBar == SB_BOTH)) {
761 if (bFlag)
762 wndPtr->scroll_flags |= 1;
763 else
764 wndPtr->scroll_flags &= ~1;
766 if ((wBar == SB_HORZ) || (wBar == SB_BOTH)) {
767 if (bFlag)
768 wndPtr->scroll_flags |= 2;
769 else
770 wndPtr->scroll_flags &= ~2;
772 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
773 SWP_NOZORDER | SWP_NOMOVE |
774 SWP_NOSIZE | SWP_FRAMECHANGED);