Don't return overflow if no class buffer was specified.
[wine/dcerpc.git] / dlls / comctl32 / pager.c
blobe60f734729c31d2afa9aadaa60a354da7e15a8ec
1 /*
2 * Pager control
4 * Copyright 1998, 1999 Eric Kohl
6 * NOTES
7 * Tested primarily with the controlspy Pager application.
8 * Susan Farley (susan@codeweavers.com)
10 * TODO:
11 * Implement repetitive button press.
12 * Adjust arrow size relative to size of button.
13 * Allow border size changes.
14 * Implement drag and drop style.
17 #include <string.h>
18 #include "winbase.h"
19 #include "commctrl.h"
20 #include "debugtools.h"
22 DEFAULT_DEBUG_CHANNEL(pager);
24 typedef struct
26 HWND hwndChild; /* handle of the contained wnd */
27 BOOL bNoResize; /* set when created with CCS_NORESIZE */
28 COLORREF clrBk; /* background color */
29 INT nBorder; /* border size for the control */
30 INT nButtonSize;/* size of the pager btns */
31 INT nPos; /* scroll position */
32 INT nWidth; /* from child wnd's response to PGN_CALCSIZE */
33 INT nHeight; /* from child wnd's response to PGN_CALCSIZE */
34 BOOL bForward; /* forward WM_MOUSEMOVE msgs to the contained wnd */
35 INT TLbtnState; /* state of top or left btn */
36 INT BRbtnState; /* state of bottom or right btn */
37 INT direction; /* direction of the scroll, (e.g. PGF_SCROLLUP) */
38 } PAGER_INFO;
40 #define PAGER_GetInfoPtr(hwnd) ((PAGER_INFO *)GetWindowLongA(hwnd, 0))
41 #define PAGER_IsHorizontal(hwnd) ((GetWindowLongA (hwnd, GWL_STYLE) & PGS_HORZ))
43 #define MIN_ARROW_WIDTH 8
44 #define MIN_ARROW_HEIGHT 5
46 #define TIMERID1 1
47 #define TIMERID2 2
48 #define INITIAL_DELAY 500
49 #define REPEAT_DELAY 50
51 /* the horizontal arrows are:
53 * 01234 01234
54 * 1 * *
55 * 2 ** **
56 * 3*** ***
57 * 4*** ***
58 * 5 ** **
59 * 6 * *
60 * 7
63 static void
64 PAGER_DrawHorzArrow (HDC hdc, RECT r, INT colorRef, BOOL left)
66 INT x, y, w, h;
67 HPEN hOldPen;
69 w = r.right - r.left + 1;
70 h = r.bottom - r.top + 1;
71 if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
72 return; /* refuse to draw partial arrow */
74 hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
75 if (left)
77 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 3;
78 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
79 MoveToEx (hdc, x, y, NULL);
80 LineTo (hdc, x--, y+5); y++;
81 MoveToEx (hdc, x, y, NULL);
82 LineTo (hdc, x--, y+3); y++;
83 MoveToEx (hdc, x, y, NULL);
84 LineTo (hdc, x, y+1);
86 else
88 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
89 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
90 MoveToEx (hdc, x, y, NULL);
91 LineTo (hdc, x++, y+5); y++;
92 MoveToEx (hdc, x, y, NULL);
93 LineTo (hdc, x++, y+3); y++;
94 MoveToEx (hdc, x, y, NULL);
95 LineTo (hdc, x, y+1);
98 SelectObject( hdc, hOldPen );
101 /* the vertical arrows are:
103 * 01234567 01234567
104 * 1****** **
105 * 2 **** ****
106 * 3 ** ******
110 static void
111 PAGER_DrawVertArrow (HDC hdc, RECT r, INT colorRef, BOOL up)
113 INT x, y, w, h;
114 HPEN hOldPen;
116 w = r.right - r.left + 1;
117 h = r.bottom - r.top + 1;
118 if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
119 return; /* refuse to draw partial arrow */
121 hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
122 if (up)
124 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
125 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 3;
126 MoveToEx (hdc, x, y, NULL);
127 LineTo (hdc, x+5, y--); x++;
128 MoveToEx (hdc, x, y, NULL);
129 LineTo (hdc, x+3, y--); x++;
130 MoveToEx (hdc, x, y, NULL);
131 LineTo (hdc, x+1, y);
133 else
135 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
136 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
137 MoveToEx (hdc, x, y, NULL);
138 LineTo (hdc, x+5, y++); x++;
139 MoveToEx (hdc, x, y, NULL);
140 LineTo (hdc, x+3, y++); x++;
141 MoveToEx (hdc, x, y, NULL);
142 LineTo (hdc, x+1, y);
145 SelectObject( hdc, hOldPen );
148 static void
149 PAGER_DrawButton(HDC hdc, COLORREF clrBk, RECT arrowRect,
150 BOOL horz, BOOL topLeft, INT btnState)
152 HBRUSH hBrush, hOldBrush;
153 RECT rc = arrowRect;
155 if (!btnState) /* PGF_INVISIBLE */
156 return;
158 if ((rc.right - rc.left <= 0) || (rc.bottom - rc.top <= 0))
159 return;
161 hBrush = CreateSolidBrush(clrBk);
162 hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
164 FillRect(hdc, &rc, hBrush);
166 if (btnState == PGF_HOT)
168 DrawEdge( hdc, &rc, BDR_RAISEDINNER, BF_RECT);
169 if (horz)
170 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
171 else
172 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
174 else if (btnState == PGF_NORMAL)
176 DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
177 if (horz)
178 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
179 else
180 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
182 else if (btnState == PGF_DEPRESSED)
184 DrawEdge( hdc, &rc, BDR_SUNKENOUTER, BF_RECT);
185 if (horz)
186 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
187 else
188 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
190 else if (btnState == PGF_GRAYED)
192 DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
193 if (horz)
195 PAGER_DrawHorzArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
196 rc.left++, rc.top++; rc.right++, rc.bottom++;
197 PAGER_DrawHorzArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
199 else
201 PAGER_DrawVertArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
202 rc.left++, rc.top++; rc.right++, rc.bottom++;
203 PAGER_DrawVertArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
207 SelectObject( hdc, hOldBrush );
208 DeleteObject(hBrush);
211 /* << PAGER_GetDropTarget >> */
213 static inline LRESULT
214 PAGER_ForwardMouse (HWND hwnd, WPARAM wParam)
216 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
217 TRACE("[%04x]\n", hwnd);
219 infoPtr->bForward = (BOOL)wParam;
221 return 0;
224 static inline LRESULT
225 PAGER_GetButtonState (HWND hwnd, WPARAM wParam, LPARAM lParam)
227 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
228 LRESULT btnState = PGF_INVISIBLE;
229 INT btn = (INT)lParam;
230 TRACE("[%04x]\n", hwnd);
232 if (btn == PGB_TOPORLEFT)
233 btnState = infoPtr->TLbtnState;
234 else if (btn == PGB_BOTTOMORRIGHT)
235 btnState = infoPtr->BRbtnState;
237 return btnState;
241 static inline LRESULT
242 PAGER_GetPos(HWND hwnd)
244 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
245 TRACE("[%04x] returns %d\n", hwnd, infoPtr->nPos);
246 return (LRESULT)infoPtr->nPos;
249 static inline LRESULT
250 PAGER_GetButtonSize(HWND hwnd)
252 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
253 TRACE("[%04x] returns %d\n", hwnd, infoPtr->nButtonSize);
254 return (LRESULT)infoPtr->nButtonSize;
257 static inline LRESULT
258 PAGER_GetBorder(HWND hwnd)
260 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
261 TRACE("[%04x] returns %d\n", hwnd, infoPtr->nBorder);
262 return (LRESULT)infoPtr->nBorder;
265 static inline LRESULT
266 PAGER_GetBkColor(HWND hwnd)
268 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
269 TRACE("[%04x] returns %06lx\n", hwnd, infoPtr->clrBk);
270 return (LRESULT)infoPtr->clrBk;
273 static void
274 PAGER_CalcSize (HWND hwnd, INT* size, BOOL getWidth)
276 NMPGCALCSIZE nmpgcs;
277 ZeroMemory (&nmpgcs, sizeof (NMPGCALCSIZE));
278 nmpgcs.hdr.hwndFrom = hwnd;
279 nmpgcs.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
280 nmpgcs.hdr.code = PGN_CALCSIZE;
281 nmpgcs.dwFlag = getWidth ? PGF_CALCWIDTH : PGF_CALCHEIGHT;
282 nmpgcs.iWidth = getWidth ? *size : 0;
283 nmpgcs.iHeight = getWidth ? 0 : *size;
284 SendMessageA (GetParent (hwnd), WM_NOTIFY,
285 (WPARAM)nmpgcs.hdr.idFrom, (LPARAM)&nmpgcs);
287 *size = getWidth ? nmpgcs.iWidth : nmpgcs.iHeight;
289 TRACE("[%04x] PGN_CALCSIZE returns %s=%d\n", hwnd,
290 getWidth ? "width" : "height", *size);
293 static void
294 PAGER_PositionChildWnd(HWND hwnd, PAGER_INFO* infoPtr)
296 if (infoPtr->hwndChild)
298 RECT rcClient;
299 int nPos = infoPtr->nPos;
301 /* compensate for a grayed btn, which will soon become invisible */
302 if (infoPtr->TLbtnState == PGF_GRAYED)
303 nPos += infoPtr->nButtonSize;
305 GetClientRect(hwnd, &rcClient);
307 if (PAGER_IsHorizontal(hwnd))
309 int wndSize = max(0, rcClient.right - rcClient.left);
310 if (infoPtr->nWidth < wndSize)
311 infoPtr->nWidth = wndSize;
313 TRACE("[%04x] SWP %dx%d at (%d,%d)\n", hwnd,
314 infoPtr->nWidth, infoPtr->nHeight,
315 -nPos, 0);
316 SetWindowPos(infoPtr->hwndChild, 0,
317 -nPos, 0,
318 infoPtr->nWidth, infoPtr->nHeight,
319 SWP_NOZORDER);
321 else
323 int wndSize = max(0, rcClient.bottom - rcClient.top);
324 if (infoPtr->nHeight < wndSize)
325 infoPtr->nHeight = wndSize;
327 TRACE("[%04x] SWP %dx%d at (%d,%d)\n", hwnd,
328 infoPtr->nWidth, infoPtr->nHeight,
329 0, -nPos);
330 SetWindowPos(infoPtr->hwndChild, 0,
331 0, -nPos,
332 infoPtr->nWidth, infoPtr->nHeight,
333 SWP_NOZORDER);
336 InvalidateRect(infoPtr->hwndChild, NULL, TRUE);
340 static INT
341 PAGER_GetScrollRange(HWND hwnd, PAGER_INFO* infoPtr)
343 INT scrollRange = 0;
345 if (infoPtr->hwndChild)
347 INT wndSize, childSize;
348 RECT wndRect;
349 GetWindowRect(hwnd, &wndRect);
351 if (PAGER_IsHorizontal(hwnd))
353 wndSize = wndRect.right - wndRect.left;
354 PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
355 childSize = infoPtr->nWidth;
357 else
359 wndSize = wndRect.bottom - wndRect.top;
360 PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
361 childSize = infoPtr->nHeight;
364 TRACE("childSize = %d, wndSize = %d\n", childSize, wndSize);
365 if (childSize > wndSize)
366 scrollRange = childSize - wndSize + infoPtr->nButtonSize;
369 TRACE("[%04x] returns %d\n", hwnd, scrollRange);
370 return scrollRange;
373 static void
374 PAGER_GrayAndRestoreBtns(PAGER_INFO* infoPtr, INT scrollRange,
375 BOOL* needsResize, BOOL* needsRepaint)
377 if (infoPtr->nPos > 0)
379 *needsResize |= !infoPtr->TLbtnState; /* PGF_INVISIBLE */
380 if (infoPtr->TLbtnState != PGF_DEPRESSED)
381 infoPtr->TLbtnState = PGF_NORMAL;
383 else
385 *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
386 infoPtr->TLbtnState = PGF_GRAYED;
389 if (scrollRange <= 0)
391 *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
392 infoPtr->TLbtnState = PGF_GRAYED;
393 *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
394 infoPtr->BRbtnState = PGF_GRAYED;
396 else if (infoPtr->nPos < scrollRange)
398 *needsResize |= !infoPtr->BRbtnState; /* PGF_INVISIBLE */
399 if (infoPtr->BRbtnState != PGF_DEPRESSED)
400 infoPtr->BRbtnState = PGF_NORMAL;
402 else
404 *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
405 infoPtr->BRbtnState = PGF_GRAYED;
410 static void
411 PAGER_NormalizeBtns(PAGER_INFO* infoPtr, BOOL* needsRepaint)
413 if (infoPtr->TLbtnState & (PGF_HOT | PGF_DEPRESSED))
415 infoPtr->TLbtnState = PGF_NORMAL;
416 *needsRepaint = TRUE;
419 if (infoPtr->BRbtnState & (PGF_HOT | PGF_DEPRESSED))
421 infoPtr->BRbtnState = PGF_NORMAL;
422 *needsRepaint = TRUE;
426 static void
427 PAGER_HideGrayBtns(PAGER_INFO* infoPtr, BOOL* needsResize)
429 if (infoPtr->TLbtnState == PGF_GRAYED)
431 infoPtr->TLbtnState = PGF_INVISIBLE;
432 *needsResize = TRUE;
435 if (infoPtr->BRbtnState == PGF_GRAYED)
437 infoPtr->BRbtnState = PGF_INVISIBLE;
438 *needsResize = TRUE;
442 static void
443 PAGER_UpdateBtns(HWND hwnd, PAGER_INFO *infoPtr,
444 INT scrollRange, BOOL hideGrayBtns)
446 BOOL resizeClient = FALSE;
447 BOOL repaintBtns = FALSE;
449 if (scrollRange < 0)
450 PAGER_NormalizeBtns(infoPtr, &repaintBtns);
451 else
452 PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
454 if (hideGrayBtns)
455 PAGER_HideGrayBtns(infoPtr, &resizeClient);
457 if (resizeClient) /* initiate NCCalcSize to resize client wnd */ {
458 SetWindowPos(hwnd, 0,0,0,0,0,
459 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
460 SWP_NOZORDER | SWP_NOACTIVATE);
463 if (repaintBtns)
464 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
467 static LRESULT
468 PAGER_SetPos(HWND hwnd, INT newPos, BOOL fromBtnPress)
470 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
471 INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
472 INT oldPos = infoPtr->nPos;
474 if ((scrollRange <= 0) || (newPos < 0))
475 infoPtr->nPos = 0;
476 else if (newPos > scrollRange)
477 infoPtr->nPos = scrollRange;
478 else
479 infoPtr->nPos = newPos;
481 TRACE("[%04x] pos=%d\n", hwnd, infoPtr->nPos);
483 if (infoPtr->nPos != oldPos)
485 /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
486 PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, !fromBtnPress);
487 PAGER_PositionChildWnd(hwnd, infoPtr);
490 return 0;
493 static LRESULT
494 PAGER_HandleWindowPosChanging(HWND hwnd, WPARAM wParam, WINDOWPOS *winpos)
496 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
498 if (infoPtr->bNoResize && !(winpos->flags & SWP_NOSIZE))
500 /* don't let the app resize the nonscrollable dimension of a control
501 * that was created with CCS_NORESIZE style
502 * (i.e. height for a horizontal pager, or width for a vertical one) */
504 /* except if the current dimension is 0 and app is setting for
505 * first time, then save amount as dimension. - GA 8/01 */
507 if (PAGER_IsHorizontal(hwnd))
508 if (!infoPtr->nHeight && winpos->cy)
509 infoPtr->nHeight = winpos->cy;
510 else
511 winpos->cy = infoPtr->nHeight;
512 else
513 if (!infoPtr->nWidth && winpos->cx)
514 infoPtr->nWidth = winpos->cx;
515 else
516 winpos->cx = infoPtr->nWidth;
517 return 0;
520 DefWindowProcA (hwnd, WM_WINDOWPOSCHANGING, wParam, (LPARAM)winpos);
522 return 1;
525 static INT
526 PAGER_SetFixedWidth(HWND hwnd, PAGER_INFO* infoPtr)
528 /* Must set the non-scrollable dimension to be less than the full height/width
529 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
530 * size, and experimentation shows that affect is almost right. */
532 RECT wndRect;
533 INT delta, h;
534 GetWindowRect(hwnd, &wndRect);
536 /* see what the app says for btn width */
537 PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
539 if (infoPtr->bNoResize)
541 delta = wndRect.right - wndRect.left - infoPtr->nWidth;
542 if (delta > infoPtr->nButtonSize)
543 infoPtr->nWidth += 4 * infoPtr->nButtonSize / 3;
544 else if (delta > 0)
545 infoPtr->nWidth += infoPtr->nButtonSize / 3;
548 h = wndRect.bottom - wndRect.top + infoPtr->nButtonSize;
550 TRACE("[%04x] infoPtr->nWidth set to %d\n",
551 hwnd, infoPtr->nWidth);
553 return h;
556 static INT
557 PAGER_SetFixedHeight(HWND hwnd, PAGER_INFO* infoPtr)
559 /* Must set the non-scrollable dimension to be less than the full height/width
560 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
561 * size, and experimentation shows that affect is almost right. */
563 RECT wndRect;
564 INT delta, w;
565 GetWindowRect(hwnd, &wndRect);
567 /* see what the app says for btn height */
568 PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
570 if (infoPtr->bNoResize)
572 delta = wndRect.bottom - wndRect.top - infoPtr->nHeight;
573 if (delta > infoPtr->nButtonSize)
574 infoPtr->nHeight += infoPtr->nButtonSize;
575 else if (delta > 0)
576 infoPtr->nHeight += infoPtr->nButtonSize / 3;
579 w = wndRect.right - wndRect.left + infoPtr->nButtonSize;
581 TRACE("[%04x] infoPtr->nHeight set to %d\n",
582 hwnd, infoPtr->nHeight);
584 return w;
587 static LRESULT
588 PAGER_RecalcSize(HWND hwnd)
590 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
592 TRACE("[%04x]\n", hwnd);
594 if (infoPtr->hwndChild)
596 INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
598 if (scrollRange <= 0)
600 infoPtr->nPos = -1;
601 PAGER_SetPos(hwnd, 0, FALSE);
603 else
605 PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, TRUE);
606 PAGER_PositionChildWnd(hwnd, infoPtr);
610 return 1;
614 static LRESULT
615 PAGER_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
617 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
618 COLORREF clrTemp = infoPtr->clrBk;
620 infoPtr->clrBk = (COLORREF)lParam;
621 TRACE("[%04x] %06lx\n", hwnd, infoPtr->clrBk);
623 PAGER_RecalcSize(hwnd);
624 SendMessageA(hwnd, WM_NCPAINT, (WPARAM)0, (LPARAM)0);
626 return (LRESULT)clrTemp;
630 static LRESULT
631 PAGER_SetBorder (HWND hwnd, WPARAM wParam, LPARAM lParam)
633 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
634 INT nTemp = infoPtr->nBorder;
636 infoPtr->nBorder = (INT)lParam;
637 TRACE("[%04x] %d\n", hwnd, infoPtr->nBorder);
639 PAGER_RecalcSize(hwnd);
641 return (LRESULT)nTemp;
645 static LRESULT
646 PAGER_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
648 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
649 INT nTemp = infoPtr->nButtonSize;
651 infoPtr->nButtonSize = (INT)lParam;
652 TRACE("[%04x] %d\n", hwnd, infoPtr->nButtonSize);
654 PAGER_RecalcSize(hwnd);
656 return (LRESULT)nTemp;
660 static LRESULT
661 PAGER_SetChild (HWND hwnd, WPARAM wParam, LPARAM lParam)
663 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
664 INT hw;
666 infoPtr->hwndChild = IsWindow ((HWND)lParam) ? (HWND)lParam : 0;
668 if (infoPtr->hwndChild)
670 TRACE("[%04x] hwndChild=%04x\n", hwnd, infoPtr->hwndChild);
672 if (PAGER_IsHorizontal(hwnd)) {
673 hw = PAGER_SetFixedHeight(hwnd, infoPtr);
674 /* adjust non-scrollable dimension to fit the child */
675 SetWindowPos(hwnd, 0, 0,0, hw, infoPtr->nHeight,
676 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER |
677 SWP_NOSIZE | SWP_NOACTIVATE);
679 else {
680 hw = PAGER_SetFixedWidth(hwnd, infoPtr);
681 /* adjust non-scrollable dimension to fit the child */
682 SetWindowPos(hwnd, 0, 0,0, infoPtr->nWidth, hw,
683 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER |
684 SWP_NOSIZE | SWP_NOACTIVATE);
687 /* position child within the page scroller */
688 SetWindowPos(infoPtr->hwndChild, HWND_TOP,
689 0,0,0,0,
690 SWP_SHOWWINDOW | SWP_NOSIZE); /* native is 0 */
692 infoPtr->nPos = -1;
693 PAGER_SetPos(hwnd, 0, FALSE);
696 return 0;
699 static void
700 PAGER_Scroll(HWND hwnd, INT dir)
702 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
703 NMPGSCROLL nmpgScroll;
704 RECT rcWnd;
706 if (infoPtr->hwndChild)
708 ZeroMemory (&nmpgScroll, sizeof (NMPGSCROLL));
709 nmpgScroll.hdr.hwndFrom = hwnd;
710 nmpgScroll.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
711 nmpgScroll.hdr.code = PGN_SCROLL;
713 GetWindowRect(hwnd, &rcWnd);
714 GetClientRect(hwnd, &nmpgScroll.rcParent);
715 nmpgScroll.iXpos = nmpgScroll.iYpos = 0;
716 nmpgScroll.iDir = dir;
718 if (PAGER_IsHorizontal(hwnd))
720 nmpgScroll.iScroll = rcWnd.right - rcWnd.left;
721 nmpgScroll.iXpos = infoPtr->nPos;
723 else
725 nmpgScroll.iScroll = rcWnd.bottom - rcWnd.top;
726 nmpgScroll.iYpos = infoPtr->nPos;
728 nmpgScroll.iScroll -= 2*infoPtr->nButtonSize;
730 SendMessageA (hwnd, WM_NOTIFY,
731 (WPARAM)nmpgScroll.hdr.idFrom, (LPARAM)&nmpgScroll);
733 TRACE("[%04x] PGN_SCROLL returns iScroll=%d\n", hwnd, nmpgScroll.iScroll);
735 if (nmpgScroll.iScroll > 0)
737 infoPtr->direction = dir;
739 if (dir == PGF_SCROLLLEFT || dir == PGF_SCROLLUP)
740 PAGER_SetPos(hwnd, infoPtr->nPos - nmpgScroll.iScroll, TRUE);
741 else
742 PAGER_SetPos(hwnd, infoPtr->nPos + nmpgScroll.iScroll, TRUE);
744 else
745 infoPtr->direction = -1;
749 static LRESULT
750 PAGER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
752 PAGER_INFO *infoPtr;
753 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
755 /* allocate memory for info structure */
756 infoPtr = (PAGER_INFO *)COMCTL32_Alloc (sizeof(PAGER_INFO));
757 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
759 /* set default settings */
760 infoPtr->hwndChild = (HWND)NULL;
761 infoPtr->bNoResize = dwStyle & CCS_NORESIZE;
762 infoPtr->clrBk = GetSysColor(COLOR_BTNFACE);
763 infoPtr->nBorder = 0;
764 infoPtr->nButtonSize = 12;
765 infoPtr->nPos = 0;
766 infoPtr->nWidth = 0;
767 infoPtr->nHeight = 0;
768 infoPtr->bForward = FALSE;
769 infoPtr->TLbtnState = PGF_INVISIBLE;
770 infoPtr->BRbtnState = PGF_INVISIBLE;
771 infoPtr->direction = -1;
773 if (dwStyle & PGS_AUTOSCROLL)
774 FIXME("[%04x] Autoscroll style is not implemented yet.\n", hwnd);
775 if (dwStyle & PGS_DRAGNDROP)
776 FIXME("[%04x] Drag and Drop style is not implemented yet.\n", hwnd);
778 * If neither horizontal nor vertical style specified, default to vertical.
779 * This is probably not necessary, since the style may be set later on as
780 * the control is initialized, but just in case it isn't, set it here.
782 if (!(dwStyle & PGS_HORZ) && !(dwStyle & PGS_VERT))
784 dwStyle |= PGS_VERT;
785 SetWindowLongA(hwnd, GWL_STYLE, dwStyle);
788 return 0;
792 static LRESULT
793 PAGER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
795 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
796 /* free pager info data */
797 COMCTL32_Free (infoPtr);
798 SetWindowLongA (hwnd, 0, 0);
799 return 0;
802 static LRESULT
803 PAGER_NCCalcSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
805 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
806 LPRECT lpRect = (LPRECT)lParam;
807 RECT rcChildw, rcmyw, wnrc, lbrc, rbrc;
808 POINT cursor;
811 * lParam points to a RECT struct. On entry, the struct
812 * contains the proposed wnd rectangle for the window.
813 * On exit, the struct should contain the screen
814 * coordinates of the corresponding window's client area.
817 DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
819 if (PAGER_IsHorizontal(hwnd))
821 infoPtr->nWidth = lpRect->right - lpRect->left;
822 PAGER_CalcSize (hwnd, &infoPtr->nWidth, TRUE);
823 GetWindowRect (infoPtr->hwndChild, &rcChildw);
824 MapWindowPoints (0, hwnd, (LPPOINT)&rcChildw, 2);
825 GetCursorPos (&cursor);
826 GetWindowRect (hwnd, &rcmyw);
827 if (PtInRect (&rcmyw, cursor)) {
828 GetWindowRect (hwnd, &wnrc);
829 lbrc = wnrc;
830 lbrc.right = lbrc.left + infoPtr->nButtonSize;
831 rbrc = wnrc;
832 rbrc.left = rbrc.right - infoPtr->nButtonSize;
833 TRACE("horz lb rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
834 lbrc.left, lbrc.top, lbrc.right, lbrc.bottom,
835 rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
836 if (PtInRect (&lbrc, cursor) && infoPtr->TLbtnState)
837 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
838 if (PtInRect (&rbrc, cursor) && infoPtr->BRbtnState)
839 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
841 if (infoPtr->TLbtnState) /* != PGF_INVISIBLE */
842 lpRect->left += infoPtr->nButtonSize;
843 if (infoPtr->BRbtnState)
844 lpRect->right -= infoPtr->nButtonSize;
846 else
848 /* native does: (from trace of IE4 opening "Favorites" frame)
849 * DefWindowProc
850 * WM_NOITFY PGN_CALCSIZE w/ dwFlag=2
851 * GetWindowRect (child, &rc)
852 * MapWindowPoints (0, syspager, &rc, 2)
853 * GetCursorPos( &cur )
854 * GetWindowRect (syspager, &rc2)
855 * PtInRect (&rc2, cur.x, cur.y) rtns 0
856 * returns with rect empty
858 infoPtr->nHeight = lpRect->bottom - lpRect->top;
859 PAGER_CalcSize (hwnd, &infoPtr->nHeight, FALSE);
860 GetWindowRect (infoPtr->hwndChild, &rcChildw);
861 MapWindowPoints (0, hwnd, (LPPOINT)&rcChildw, 2);
862 GetCursorPos (&cursor);
863 GetWindowRect (hwnd, &rcmyw);
864 if (PtInRect (&rcmyw, cursor)) {
866 /* native does:
867 * GetWindowRect(pager, &rc)
868 * PtInRect(btn-left????, cur.x, cur.y)
869 * if true -> ???
870 * PtInRect(btn-right????, cur.x, cur.y)
871 * if true
872 * RedrawWindow(pager, 0, 0, 5)
873 * return TRUE
876 GetWindowRect (hwnd, &wnrc);
877 lbrc = wnrc;
878 lbrc.right = lbrc.left + infoPtr->nButtonSize;
879 rbrc = wnrc;
880 rbrc.left = rbrc.right - infoPtr->nButtonSize;
881 TRACE("vert lb rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
882 lbrc.left, lbrc.top, lbrc.right, lbrc.bottom,
883 rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
884 if (PtInRect (&lbrc, cursor) && infoPtr->TLbtnState)
885 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
886 if (PtInRect (&rbrc, cursor) && infoPtr->BRbtnState)
887 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
889 if (infoPtr->TLbtnState)
890 lpRect->top += infoPtr->nButtonSize;
891 if (infoPtr->BRbtnState)
892 lpRect->bottom -= infoPtr->nButtonSize;
893 /* ???? */
894 if ((lpRect->bottom < 0) || (lpRect->bottom > infoPtr->nHeight))
895 lpRect->bottom = infoPtr->nHeight;
898 TRACE("[%04x] client rect set to %dx%d at (%d,%d)\n", hwnd,
899 lpRect->right-lpRect->left,
900 lpRect->bottom-lpRect->top,
901 lpRect->left, lpRect->top);
903 return 0;
906 static LRESULT
907 PAGER_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
909 PAGER_INFO* infoPtr = PAGER_GetInfoPtr(hwnd);
910 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
911 RECT rcWindow, rcBottomRight, rcTopLeft;
912 HDC hdc;
913 BOOL bHorizontal = PAGER_IsHorizontal(hwnd);
915 if (dwStyle & WS_MINIMIZE)
916 return 0;
918 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
920 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
921 return 0;
923 GetWindowRect (hwnd, &rcWindow);
924 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
926 rcTopLeft = rcBottomRight = rcWindow;
927 if (bHorizontal)
929 rcTopLeft.right = rcTopLeft.left + infoPtr->nButtonSize;
930 rcBottomRight.left = rcBottomRight.right - infoPtr->nButtonSize;
932 else
934 rcTopLeft.bottom = rcTopLeft.top + infoPtr->nButtonSize;
935 rcBottomRight.top = rcBottomRight.bottom - infoPtr->nButtonSize;
938 PAGER_DrawButton(hdc, infoPtr->clrBk, rcTopLeft,
939 bHorizontal, TRUE, infoPtr->TLbtnState);
940 PAGER_DrawButton(hdc, infoPtr->clrBk, rcBottomRight,
941 bHorizontal, FALSE, infoPtr->BRbtnState);
943 ReleaseDC( hwnd, hdc );
944 return 0;
947 static INT
948 PAGER_HitTest (HWND hwnd, LPPOINT pt)
950 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
951 RECT clientRect;
952 BOOL bHorizontal = PAGER_IsHorizontal(hwnd);
954 GetClientRect (hwnd, &clientRect);
956 if (PtInRect(&clientRect, *pt))
958 /* TRACE("HTCLIENT\n"); */
959 return HTCLIENT;
962 if (infoPtr->TLbtnState && infoPtr->TLbtnState != PGF_GRAYED)
964 if (bHorizontal)
966 if (pt->x < clientRect.left)
968 /* TRACE("HTLEFT\n"); */
969 return HTLEFT;
972 else
974 if (pt->y < clientRect.top)
976 /* TRACE("HTTOP\n"); */
977 return HTTOP;
982 if (infoPtr->BRbtnState && infoPtr->BRbtnState != PGF_GRAYED)
984 if (bHorizontal)
986 if (pt->x > clientRect.right)
988 /* TRACE("HTRIGHT\n"); */
989 return HTRIGHT;
992 else
994 if (pt->y > clientRect.bottom)
996 /* TRACE("HTBOTTOM\n"); */
997 return HTBOTTOM;
1002 /* TRACE("HTNOWHERE\n"); */
1003 return HTNOWHERE;
1006 static LRESULT
1007 PAGER_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1009 POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
1010 ScreenToClient (hwnd, &pt);
1011 return PAGER_HitTest(hwnd, &pt);
1014 static LRESULT
1015 PAGER_SetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1017 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1018 BOOL notCaptured = FALSE;
1020 switch(LOWORD(lParam))
1022 case HTLEFT:
1023 case HTTOP:
1024 if ((notCaptured = infoPtr->TLbtnState != PGF_HOT))
1025 infoPtr->TLbtnState = PGF_HOT;
1026 break;
1027 case HTRIGHT:
1028 case HTBOTTOM:
1029 if ((notCaptured = infoPtr->BRbtnState != PGF_HOT))
1030 infoPtr->BRbtnState = PGF_HOT;
1031 break;
1032 default:
1033 return FALSE;
1036 if (notCaptured)
1038 TRACKMOUSEEVENT trackinfo;
1040 TRACE("[%04x] SetCapture\n", hwnd);
1041 SetCapture(hwnd);
1043 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
1044 trackinfo.dwFlags = TME_QUERY;
1045 trackinfo.hwndTrack = hwnd;
1046 trackinfo.dwHoverTime = HOVER_DEFAULT;
1048 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
1049 _TrackMouseEvent(&trackinfo);
1051 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
1052 if(!(trackinfo.dwFlags & TME_LEAVE)) {
1053 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
1055 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
1056 /* and can properly deactivate the hot button */
1057 _TrackMouseEvent(&trackinfo);
1060 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
1063 return TRUE;
1066 static LRESULT
1067 PAGER_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
1069 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1071 KillTimer (hwnd, TIMERID1);
1072 KillTimer (hwnd, TIMERID2);
1074 TRACE("[%04x] ReleaseCapture\n", hwnd);
1075 ReleaseCapture();
1077 /* Notify parent of released mouse capture */
1079 NMHDR nmhdr;
1080 ZeroMemory (&nmhdr, sizeof (NMHDR));
1081 nmhdr.hwndFrom = hwnd;
1082 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1083 nmhdr.code = NM_RELEASEDCAPTURE;
1084 SendMessageA (GetParent(hwnd), WM_NOTIFY,
1085 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1088 /* make HOT btns NORMAL and hide gray btns */
1089 PAGER_UpdateBtns(hwnd, infoPtr, -1, TRUE);
1091 return TRUE;
1094 static LRESULT
1095 PAGER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1097 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1098 BOOL repaintBtns = FALSE;
1099 POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
1100 INT hit;
1102 TRACE("[%04x]\n", hwnd);
1104 hit = PAGER_HitTest(hwnd, &pt);
1106 /* put btn in DEPRESSED state */
1107 if (hit == HTLEFT || hit == HTTOP)
1109 repaintBtns = infoPtr->TLbtnState != PGF_DEPRESSED;
1110 infoPtr->TLbtnState = PGF_DEPRESSED;
1111 SetTimer(hwnd, TIMERID1, INITIAL_DELAY, 0);
1113 else if (hit == HTRIGHT || hit == HTBOTTOM)
1115 repaintBtns = infoPtr->BRbtnState != PGF_DEPRESSED;
1116 infoPtr->BRbtnState = PGF_DEPRESSED;
1117 SetTimer(hwnd, TIMERID1, INITIAL_DELAY, 0);
1120 if (repaintBtns)
1121 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
1123 switch(hit)
1125 case HTLEFT:
1126 TRACE("[%04x] PGF_SCROLLLEFT\n", hwnd);
1127 PAGER_Scroll(hwnd, PGF_SCROLLLEFT);
1128 break;
1129 case HTTOP:
1130 TRACE("[%04x] PGF_SCROLLUP\n", hwnd);
1131 PAGER_Scroll(hwnd, PGF_SCROLLUP);
1132 break;
1133 case HTRIGHT:
1134 TRACE("[%04x] PGF_SCROLLRIGHT\n", hwnd);
1135 PAGER_Scroll(hwnd, PGF_SCROLLRIGHT);
1136 break;
1137 case HTBOTTOM:
1138 TRACE("[%04x] PGF_SCROLLDOWN\n", hwnd);
1139 PAGER_Scroll(hwnd, PGF_SCROLLDOWN);
1140 break;
1141 default:
1142 break;
1145 return TRUE;
1148 static LRESULT
1149 PAGER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1151 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1152 TRACE("[%04x]\n", hwnd);
1154 KillTimer (hwnd, TIMERID1);
1155 KillTimer (hwnd, TIMERID2);
1157 /* make PRESSED btns NORMAL but don't hide gray btns */
1158 PAGER_UpdateBtns(hwnd, infoPtr, -1, FALSE);
1160 return 0;
1163 static LRESULT
1164 PAGER_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
1166 POINT pt, ptorig;
1167 HDC hdc = (HDC)wParam;
1168 HWND parent;
1170 /* native does:
1171 * parent = GetParent(pager)
1172 * pt.x=0; pt.y=0; ?????
1173 * MapWindowPoints(pager, parent, &pt, 1)
1174 * OffsetWindowOrgEx(hdc, pt.x, pt.y, &ptorg)
1175 * SendMessageA(parent, WM_ERASEBKGND, hdc, 0)
1176 * SetWindowOrgEx(hdc, 0, 0, 0)
1179 pt.x = 0;
1180 pt.y = 0;
1181 parent = GetParent(hwnd);
1182 MapWindowPoints(hwnd, parent, &pt, 1);
1183 OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig);
1184 SendMessageA (parent, WM_ERASEBKGND, wParam, lParam);
1185 SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0);
1188 #if 0
1189 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1190 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
1191 RECT rect;
1193 GetClientRect (hwnd, &rect);
1194 FillRect ((HDC)wParam, &rect, hBrush);
1196 /* background color of the child should be the same as the pager */
1197 if (infoPtr->hwndChild)
1199 GetClientRect (infoPtr->hwndChild, &rect);
1200 FillRect ((HDC)wParam, &rect, hBrush);
1203 DeleteObject (hBrush);
1204 #endif
1206 return TRUE;
1210 static LRESULT
1211 PAGER_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
1213 /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
1215 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1216 TRACE("[%04x] %dx%d\n", hwnd, LOWORD(lParam), HIWORD(lParam));
1218 if (PAGER_IsHorizontal(hwnd))
1219 infoPtr->nHeight = HIWORD(lParam);
1220 else
1221 infoPtr->nWidth = LOWORD(lParam);
1223 return PAGER_RecalcSize(hwnd);
1227 static LRESULT WINAPI
1228 PAGER_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1230 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1232 if (!infoPtr && (uMsg != WM_CREATE))
1233 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1235 switch (uMsg)
1237 case PGM_FORWARDMOUSE:
1238 return PAGER_ForwardMouse (hwnd, wParam);
1240 case PGM_GETBKCOLOR:
1241 return PAGER_GetBkColor(hwnd);
1243 case PGM_GETBORDER:
1244 return PAGER_GetBorder(hwnd);
1246 case PGM_GETBUTTONSIZE:
1247 return PAGER_GetButtonSize(hwnd);
1249 case PGM_GETPOS:
1250 return PAGER_GetPos(hwnd);
1252 case PGM_GETBUTTONSTATE:
1253 return PAGER_GetButtonState (hwnd, wParam, lParam);
1255 /* case PGM_GETDROPTARGET: */
1257 case PGM_RECALCSIZE:
1258 return PAGER_RecalcSize(hwnd);
1260 case PGM_SETBKCOLOR:
1261 return PAGER_SetBkColor (hwnd, wParam, lParam);
1263 case PGM_SETBORDER:
1264 return PAGER_SetBorder (hwnd, wParam, lParam);
1266 case PGM_SETBUTTONSIZE:
1267 return PAGER_SetButtonSize (hwnd, wParam, lParam);
1269 case PGM_SETCHILD:
1270 return PAGER_SetChild (hwnd, wParam, lParam);
1272 case PGM_SETPOS:
1273 return PAGER_SetPos(hwnd, (INT)lParam, FALSE);
1275 case WM_CREATE:
1276 return PAGER_Create (hwnd, wParam, lParam);
1278 case WM_DESTROY:
1279 return PAGER_Destroy (hwnd, wParam, lParam);
1281 case WM_SIZE:
1282 return PAGER_Size (hwnd, wParam, lParam);
1284 case WM_NCPAINT:
1285 return PAGER_NCPaint (hwnd, wParam, lParam);
1287 case WM_WINDOWPOSCHANGING:
1288 return PAGER_HandleWindowPosChanging (hwnd, wParam, (WINDOWPOS*)lParam);
1290 case WM_NCCALCSIZE:
1291 return PAGER_NCCalcSize (hwnd, wParam, lParam);
1293 case WM_NCHITTEST:
1294 return PAGER_NCHitTest (hwnd, wParam, lParam);
1296 case WM_SETCURSOR:
1298 if (hwnd == (HWND)wParam)
1299 return PAGER_SetCursor(hwnd, wParam, lParam);
1300 else /* its for the child */
1301 return 0;
1304 case WM_MOUSEMOVE:
1305 if (infoPtr->bForward && infoPtr->hwndChild)
1306 PostMessageA(infoPtr->hwndChild, WM_MOUSEMOVE, wParam, lParam);
1307 return TRUE;
1309 case WM_MOUSELEAVE:
1310 return PAGER_MouseLeave (hwnd, wParam, lParam);
1312 case WM_LBUTTONDOWN:
1313 return PAGER_LButtonDown (hwnd, wParam, lParam);
1315 case WM_LBUTTONUP:
1316 return PAGER_LButtonUp (hwnd, wParam, lParam);
1318 case WM_ERASEBKGND:
1319 return PAGER_EraseBackground (hwnd, wParam, lParam);
1321 case WM_PAINT:
1322 return PAGER_Paint (hwnd, wParam);
1324 case WM_TIMER:
1325 /* if initial timer, kill it and start the repeat timer */
1326 if (wParam == TIMERID1)
1328 KillTimer(hwnd, TIMERID1);
1329 SetTimer(hwnd, TIMERID2, REPEAT_DELAY, 0);
1332 KillTimer(hwnd, TIMERID2);
1333 if (infoPtr->direction > 0)
1335 PAGER_Scroll(hwnd, infoPtr->direction);
1336 SetTimer(hwnd, TIMERID2, REPEAT_DELAY, 0);
1338 break;
1340 case WM_NOTIFY:
1341 case WM_COMMAND:
1342 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
1344 default:
1345 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1348 return 0;
1352 VOID
1353 PAGER_Register (void)
1355 WNDCLASSA wndClass;
1357 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1358 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
1359 wndClass.lpfnWndProc = (WNDPROC)PAGER_WindowProc;
1360 wndClass.cbClsExtra = 0;
1361 wndClass.cbWndExtra = sizeof(PAGER_INFO *);
1362 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1363 wndClass.hbrBackground = 0;
1364 wndClass.lpszClassName = WC_PAGESCROLLERA;
1366 RegisterClassA (&wndClass);
1370 VOID
1371 PAGER_Unregister (void)
1373 UnregisterClassA (WC_PAGESCROLLERA, (HINSTANCE)NULL);