4 * Copyright 1998, 1999 Eric Kohl
7 * Tested primarily with the controlspy Pager application.
8 * Susan Farley (susan@codeweavers.com)
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.
20 #include "debugtools.h"
22 DEFAULT_DEBUG_CHANNEL(pager);
26 HWND hwndChild; /* handle of the contained wnd */
27 BOOL bNoResize; /* set when created with CCS_NORESIZE */
28 BOOL bHorizontal;/* orientation of the control */
29 COLORREF clrBk; /* background color */
30 INT nBorder; /* border size for the control */
31 INT nButtonSize;/* size of the pager btns */
32 INT nPos; /* scroll position */
33 INT nDelta; /* scroll delta */
34 INT nWidth; /* from child wnd's response to PGN_CALCSIZE */
35 INT nHeight; /* from child wnd's response to PGN_CALCSIZE */
36 BOOL bForward; /* forward WM_MOUSEMOVE msgs to the contained wnd */
37 INT TLbtnState; /* state of top or left btn */
38 INT BRbtnState; /* state of bottom or right btn */
42 #define PAGER_GetInfoPtr(hwnd) ((PAGER_INFO *)GetWindowLongA(hwnd, 0))
44 #define MIN_ARROW_WIDTH 8
45 #define MIN_ARROW_HEIGHT 5
47 /* the horizontal arrows are:
60 PAGER_DrawHorzArrow (HDC hdc, RECT r, INT colorRef, BOOL left)
65 w = r.right - r.left + 1;
66 h = r.bottom - r.top + 1;
67 if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
68 return; /* refuse to draw partial arrow */
70 hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
73 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 3;
74 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
75 MoveToEx (hdc, x, y, NULL);
76 LineTo (hdc, x--, y+5); y++;
77 MoveToEx (hdc, x, y, NULL);
78 LineTo (hdc, x--, y+3); y++;
79 MoveToEx (hdc, x, y, NULL);
84 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
85 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
86 MoveToEx (hdc, x, y, NULL);
87 LineTo (hdc, x++, y+5); y++;
88 MoveToEx (hdc, x, y, NULL);
89 LineTo (hdc, x++, y+3); y++;
90 MoveToEx (hdc, x, y, NULL);
94 SelectObject( hdc, hOldPen );
97 /* the vertical arrows are:
107 PAGER_DrawVertArrow (HDC hdc, RECT r, INT colorRef, BOOL up)
112 w = r.right - r.left + 1;
113 h = r.bottom - r.top + 1;
114 if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
115 return; /* refuse to draw partial arrow */
117 hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
120 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
121 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 3;
122 MoveToEx (hdc, x, y, NULL);
123 LineTo (hdc, x+5, y--); x++;
124 MoveToEx (hdc, x, y, NULL);
125 LineTo (hdc, x+3, y--); x++;
126 MoveToEx (hdc, x, y, NULL);
127 LineTo (hdc, x+1, y);
131 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
132 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
133 MoveToEx (hdc, x, y, NULL);
134 LineTo (hdc, x+5, y++); x++;
135 MoveToEx (hdc, x, y, NULL);
136 LineTo (hdc, x+3, y++); x++;
137 MoveToEx (hdc, x, y, NULL);
138 LineTo (hdc, x+1, y);
141 SelectObject( hdc, hOldPen );
145 PAGER_DrawButton(HDC hdc, COLORREF clrBk, RECT arrowRect,
146 BOOL horz, BOOL topLeft, INT btnState)
148 HBRUSH hBrush, hOldBrush;
151 if (!btnState) /* PGF_INVISIBLE */
154 if ((rc.right - rc.left <= 0) || (rc.bottom - rc.top <= 0))
157 hBrush = CreateSolidBrush(clrBk);
158 hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
160 FillRect(hdc, &rc, hBrush);
162 if (btnState == PGF_HOT)
164 rc.left++, rc.top++; rc.right++, rc.bottom++;
165 DrawEdge( hdc, &rc, EDGE_RAISED, BF_RECT);
167 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
169 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
170 rc.left--, rc.top--; rc.right--, rc.bottom--;
172 else if (btnState == PGF_NORMAL)
174 DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
176 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
178 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
180 else if (btnState == PGF_DEPRESSED)
183 DrawEdge( hdc, &rc, BDR_SUNKENOUTER, BF_RECT);
185 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
187 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
190 else if (btnState == PGF_GRAYED)
192 DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
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);
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);
205 rc.left--, rc.top--; rc.right--, rc.bottom--;
208 SelectObject( hdc, hOldBrush );
209 DeleteObject(hBrush);
212 /* << PAGER_GetDropTarget >> */
214 static inline LRESULT
215 PAGER_ForwardMouse (HWND hwnd, WPARAM wParam)
217 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
218 TRACE("[%04x]\n", hwnd);
220 infoPtr->bForward = (BOOL)wParam;
225 static inline LRESULT
226 PAGER_GetButtonState (HWND hwnd, WPARAM wParam, LPARAM lParam)
228 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
229 LRESULT btnState = PGF_INVISIBLE;
230 INT btn = (INT)lParam;
231 TRACE("[%04x]\n", hwnd);
233 if (btn == PGB_TOPORLEFT)
234 btnState = infoPtr->TLbtnState;
235 else if (btn == PGB_BOTTOMORRIGHT)
236 btnState = infoPtr->BRbtnState;
242 static inline LRESULT
243 PAGER_GetPos(HWND hwnd)
245 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
246 TRACE("[%04x] returns %d\n", hwnd, infoPtr->nPos);
247 return (LRESULT)infoPtr->nPos;
250 static inline LRESULT
251 PAGER_GetButtonSize(HWND hwnd)
253 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
254 TRACE("[%04x] returns %d\n", hwnd, infoPtr->nButtonSize);
255 return (LRESULT)infoPtr->nButtonSize;
258 static inline LRESULT
259 PAGER_GetBorder(HWND hwnd)
261 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
262 TRACE("[%04x] returns %d\n", hwnd, infoPtr->nBorder);
263 return (LRESULT)infoPtr->nBorder;
266 static inline LRESULT
267 PAGER_GetBkColor(HWND hwnd)
269 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
270 TRACE("[%04x] returns %06lx\n", hwnd, infoPtr->clrBk);
271 return (LRESULT)infoPtr->clrBk;
275 PAGER_CalcSize (HWND hwnd, INT* size, BOOL getWidth)
278 ZeroMemory (&nmpgcs, sizeof (NMPGCALCSIZE));
279 nmpgcs.hdr.hwndFrom = hwnd;
280 nmpgcs.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
281 nmpgcs.hdr.code = PGN_CALCSIZE;
282 nmpgcs.dwFlag = getWidth ? PGF_CALCWIDTH : PGF_CALCHEIGHT;
283 nmpgcs.iWidth = getWidth ? *size : 0;
284 nmpgcs.iHeight = getWidth ? 0 : *size;
285 SendMessageA (hwnd, WM_NOTIFY,
286 (WPARAM)nmpgcs.hdr.idFrom, (LPARAM)&nmpgcs);
288 *size = getWidth ? nmpgcs.iWidth : nmpgcs.iHeight;
290 TRACE("[%04x] PGN_CALCSIZE returns %s=%d\n", hwnd,
291 getWidth ? "width" : "height", *size);
295 PAGER_PositionChildWnd(HWND hwnd, PAGER_INFO* infoPtr)
297 if (infoPtr->hwndChild)
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 if (infoPtr->bHorizontal)
307 TRACE("[%04x] SWP %dx%d at (%d,%d)\n", hwnd,
308 infoPtr->nWidth, infoPtr->nHeight,
310 SetWindowPos(infoPtr->hwndChild, 0,
312 infoPtr->nWidth, infoPtr->nHeight,
317 TRACE("[%04x] SWP %dx%d at (%d,%d)\n", hwnd,
318 infoPtr->nWidth, infoPtr->nHeight,
320 SetWindowPos(infoPtr->hwndChild, 0,
322 infoPtr->nWidth, infoPtr->nHeight,
326 InvalidateRect(infoPtr->hwndChild, NULL, FALSE);
331 PAGER_GetScrollRange(HWND hwnd, PAGER_INFO* infoPtr)
335 if (infoPtr->hwndChild)
337 INT wndSize, childSize;
339 GetWindowRect(hwnd, &wndRect);
341 if (infoPtr->bHorizontal)
343 wndSize = wndRect.right - wndRect.left;
344 PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
345 childSize = infoPtr->nWidth;
349 wndSize = wndRect.bottom - wndRect.top;
350 PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
351 childSize = infoPtr->nHeight;
354 TRACE("childSize = %d, wndSize = %d\n", childSize, wndSize);
355 if (childSize > wndSize)
356 scrollRange = childSize - wndSize + infoPtr->nButtonSize;
359 TRACE("[%04x] returns %d\n", hwnd, scrollRange);
364 PAGER_GrayAndRestoreBtns(PAGER_INFO* infoPtr, INT scrollRange,
365 BOOL* needsResize, BOOL* needsRepaint)
367 if (infoPtr->nPos > 0)
369 *needsResize |= !infoPtr->TLbtnState; /* PGF_INVISIBLE */
370 if (infoPtr->TLbtnState != PGF_DEPRESSED)
371 infoPtr->TLbtnState = PGF_NORMAL;
375 *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
376 infoPtr->TLbtnState = PGF_GRAYED;
379 if (scrollRange <= 0)
381 *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
382 infoPtr->TLbtnState = PGF_GRAYED;
383 *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
384 infoPtr->BRbtnState = PGF_GRAYED;
386 else if (infoPtr->nPos < scrollRange)
388 *needsResize |= !infoPtr->BRbtnState; /* PGF_INVISIBLE */
389 if (infoPtr->BRbtnState != PGF_DEPRESSED)
390 infoPtr->BRbtnState = PGF_NORMAL;
394 *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
395 infoPtr->BRbtnState = PGF_GRAYED;
401 PAGER_NormalizeBtns(PAGER_INFO* infoPtr, BOOL* needsRepaint)
403 if (infoPtr->TLbtnState & (PGF_HOT | PGF_DEPRESSED))
405 infoPtr->TLbtnState = PGF_NORMAL;
406 *needsRepaint = TRUE;
409 if (infoPtr->BRbtnState & (PGF_HOT | PGF_DEPRESSED))
411 infoPtr->BRbtnState = PGF_NORMAL;
412 *needsRepaint = TRUE;
417 PAGER_HideGrayBtns(PAGER_INFO* infoPtr, BOOL* needsResize)
419 if (infoPtr->TLbtnState == PGF_GRAYED)
421 infoPtr->TLbtnState = PGF_INVISIBLE;
425 if (infoPtr->BRbtnState == PGF_GRAYED)
427 infoPtr->BRbtnState = PGF_INVISIBLE;
433 PAGER_UpdateBtns(HWND hwnd, PAGER_INFO *infoPtr,
434 INT scrollRange, BOOL hideGrayBtns)
436 BOOL resizeClient = FALSE;
437 BOOL repaintBtns = FALSE;
440 PAGER_NormalizeBtns(infoPtr, &repaintBtns);
442 PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
445 PAGER_HideGrayBtns(infoPtr, &resizeClient);
447 if (resizeClient) /* initiate NCCalcSize to resize client wnd */
448 SetWindowPos(hwnd, 0,0,0,0,0,
449 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
450 SWP_NOZORDER | SWP_NOACTIVATE);
453 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
457 PAGER_SetPos(HWND hwnd, INT newPos, BOOL fromBtnPress)
459 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
460 INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
462 if ((scrollRange <= 0) || (newPos < 0))
464 else if (newPos > scrollRange)
465 infoPtr->nPos = scrollRange;
467 infoPtr->nPos = newPos;
469 TRACE("[%04x] pos=%d\n", hwnd, infoPtr->nPos);
471 /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
472 PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, !fromBtnPress);
473 PAGER_PositionChildWnd(hwnd, infoPtr);
479 PAGER_HandleWindowPosChanging(HWND hwnd, WINDOWPOS *winpos)
481 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
483 if (infoPtr->bNoResize && !(winpos->flags & SWP_NOSIZE))
485 /* don't let the app resize the nonscrollable dimension of a control
486 * that was created with CCS_NORESIZE style
487 * (i.e. height for a horizontal pager, or width for a vertical one) */
489 if (infoPtr->bHorizontal)
490 winpos->cy = infoPtr->nHeight;
492 winpos->cx = infoPtr->nWidth;
499 PAGER_SetFixedWidth(HWND hwnd, PAGER_INFO* infoPtr)
501 /* Must set the non-scrollable dimension to be less than the full height/width
502 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
503 * size, and experimentation shows that affect is almost right. */
507 GetWindowRect(hwnd, &wndRect);
509 /* see what the app says for btn width */
510 PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
512 if (infoPtr->bNoResize)
514 delta = wndRect.right - wndRect.left - infoPtr->nWidth;
515 if (delta > infoPtr->nButtonSize)
516 infoPtr->nWidth += 4 * infoPtr->nButtonSize / 3;
518 infoPtr->nWidth += infoPtr->nButtonSize / 3;
521 infoPtr->nDelta = wndRect.bottom - wndRect.top - infoPtr->nButtonSize;
523 TRACE("[%04x] infoPtr->nWidth set to %d\n",
524 hwnd, infoPtr->nWidth);
528 PAGER_SetFixedHeight(HWND hwnd, PAGER_INFO* infoPtr)
530 /* Must set the non-scrollable dimension to be less than the full height/width
531 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
532 * size, and experimentation shows that affect is almost right. */
536 GetWindowRect(hwnd, &wndRect);
538 /* see what the app says for btn height */
539 PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
541 if (infoPtr->bNoResize)
543 delta = wndRect.bottom - wndRect.top - infoPtr->nHeight;
544 if (delta > infoPtr->nButtonSize)
545 infoPtr->nHeight += 4 * infoPtr->nButtonSize / 3;
547 infoPtr->nHeight += infoPtr->nButtonSize / 3;
550 infoPtr->nDelta = wndRect.right - wndRect.left - infoPtr->nButtonSize;
552 TRACE("[%04x] infoPtr->nHeight set to %d\n",
553 hwnd, infoPtr->nHeight);
557 PAGER_RecalcSize(HWND hwnd)
559 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
560 TRACE("[%04x]\n", hwnd);
562 if (infoPtr->hwndChild)
564 INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
566 if (scrollRange <= 0)
567 PAGER_SetPos(hwnd, 0, FALSE);
570 PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, TRUE);
571 PAGER_PositionChildWnd(hwnd, infoPtr);
580 PAGER_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
582 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
583 COLORREF clrTemp = infoPtr->clrBk;
585 infoPtr->clrBk = (COLORREF)lParam;
586 TRACE("[%04x] %06lx\n", hwnd, infoPtr->clrBk);
588 PAGER_RecalcSize(hwnd);
590 return (LRESULT)clrTemp;
595 PAGER_SetBorder (HWND hwnd, WPARAM wParam, LPARAM lParam)
597 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
598 INT nTemp = infoPtr->nBorder;
600 infoPtr->nBorder = (INT)lParam;
601 TRACE("[%04x] %d\n", hwnd, infoPtr->nBorder);
603 PAGER_RecalcSize(hwnd);
605 return (LRESULT)nTemp;
610 PAGER_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
612 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
613 INT nTemp = infoPtr->nButtonSize;
615 infoPtr->nButtonSize = (INT)lParam;
616 TRACE("[%04x] %d\n", hwnd, infoPtr->nButtonSize);
618 PAGER_RecalcSize(hwnd);
620 return (LRESULT)nTemp;
625 PAGER_SetChild (HWND hwnd, WPARAM wParam, LPARAM lParam)
627 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
629 infoPtr->hwndChild = IsWindow ((HWND)lParam) ? (HWND)lParam : 0;
631 if (infoPtr->hwndChild)
633 TRACE("[%04x] hwndChild=%04x\n", hwnd, infoPtr->hwndChild);
635 if (infoPtr->bHorizontal)
636 PAGER_SetFixedHeight(hwnd, infoPtr);
638 PAGER_SetFixedWidth(hwnd, infoPtr);
640 /* adjust non-scrollable dimension to fit the child */
641 SetWindowPos(hwnd, 0, 0,0,
642 infoPtr->bHorizontal ? infoPtr->nDelta + infoPtr->nButtonSize : infoPtr->nWidth,
643 infoPtr->bHorizontal ? infoPtr->nHeight : infoPtr->nDelta + infoPtr->nButtonSize,
644 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER);
646 /* position child within the page scroller */
647 SetWindowPos(infoPtr->hwndChild, HWND_TOP,
649 SWP_SHOWWINDOW | SWP_NOSIZE);
651 PAGER_SetPos(hwnd, 0, FALSE);
658 PAGER_Scroll(HWND hwnd, INT dir)
660 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
661 NMPGSCROLL nmpgScroll;
663 if (infoPtr->hwndChild)
666 ZeroMemory (&nmpgScroll, sizeof (NMPGSCROLL));
667 nmpgScroll.hdr.hwndFrom = hwnd;
668 nmpgScroll.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
669 nmpgScroll.hdr.code = PGN_SCROLL;
671 GetClientRect(hwnd, &nmpgScroll.rcParent);
672 nmpgScroll.iXpos = nmpgScroll.iYpos = 0;
673 nmpgScroll.iDir = dir;
674 nmpgScroll.iScroll = infoPtr->nDelta;
676 if (infoPtr->bHorizontal)
677 nmpgScroll.iXpos = infoPtr->nPos;
679 nmpgScroll.iYpos = infoPtr->nPos;
681 TRACE("[%04x] sending PGN_SCROLL\n", hwnd);
682 res = SendMessageA (hwnd, WM_NOTIFY,
683 (WPARAM)nmpgScroll.hdr.idFrom, (LPARAM)&nmpgScroll);
685 if (res && infoPtr->nDelta != nmpgScroll.iScroll)
687 TRACE("delta changing from %d to %d\n",
688 infoPtr->nDelta, nmpgScroll.iScroll);
689 infoPtr->nDelta = nmpgScroll.iScroll;
692 if (dir == PGF_SCROLLLEFT || dir == PGF_SCROLLUP)
693 PAGER_SetPos(hwnd, infoPtr->nPos - infoPtr->nDelta, TRUE);
695 PAGER_SetPos(hwnd, infoPtr->nPos + infoPtr->nDelta, TRUE);
700 PAGER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
703 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
706 SetWindowLongA(hwnd, GWL_STYLE, dwStyle & WS_CLIPCHILDREN);
708 /* allocate memory for info structure */
709 infoPtr = (PAGER_INFO *)COMCTL32_Alloc (sizeof(PAGER_INFO));
710 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
712 /* set default settings */
713 infoPtr->hwndChild = (HWND)NULL;
714 infoPtr->bNoResize = dwStyle & CCS_NORESIZE;
715 infoPtr->clrBk = GetSysColor(COLOR_BTNFACE);
716 infoPtr->nBorder = 0;
717 infoPtr->nButtonSize = 12;
720 infoPtr->nHeight = 0;
721 infoPtr->bForward = FALSE;
722 infoPtr->TLbtnState = PGF_INVISIBLE;
723 infoPtr->BRbtnState = PGF_INVISIBLE;
725 if (dwStyle & PGS_AUTOSCROLL)
726 FIXME("[%04x] Autoscroll style is not implemented yet.\n", hwnd);
727 if (dwStyle & PGS_DRAGNDROP)
728 FIXME("[%04x] Drag and Drop style is not implemented yet.\n", hwnd);
729 if ((dwStyle & PGS_HORZ) && (dwStyle & PGS_VERT))
731 ERR("[%04x] Cannot have both horizontal and vertical styles.\n", hwnd);
732 ERR("[%04x] Defaulting to vertical.\n", hwnd);
733 dwStyle &= ~PGS_HORZ;
735 else if (!(dwStyle & PGS_HORZ) && !(dwStyle & PGS_VERT))
736 dwStyle |= PGS_VERT; /* the default according to MSDN */
738 infoPtr->bHorizontal = dwStyle & PGS_HORZ;
740 GetWindowRect(hwnd, &rect);
741 if (infoPtr->bHorizontal)
743 infoPtr->nHeight = rect.bottom - rect.top;
744 infoPtr->nDelta = rect.right - rect.left - infoPtr->nButtonSize;
745 TRACE("height = %d %s\n", infoPtr->nHeight,
746 infoPtr->bNoResize ? "CCS_NORESIZE" : "");
750 infoPtr->nWidth = rect.right - rect.left;
751 infoPtr->nDelta = rect.bottom - rect.top - infoPtr->nButtonSize;
752 TRACE("width = %d %s\n", infoPtr->nWidth,
753 infoPtr->bNoResize ? "CCS_NORESIZE" : "");
756 TRACE("[%04x] orientation = %s\n", hwnd,
757 infoPtr->bHorizontal ? "PGS_HORZ" : "PGS_VERT");
764 PAGER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
766 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
767 /* free pager info data */
768 COMCTL32_Free (infoPtr);
769 SetWindowLongA (hwnd, 0, 0);
774 PAGER_NCCalcSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
776 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
777 LPRECT lpRect = (LPRECT)lParam;
779 * lParam points to a RECT struct. On entry, the struct
780 * contains the proposed wnd rectangle for the window.
781 * On exit, the struct should contain the screen
782 * coordinates of the corresponding window's client area.
785 if (infoPtr->bHorizontal)
787 if (infoPtr->TLbtnState) /* != PGF_INVISIBLE */
788 lpRect->left += infoPtr->nButtonSize;
789 if (infoPtr->BRbtnState)
790 lpRect->right -= infoPtr->nButtonSize;
794 if (infoPtr->TLbtnState)
795 lpRect->top += infoPtr->nButtonSize;
796 if (infoPtr->BRbtnState)
797 lpRect->bottom -= infoPtr->nButtonSize;
800 TRACE("[%04x] client rect set to %dx%d at (%d,%d)\n", hwnd,
801 lpRect->right-lpRect->left,
802 lpRect->bottom-lpRect->top,
803 lpRect->left, lpRect->top);
809 PAGER_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
811 PAGER_INFO* infoPtr = PAGER_GetInfoPtr(hwnd);
812 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
813 RECT rcWindow, rcBottomRight, rcTopLeft;
816 if (dwStyle & WS_MINIMIZE)
819 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
821 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
824 GetWindowRect (hwnd, &rcWindow);
825 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
827 rcTopLeft = rcBottomRight = rcWindow;
828 if (infoPtr->bHorizontal)
830 rcTopLeft.right = rcTopLeft.left + infoPtr->nButtonSize;
831 rcBottomRight.left = rcBottomRight.right - infoPtr->nButtonSize;
835 rcTopLeft.bottom = rcTopLeft.top + infoPtr->nButtonSize;
836 rcBottomRight.top = rcBottomRight.bottom - infoPtr->nButtonSize;
839 PAGER_DrawButton(hdc, infoPtr->clrBk, rcTopLeft,
840 infoPtr->bHorizontal, TRUE, infoPtr->TLbtnState);
841 PAGER_DrawButton(hdc, infoPtr->clrBk, rcBottomRight,
842 infoPtr->bHorizontal, FALSE, infoPtr->BRbtnState);
844 ReleaseDC( hwnd, hdc );
849 PAGER_HitTest (HWND hwnd, LPPOINT pt)
851 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
854 GetClientRect (hwnd, &clientRect);
856 if (PtInRect(&clientRect, *pt))
858 /* TRACE("HTCLIENT\n"); */
862 if (infoPtr->TLbtnState && infoPtr->TLbtnState != PGF_GRAYED)
864 if (infoPtr->bHorizontal)
866 if (pt->x < clientRect.left)
868 /* TRACE("HTLEFT\n"); */
874 if (pt->y < clientRect.top)
876 /* TRACE("HTTOP\n"); */
882 if (infoPtr->BRbtnState && infoPtr->BRbtnState != PGF_GRAYED)
884 if (infoPtr->bHorizontal)
886 if (pt->x > clientRect.right)
888 /* TRACE("HTRIGHT\n"); */
894 if (pt->y > clientRect.bottom)
896 /* TRACE("HTBOTTOM\n"); */
902 /* TRACE("HTNOWHERE\n"); */
907 PAGER_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
909 POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
910 ScreenToClient (hwnd, &pt);
911 return PAGER_HitTest(hwnd, &pt);
915 PAGER_SetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
917 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
918 BOOL notCaptured = FALSE;
920 switch(LOWORD(lParam))
924 if ((notCaptured = infoPtr->TLbtnState != PGF_HOT))
925 infoPtr->TLbtnState = PGF_HOT;
929 if ((notCaptured = infoPtr->BRbtnState != PGF_HOT))
930 infoPtr->BRbtnState = PGF_HOT;
938 TRACKMOUSEEVENT trackinfo;
940 TRACE("[%04x] SetCapture\n", hwnd);
943 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
944 trackinfo.dwFlags = TME_QUERY;
945 trackinfo.hwndTrack = hwnd;
946 trackinfo.dwHoverTime = HOVER_DEFAULT;
948 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
949 _TrackMouseEvent(&trackinfo);
951 /* Make sure tracking is enabled so we recieve a WM_MOUSELEAVE message */
952 if(!(trackinfo.dwFlags & TME_LEAVE)) {
953 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
955 /* call TRACKMOUSEEVENT so we recieve a WM_MOUSELEAVE message */
956 /* and can properly deactivate the hot button */
957 _TrackMouseEvent(&trackinfo);
960 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
967 PAGER_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
969 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
971 TRACE("[%04x] ReleaseCapture\n", hwnd);
974 /* Notify parent of released mouse capture */
975 if (infoPtr->hwndChild)
978 ZeroMemory (&nmhdr, sizeof (NMHDR));
979 nmhdr.hwndFrom = hwnd;
980 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
981 nmhdr.code = NM_RELEASEDCAPTURE;
982 SendMessageA (GetParent (infoPtr->hwndChild), WM_NOTIFY,
983 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
986 /* make HOT btns NORMAL and hide gray btns */
987 PAGER_UpdateBtns(hwnd, infoPtr, -1, TRUE);
993 PAGER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
995 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
996 BOOL repaintBtns = FALSE;
997 POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
1000 TRACE("[%04x]\n", hwnd);
1002 if (infoPtr->nDelta <= 0)
1005 hit = PAGER_HitTest(hwnd, &pt);
1007 /* put btn in DEPRESSED state */
1008 if (hit == HTLEFT || hit == HTTOP)
1010 repaintBtns = infoPtr->TLbtnState != PGF_DEPRESSED;
1011 infoPtr->TLbtnState = PGF_DEPRESSED;
1013 else if (hit == HTRIGHT || hit == HTBOTTOM)
1015 repaintBtns = infoPtr->BRbtnState != PGF_DEPRESSED;
1016 infoPtr->BRbtnState = PGF_DEPRESSED;
1020 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
1025 TRACE("[%04x] PGF_SCROLLLEFT\n", hwnd);
1026 PAGER_Scroll(hwnd, PGF_SCROLLLEFT);
1029 TRACE("[%04x] PGF_SCROLLUP\n", hwnd);
1030 PAGER_Scroll(hwnd, PGF_SCROLLUP);
1033 TRACE("[%04x] PGF_SCROLLRIGHT\n", hwnd);
1034 PAGER_Scroll(hwnd, PGF_SCROLLRIGHT);
1037 TRACE("[%04x] PGF_SCROLLDOWN\n", hwnd);
1038 PAGER_Scroll(hwnd, PGF_SCROLLDOWN);
1048 PAGER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1050 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1051 TRACE("[%04x]\n", hwnd);
1053 /* make PRESSED btns NORMAL but don't hide gray btns */
1054 PAGER_UpdateBtns(hwnd, infoPtr, -1, FALSE);
1060 PAGER_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
1062 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1063 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
1065 GetClientRect (hwnd, &rect);
1067 FillRect ((HDC)wParam, &rect, hBrush);
1068 DeleteObject (hBrush);
1074 PAGER_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
1076 /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
1078 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1079 TRACE("[%04x] %dx%d\n", hwnd, LOWORD(lParam), HIWORD(lParam));
1081 if (infoPtr->bHorizontal)
1083 infoPtr->nHeight = HIWORD(lParam);
1084 infoPtr->nDelta = LOWORD(lParam) - infoPtr->nButtonSize;
1088 infoPtr->nWidth = LOWORD(lParam);
1089 infoPtr->nDelta = HIWORD(lParam) - infoPtr->nButtonSize;
1092 return PAGER_RecalcSize(hwnd);
1096 static LRESULT WINAPI
1097 PAGER_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1099 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1101 if (!infoPtr && (uMsg != WM_CREATE))
1102 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1106 case PGM_FORWARDMOUSE:
1107 return PAGER_ForwardMouse (hwnd, wParam);
1109 case PGM_GETBKCOLOR:
1110 return PAGER_GetBkColor(hwnd);
1113 return PAGER_GetBorder(hwnd);
1115 case PGM_GETBUTTONSIZE:
1116 return PAGER_GetButtonSize(hwnd);
1119 return PAGER_GetPos(hwnd);
1121 case PGM_GETBUTTONSTATE:
1122 return PAGER_GetButtonState (hwnd, wParam, lParam);
1124 /* case PGM_GETDROPTARGET: */
1126 case PGM_RECALCSIZE:
1127 return PAGER_RecalcSize(hwnd);
1129 case PGM_SETBKCOLOR:
1130 return PAGER_SetBkColor (hwnd, wParam, lParam);
1133 return PAGER_SetBorder (hwnd, wParam, lParam);
1135 case PGM_SETBUTTONSIZE:
1136 return PAGER_SetButtonSize (hwnd, wParam, lParam);
1139 return PAGER_SetChild (hwnd, wParam, lParam);
1142 return PAGER_SetPos(hwnd, (INT)lParam, FALSE);
1145 return PAGER_Create (hwnd, wParam, lParam);
1148 return PAGER_Destroy (hwnd, wParam, lParam);
1151 return PAGER_Size (hwnd, wParam, lParam);
1154 return PAGER_NCPaint (hwnd, wParam, lParam);
1156 case WM_WINDOWPOSCHANGING:
1157 return PAGER_HandleWindowPosChanging (hwnd, (WINDOWPOS*)lParam);
1160 return PAGER_NCCalcSize (hwnd, wParam, lParam);
1163 return PAGER_NCHitTest (hwnd, wParam, lParam);
1167 if (hwnd == (HWND)wParam)
1168 return PAGER_SetCursor(hwnd, wParam, lParam);
1169 else /* its for the child */
1174 if (infoPtr->bForward && infoPtr->hwndChild)
1175 PostMessageA(infoPtr->hwndChild, WM_MOUSEMOVE, wParam, lParam);
1179 return PAGER_MouseLeave (hwnd, wParam, lParam);
1181 case WM_LBUTTONDOWN:
1182 return PAGER_LButtonDown (hwnd, wParam, lParam);
1185 return PAGER_LButtonUp (hwnd, wParam, lParam);
1188 return PAGER_EraseBackground (hwnd, wParam, lParam);
1191 return PAGER_Paint (hwnd, wParam);
1195 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
1198 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1206 PAGER_Register (void)
1210 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1211 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
1212 wndClass.lpfnWndProc = (WNDPROC)PAGER_WindowProc;
1213 wndClass.cbClsExtra = 0;
1214 wndClass.cbWndExtra = sizeof(PAGER_INFO *);
1215 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1216 wndClass.hbrBackground = 0;
1217 wndClass.lpszClassName = WC_PAGESCROLLERA;
1219 RegisterClassA (&wndClass);
1224 PAGER_Unregister (void)
1226 UnregisterClassA (WC_PAGESCROLLERA, (HINSTANCE)NULL);