4 * Copyright 1998, 1999 Eric Kohl
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Tested primarily with the controlspy Pager application.
22 * Susan Farley (susan@codeweavers.com)
25 * Implement repetitive button press.
26 * Adjust arrow size relative to size of button.
27 * Allow border size changes.
28 * Implement drag and drop style.
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(pager);
40 HWND hwndChild; /* handle of the contained wnd */
41 BOOL bNoResize; /* set when created with CCS_NORESIZE */
42 COLORREF clrBk; /* background color */
43 INT nBorder; /* border size for the control */
44 INT nButtonSize;/* size of the pager btns */
45 INT nPos; /* scroll position */
46 INT nWidth; /* from child wnd's response to PGN_CALCSIZE */
47 INT nHeight; /* from child wnd's response to PGN_CALCSIZE */
48 BOOL bForward; /* forward WM_MOUSEMOVE msgs to the contained wnd */
49 BOOL bCapture; /* we have captured the mouse */
50 INT TLbtnState; /* state of top or left btn */
51 INT BRbtnState; /* state of bottom or right btn */
52 INT direction; /* direction of the scroll, (e.g. PGF_SCROLLUP) */
55 #define PAGER_GetInfoPtr(hwnd) ((PAGER_INFO *)GetWindowLongA(hwnd, 0))
56 #define PAGER_IsHorizontal(hwnd) ((GetWindowLongA (hwnd, GWL_STYLE) & PGS_HORZ))
58 #define MIN_ARROW_WIDTH 8
59 #define MIN_ARROW_HEIGHT 5
63 #define INITIAL_DELAY 500
64 #define REPEAT_DELAY 50
66 /* the horizontal arrows are:
79 PAGER_DrawHorzArrow (HDC hdc, RECT r, INT colorRef, BOOL left)
84 w = r.right - r.left + 1;
85 h = r.bottom - r.top + 1;
86 if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
87 return; /* refuse to draw partial arrow */
89 hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
92 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 3;
93 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
94 MoveToEx (hdc, x, y, NULL);
95 LineTo (hdc, x--, y+5); y++;
96 MoveToEx (hdc, x, y, NULL);
97 LineTo (hdc, x--, y+3); y++;
98 MoveToEx (hdc, x, y, NULL);
103 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
104 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
105 MoveToEx (hdc, x, y, NULL);
106 LineTo (hdc, x++, y+5); y++;
107 MoveToEx (hdc, x, y, NULL);
108 LineTo (hdc, x++, y+3); y++;
109 MoveToEx (hdc, x, y, NULL);
110 LineTo (hdc, x, y+1);
113 SelectObject( hdc, hOldPen );
116 /* the vertical arrows are:
126 PAGER_DrawVertArrow (HDC hdc, RECT r, INT colorRef, BOOL up)
131 w = r.right - r.left + 1;
132 h = r.bottom - r.top + 1;
133 if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
134 return; /* refuse to draw partial arrow */
136 hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
139 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
140 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 3;
141 MoveToEx (hdc, x, y, NULL);
142 LineTo (hdc, x+5, y--); x++;
143 MoveToEx (hdc, x, y, NULL);
144 LineTo (hdc, x+3, y--); x++;
145 MoveToEx (hdc, x, y, NULL);
146 LineTo (hdc, x+1, y);
150 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
151 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
152 MoveToEx (hdc, x, y, NULL);
153 LineTo (hdc, x+5, y++); x++;
154 MoveToEx (hdc, x, y, NULL);
155 LineTo (hdc, x+3, y++); x++;
156 MoveToEx (hdc, x, y, NULL);
157 LineTo (hdc, x+1, y);
160 SelectObject( hdc, hOldPen );
164 PAGER_DrawButton(HDC hdc, COLORREF clrBk, RECT arrowRect,
165 BOOL horz, BOOL topLeft, INT btnState)
167 HBRUSH hBrush, hOldBrush;
170 if (!btnState) /* PGF_INVISIBLE */
173 if ((rc.right - rc.left <= 0) || (rc.bottom - rc.top <= 0))
176 hBrush = CreateSolidBrush(clrBk);
177 hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
179 FillRect(hdc, &rc, hBrush);
181 if (btnState == PGF_HOT)
183 DrawEdge( hdc, &rc, BDR_RAISEDINNER, BF_RECT);
185 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
187 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
189 else if (btnState == PGF_NORMAL)
191 DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
193 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
195 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
197 else if (btnState == PGF_DEPRESSED)
199 DrawEdge( hdc, &rc, BDR_SUNKENOUTER, BF_RECT);
201 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
203 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
205 else if (btnState == PGF_GRAYED)
207 DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
210 PAGER_DrawHorzArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
211 rc.left++, rc.top++; rc.right++, rc.bottom++;
212 PAGER_DrawHorzArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
216 PAGER_DrawVertArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
217 rc.left++, rc.top++; rc.right++, rc.bottom++;
218 PAGER_DrawVertArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
222 SelectObject( hdc, hOldBrush );
223 DeleteObject(hBrush);
226 static void PAGER_CaptureandTrack(PAGER_INFO *infoPtr, HWND hwnd)
228 TRACKMOUSEEVENT trackinfo;
230 TRACE("[%08x] SetCapture\n", hwnd);
232 infoPtr->bCapture = TRUE;
234 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
235 trackinfo.dwFlags = TME_QUERY;
236 trackinfo.hwndTrack = hwnd;
237 trackinfo.dwHoverTime = HOVER_DEFAULT;
239 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
240 _TrackMouseEvent(&trackinfo);
242 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
243 if(!(trackinfo.dwFlags & TME_LEAVE)) {
244 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
246 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
247 /* and can properly deactivate the hot button */
248 _TrackMouseEvent(&trackinfo);
253 /* << PAGER_GetDropTarget >> */
255 static inline LRESULT
256 PAGER_ForwardMouse (HWND hwnd, WPARAM wParam)
258 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
259 TRACE("[%08x]\n", hwnd);
261 infoPtr->bForward = (BOOL)wParam;
266 static inline LRESULT
267 PAGER_GetButtonState (HWND hwnd, WPARAM wParam, LPARAM lParam)
269 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
270 LRESULT btnState = PGF_INVISIBLE;
271 INT btn = (INT)lParam;
272 TRACE("[%08x]\n", hwnd);
274 if (btn == PGB_TOPORLEFT)
275 btnState = infoPtr->TLbtnState;
276 else if (btn == PGB_BOTTOMORRIGHT)
277 btnState = infoPtr->BRbtnState;
283 static inline LRESULT
284 PAGER_GetPos(HWND hwnd)
286 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
287 TRACE("[%08x] returns %d\n", hwnd, infoPtr->nPos);
288 return (LRESULT)infoPtr->nPos;
291 static inline LRESULT
292 PAGER_GetButtonSize(HWND hwnd)
294 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
295 TRACE("[%08x] returns %d\n", hwnd, infoPtr->nButtonSize);
296 return (LRESULT)infoPtr->nButtonSize;
299 static inline LRESULT
300 PAGER_GetBorder(HWND hwnd)
302 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
303 TRACE("[%08x] returns %d\n", hwnd, infoPtr->nBorder);
304 return (LRESULT)infoPtr->nBorder;
307 static inline LRESULT
308 PAGER_GetBkColor(HWND hwnd)
310 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
311 TRACE("[%08x] returns %06lx\n", hwnd, infoPtr->clrBk);
312 return (LRESULT)infoPtr->clrBk;
316 PAGER_CalcSize (HWND hwnd, INT* size, BOOL getWidth)
319 ZeroMemory (&nmpgcs, sizeof (NMPGCALCSIZE));
320 nmpgcs.hdr.hwndFrom = hwnd;
321 nmpgcs.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
322 nmpgcs.hdr.code = PGN_CALCSIZE;
323 nmpgcs.dwFlag = getWidth ? PGF_CALCWIDTH : PGF_CALCHEIGHT;
324 nmpgcs.iWidth = getWidth ? *size : 0;
325 nmpgcs.iHeight = getWidth ? 0 : *size;
326 SendMessageA (GetParent (hwnd), WM_NOTIFY,
327 (WPARAM)nmpgcs.hdr.idFrom, (LPARAM)&nmpgcs);
329 *size = getWidth ? nmpgcs.iWidth : nmpgcs.iHeight;
331 TRACE("[%08x] PGN_CALCSIZE returns %s=%d\n", hwnd,
332 getWidth ? "width" : "height", *size);
336 PAGER_PositionChildWnd(HWND hwnd, PAGER_INFO* infoPtr)
338 if (infoPtr->hwndChild)
341 int nPos = infoPtr->nPos;
343 /* compensate for a grayed btn, which will soon become invisible */
344 if (infoPtr->TLbtnState == PGF_GRAYED)
345 nPos += infoPtr->nButtonSize;
347 GetClientRect(hwnd, &rcClient);
349 if (PAGER_IsHorizontal(hwnd))
351 int wndSize = max(0, rcClient.right - rcClient.left);
352 if (infoPtr->nWidth < wndSize)
353 infoPtr->nWidth = wndSize;
355 TRACE("[%08x] SWP %dx%d at (%d,%d)\n", hwnd,
356 infoPtr->nWidth, infoPtr->nHeight,
358 SetWindowPos(infoPtr->hwndChild, 0,
360 infoPtr->nWidth, infoPtr->nHeight,
365 int wndSize = max(0, rcClient.bottom - rcClient.top);
366 if (infoPtr->nHeight < wndSize)
367 infoPtr->nHeight = wndSize;
369 TRACE("[%08x] SWP %dx%d at (%d,%d)\n", hwnd,
370 infoPtr->nWidth, infoPtr->nHeight,
372 SetWindowPos(infoPtr->hwndChild, 0,
374 infoPtr->nWidth, infoPtr->nHeight,
378 InvalidateRect(infoPtr->hwndChild, NULL, TRUE);
383 PAGER_GetScrollRange(HWND hwnd, PAGER_INFO* infoPtr)
387 if (infoPtr->hwndChild)
389 INT wndSize, childSize;
391 GetWindowRect(hwnd, &wndRect);
393 if (PAGER_IsHorizontal(hwnd))
395 wndSize = wndRect.right - wndRect.left;
396 PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
397 childSize = infoPtr->nWidth;
401 wndSize = wndRect.bottom - wndRect.top;
402 PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
403 childSize = infoPtr->nHeight;
406 TRACE("childSize = %d, wndSize = %d\n", childSize, wndSize);
407 if (childSize > wndSize)
408 scrollRange = childSize - wndSize + infoPtr->nButtonSize;
411 TRACE("[%08x] returns %d\n", hwnd, scrollRange);
416 PAGER_GrayAndRestoreBtns(PAGER_INFO* infoPtr, INT scrollRange,
417 BOOL* needsResize, BOOL* needsRepaint)
419 if (infoPtr->nPos > 0)
421 *needsResize |= !infoPtr->TLbtnState; /* PGF_INVISIBLE */
422 if (infoPtr->TLbtnState != PGF_DEPRESSED)
423 infoPtr->TLbtnState = PGF_NORMAL;
427 *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
428 infoPtr->TLbtnState = PGF_GRAYED;
431 if (scrollRange <= 0)
433 *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
434 infoPtr->TLbtnState = PGF_GRAYED;
435 *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
436 infoPtr->BRbtnState = PGF_GRAYED;
438 else if (infoPtr->nPos < scrollRange)
440 *needsResize |= !infoPtr->BRbtnState; /* PGF_INVISIBLE */
441 if (infoPtr->BRbtnState != PGF_DEPRESSED)
442 infoPtr->BRbtnState = PGF_NORMAL;
446 *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
447 infoPtr->BRbtnState = PGF_GRAYED;
453 PAGER_NormalizeBtns(PAGER_INFO* infoPtr, BOOL* needsRepaint)
455 if (infoPtr->TLbtnState & (PGF_HOT | PGF_DEPRESSED))
457 infoPtr->TLbtnState = PGF_NORMAL;
458 *needsRepaint = TRUE;
461 if (infoPtr->BRbtnState & (PGF_HOT | PGF_DEPRESSED))
463 infoPtr->BRbtnState = PGF_NORMAL;
464 *needsRepaint = TRUE;
469 PAGER_HideGrayBtns(PAGER_INFO* infoPtr, BOOL* needsResize)
471 if (infoPtr->TLbtnState == PGF_GRAYED)
473 infoPtr->TLbtnState = PGF_INVISIBLE;
477 if (infoPtr->BRbtnState == PGF_GRAYED)
479 infoPtr->BRbtnState = PGF_INVISIBLE;
485 PAGER_UpdateBtns(HWND hwnd, PAGER_INFO *infoPtr,
486 INT scrollRange, BOOL hideGrayBtns)
488 BOOL resizeClient = FALSE;
489 BOOL repaintBtns = FALSE;
492 PAGER_NormalizeBtns(infoPtr, &repaintBtns);
494 PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
497 PAGER_HideGrayBtns(infoPtr, &resizeClient);
499 if (resizeClient) /* initiate NCCalcSize to resize client wnd */ {
500 SetWindowPos(hwnd, 0,0,0,0,0,
501 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
502 SWP_NOZORDER | SWP_NOACTIVATE);
506 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
510 PAGER_SetPos(HWND hwnd, INT newPos, BOOL fromBtnPress)
512 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
513 INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
514 INT oldPos = infoPtr->nPos;
516 if ((scrollRange <= 0) || (newPos < 0))
518 else if (newPos > scrollRange)
519 infoPtr->nPos = scrollRange;
521 infoPtr->nPos = newPos;
523 TRACE("[%08x] pos=%d, oldpos=%d\n", hwnd, infoPtr->nPos, oldPos);
525 if (infoPtr->nPos != oldPos)
527 /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
528 PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, !fromBtnPress);
529 PAGER_PositionChildWnd(hwnd, infoPtr);
536 PAGER_HandleWindowPosChanging(HWND hwnd, WPARAM wParam, WINDOWPOS *winpos)
538 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
540 if (infoPtr->bNoResize && !(winpos->flags & SWP_NOSIZE))
542 /* don't let the app resize the nonscrollable dimension of a control
543 * that was created with CCS_NORESIZE style
544 * (i.e. height for a horizontal pager, or width for a vertical one) */
546 /* except if the current dimension is 0 and app is setting for
547 * first time, then save amount as dimension. - GA 8/01 */
549 if (PAGER_IsHorizontal(hwnd))
550 if (!infoPtr->nHeight && winpos->cy)
551 infoPtr->nHeight = winpos->cy;
553 winpos->cy = infoPtr->nHeight;
555 if (!infoPtr->nWidth && winpos->cx)
556 infoPtr->nWidth = winpos->cx;
558 winpos->cx = infoPtr->nWidth;
562 DefWindowProcA (hwnd, WM_WINDOWPOSCHANGING, wParam, (LPARAM)winpos);
568 PAGER_SetFixedWidth(HWND hwnd, PAGER_INFO* infoPtr)
570 /* Must set the non-scrollable dimension to be less than the full height/width
571 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
572 * size, and experimentation shows that affect is almost right. */
576 GetWindowRect(hwnd, &wndRect);
578 /* see what the app says for btn width */
579 PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
581 if (infoPtr->bNoResize)
583 delta = wndRect.right - wndRect.left - infoPtr->nWidth;
584 if (delta > infoPtr->nButtonSize)
585 infoPtr->nWidth += 4 * infoPtr->nButtonSize / 3;
587 infoPtr->nWidth += infoPtr->nButtonSize / 3;
590 h = wndRect.bottom - wndRect.top + infoPtr->nButtonSize;
592 TRACE("[%08x] infoPtr->nWidth set to %d\n",
593 hwnd, infoPtr->nWidth);
599 PAGER_SetFixedHeight(HWND hwnd, PAGER_INFO* infoPtr)
601 /* Must set the non-scrollable dimension to be less than the full height/width
602 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
603 * size, and experimentation shows that affect is almost right. */
607 GetWindowRect(hwnd, &wndRect);
609 /* see what the app says for btn height */
610 PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
612 if (infoPtr->bNoResize)
614 delta = wndRect.bottom - wndRect.top - infoPtr->nHeight;
615 if (delta > infoPtr->nButtonSize)
616 infoPtr->nHeight += infoPtr->nButtonSize;
618 infoPtr->nHeight += infoPtr->nButtonSize / 3;
621 w = wndRect.right - wndRect.left + infoPtr->nButtonSize;
623 TRACE("[%08x] infoPtr->nHeight set to %d\n",
624 hwnd, infoPtr->nHeight);
629 /******************************************************************
630 * For the PGM_RECALCSIZE message (but not the other uses in *
631 * this module), the native control does only the following: *
633 * if (some condition) *
634 * PostMessageA(hwnd, EM_FMTLINES, 0, 0); *
635 * return DefWindowProcA(hwnd, PGM_RECALCSIZE, 0, 0); *
637 * When we figure out what the "some condition" is we will *
638 * implement that for the message processing. *
639 ******************************************************************/
642 PAGER_RecalcSize(HWND hwnd)
644 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
646 TRACE("[%08x]\n", hwnd);
648 if (infoPtr->hwndChild)
650 INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
652 if (scrollRange <= 0)
655 PAGER_SetPos(hwnd, 0, FALSE);
659 PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, TRUE);
660 PAGER_PositionChildWnd(hwnd, infoPtr);
669 PAGER_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
671 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
672 COLORREF clrTemp = infoPtr->clrBk;
674 infoPtr->clrBk = (COLORREF)lParam;
675 TRACE("[%08x] %06lx\n", hwnd, infoPtr->clrBk);
677 /* the native control seems to do things this way */
678 SetWindowPos(hwnd, 0,0,0,0,0,
679 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
680 SWP_NOZORDER | SWP_NOACTIVATE);
682 RedrawWindow(hwnd, 0, 0, RDW_ERASE | RDW_INVALIDATE);
684 return (LRESULT)clrTemp;
689 PAGER_SetBorder (HWND hwnd, WPARAM wParam, LPARAM lParam)
691 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
692 INT nTemp = infoPtr->nBorder;
694 infoPtr->nBorder = (INT)lParam;
695 TRACE("[%08x] %d\n", hwnd, infoPtr->nBorder);
697 PAGER_RecalcSize(hwnd);
699 return (LRESULT)nTemp;
704 PAGER_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
706 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
707 INT nTemp = infoPtr->nButtonSize;
709 infoPtr->nButtonSize = (INT)lParam;
710 TRACE("[%08x] %d\n", hwnd, infoPtr->nButtonSize);
712 PAGER_RecalcSize(hwnd);
714 return (LRESULT)nTemp;
719 PAGER_SetChild (HWND hwnd, WPARAM wParam, LPARAM lParam)
721 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
724 infoPtr->hwndChild = IsWindow ((HWND)lParam) ? (HWND)lParam : 0;
726 if (infoPtr->hwndChild)
728 TRACE("[%08x] hwndChild=%08x\n", hwnd, infoPtr->hwndChild);
730 if (PAGER_IsHorizontal(hwnd)) {
731 hw = PAGER_SetFixedHeight(hwnd, infoPtr);
732 /* adjust non-scrollable dimension to fit the child */
733 SetWindowPos(hwnd, 0, 0,0, hw, infoPtr->nHeight,
734 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER |
735 SWP_NOSIZE | SWP_NOACTIVATE);
738 hw = PAGER_SetFixedWidth(hwnd, infoPtr);
739 /* adjust non-scrollable dimension to fit the child */
740 SetWindowPos(hwnd, 0, 0,0, infoPtr->nWidth, hw,
741 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER |
742 SWP_NOSIZE | SWP_NOACTIVATE);
745 /* position child within the page scroller */
746 SetWindowPos(infoPtr->hwndChild, HWND_TOP,
748 SWP_SHOWWINDOW | SWP_NOSIZE); /* native is 0 */
751 PAGER_SetPos(hwnd, 0, FALSE);
758 PAGER_Scroll(HWND hwnd, INT dir)
760 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
761 NMPGSCROLL nmpgScroll;
764 if (infoPtr->hwndChild)
766 ZeroMemory (&nmpgScroll, sizeof (NMPGSCROLL));
767 nmpgScroll.hdr.hwndFrom = hwnd;
768 nmpgScroll.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
769 nmpgScroll.hdr.code = PGN_SCROLL;
771 GetWindowRect(hwnd, &rcWnd);
772 GetClientRect(hwnd, &nmpgScroll.rcParent);
773 nmpgScroll.iXpos = nmpgScroll.iYpos = 0;
774 nmpgScroll.iDir = dir;
776 if (PAGER_IsHorizontal(hwnd))
778 nmpgScroll.iScroll = rcWnd.right - rcWnd.left;
779 nmpgScroll.iXpos = infoPtr->nPos;
783 nmpgScroll.iScroll = rcWnd.bottom - rcWnd.top;
784 nmpgScroll.iYpos = infoPtr->nPos;
786 nmpgScroll.iScroll -= 2*infoPtr->nButtonSize;
788 SendMessageA (GetParent(hwnd), WM_NOTIFY,
789 (WPARAM)nmpgScroll.hdr.idFrom, (LPARAM)&nmpgScroll);
791 TRACE("[%08x] PGN_SCROLL returns iScroll=%d\n", hwnd, nmpgScroll.iScroll);
793 if (nmpgScroll.iScroll > 0)
795 infoPtr->direction = dir;
797 if (dir == PGF_SCROLLLEFT || dir == PGF_SCROLLUP)
798 PAGER_SetPos(hwnd, infoPtr->nPos - nmpgScroll.iScroll, TRUE);
800 PAGER_SetPos(hwnd, infoPtr->nPos + nmpgScroll.iScroll, TRUE);
803 infoPtr->direction = -1;
808 PAGER_FmtLines(HWND hwnd)
810 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
812 /* initiate NCCalcSize to resize client wnd and get size */
813 SetWindowPos(hwnd, 0, 0,0,0,0,
814 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
815 SWP_NOZORDER | SWP_NOACTIVATE);
817 SetWindowPos(infoPtr->hwndChild, 0,
818 0,0,infoPtr->nWidth,infoPtr->nHeight,
821 return DefWindowProcA (hwnd, EM_FMTLINES, 0, 0);
825 PAGER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
828 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
830 /* allocate memory for info structure */
831 infoPtr = (PAGER_INFO *)COMCTL32_Alloc (sizeof(PAGER_INFO));
832 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
834 /* set default settings */
835 infoPtr->hwndChild = (HWND)NULL;
836 infoPtr->bNoResize = dwStyle & CCS_NORESIZE;
837 infoPtr->clrBk = GetSysColor(COLOR_BTNFACE);
838 infoPtr->nBorder = 0;
839 infoPtr->nButtonSize = 12;
842 infoPtr->nHeight = 0;
843 infoPtr->bForward = FALSE;
844 infoPtr->bCapture = FALSE;
845 infoPtr->TLbtnState = PGF_INVISIBLE;
846 infoPtr->BRbtnState = PGF_INVISIBLE;
847 infoPtr->direction = -1;
849 if (dwStyle & PGS_DRAGNDROP)
850 FIXME("[%08x] Drag and Drop style is not implemented yet.\n", hwnd);
852 * If neither horizontal nor vertical style specified, default to vertical.
853 * This is probably not necessary, since the style may be set later on as
854 * the control is initialized, but just in case it isn't, set it here.
856 if (!(dwStyle & PGS_HORZ) && !(dwStyle & PGS_VERT))
859 SetWindowLongA(hwnd, GWL_STYLE, dwStyle);
867 PAGER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
869 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
870 /* free pager info data */
871 COMCTL32_Free (infoPtr);
872 SetWindowLongA (hwnd, 0, 0);
877 PAGER_NCCalcSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
879 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
880 LPRECT lpRect = (LPRECT)lParam;
881 RECT rcChildw, rcmyw, wnrc, ltrc, rbrc;
883 BOOL resizeClient = FALSE;
884 BOOL repaintBtns = FALSE;
888 * lParam points to a RECT struct. On entry, the struct
889 * contains the proposed wnd rectangle for the window.
890 * On exit, the struct should contain the screen
891 * coordinates of the corresponding window's client area.
894 DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
896 TRACE("orig rect=(%d,%d)-(%d,%d)\n",
897 lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
899 if (PAGER_IsHorizontal(hwnd))
901 infoPtr->nWidth = lpRect->right - lpRect->left;
902 PAGER_CalcSize (hwnd, &infoPtr->nWidth, TRUE);
903 GetWindowRect (infoPtr->hwndChild, &rcChildw);
904 MapWindowPoints (0, hwnd, (LPPOINT)&rcChildw, 2);
905 GetCursorPos (&cursor);
906 GetWindowRect (hwnd, &rcmyw);
908 /* Reset buttons and hide any grey ones */
909 scrollRange = infoPtr->nWidth - (rcmyw.right - rcmyw.left);
911 TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%d,%d)-(%d,%d), cursor=(%ld,%ld)\n",
912 infoPtr->nPos, scrollRange, infoPtr->nHeight,
913 rcmyw.left, rcmyw.top,
914 rcmyw.right, rcmyw.bottom,
916 PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
917 PAGER_HideGrayBtns(infoPtr, &resizeClient);
919 if (PtInRect (&rcmyw, cursor)) {
920 GetWindowRect (hwnd, &wnrc);
922 ltrc.right = ltrc.left + infoPtr->nButtonSize;
924 rbrc.left = rbrc.right - infoPtr->nButtonSize;
925 TRACE("horz lt rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
926 ltrc.left, ltrc.top, ltrc.right, ltrc.bottom,
927 rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
928 if (PtInRect (<rc, cursor) && infoPtr->TLbtnState)
929 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
930 if (PtInRect (&rbrc, cursor) && infoPtr->BRbtnState)
931 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
933 if (infoPtr->TLbtnState && (lpRect->left + infoPtr->nButtonSize < lpRect->right))
934 lpRect->left += infoPtr->nButtonSize;
935 if (infoPtr->BRbtnState && (lpRect->right - infoPtr->nButtonSize > lpRect->left))
936 lpRect->right -= infoPtr->nButtonSize;
940 /* native does: (from trace of IE4 opening "Favorites" frame)
942 * WM_NOITFY PGN_CALCSIZE w/ dwFlag=2
943 * GetWindowRect (child, &rc)
944 * MapWindowPoints (0, syspager, &rc, 2)
945 * GetCursorPos( &cur )
946 * GetWindowRect (syspager, &rc2)
947 * PtInRect (&rc2, cur.x, cur.y) rtns 0
948 * returns with rect empty
950 infoPtr->nHeight = lpRect->bottom - lpRect->top;
951 PAGER_CalcSize (hwnd, &infoPtr->nHeight, FALSE);
952 GetWindowRect (infoPtr->hwndChild, &rcChildw);
953 MapWindowPoints (0, hwnd, (LPPOINT)&rcChildw, 2);
954 GetCursorPos (&cursor);
955 GetWindowRect (hwnd, &rcmyw);
957 /* Reset buttons and hide any grey ones */
958 scrollRange = infoPtr->nHeight - (rcmyw.bottom - rcmyw.top);
960 TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%d,%d)-(%d,%d), cursor=(%ld,%ld)\n",
961 infoPtr->nPos, scrollRange, infoPtr->nHeight,
962 rcmyw.left, rcmyw.top,
963 rcmyw.right, rcmyw.bottom,
965 PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
966 PAGER_HideGrayBtns(infoPtr, &resizeClient);
968 if (PtInRect (&rcmyw, cursor)) {
971 * GetWindowRect(pager, &rc)
972 * PtInRect(btn-left????, cur.x, cur.y)
974 * PtInRect(btn-right????, cur.x, cur.y)
976 * RedrawWindow(pager, 0, 0, 5)
980 GetWindowRect (hwnd, &wnrc);
982 ltrc.right = ltrc.left + infoPtr->nButtonSize;
984 rbrc.left = rbrc.right - infoPtr->nButtonSize;
985 TRACE("vert lt rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
986 ltrc.left, ltrc.top, ltrc.right, ltrc.bottom,
987 rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
988 if (PtInRect (<rc, cursor) && infoPtr->TLbtnState)
989 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
990 if (PtInRect (&rbrc, cursor) && infoPtr->BRbtnState)
991 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
993 if (infoPtr->TLbtnState && (lpRect->top + infoPtr->nButtonSize < lpRect->bottom))
994 lpRect->top += infoPtr->nButtonSize;
995 if (infoPtr->BRbtnState && (lpRect->bottom - infoPtr->nButtonSize > lpRect->top))
996 lpRect->bottom -= infoPtr->nButtonSize;
998 if ((lpRect->bottom < 0) || (lpRect->bottom > infoPtr->nHeight))
999 lpRect->bottom = infoPtr->nHeight;
1002 TRACE("[%08x] client rect set to %dx%d at (%d,%d) BtnState[%d,%d]\n",
1003 hwnd, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top,
1004 lpRect->left, lpRect->top,
1005 infoPtr->TLbtnState, infoPtr->BRbtnState);
1011 PAGER_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
1013 PAGER_INFO* infoPtr = PAGER_GetInfoPtr(hwnd);
1014 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1015 RECT rcWindow, rcBottomRight, rcTopLeft;
1017 BOOL bHorizontal = PAGER_IsHorizontal(hwnd);
1019 if (dwStyle & WS_MINIMIZE)
1022 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
1024 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
1027 GetWindowRect (hwnd, &rcWindow);
1028 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
1030 rcTopLeft = rcBottomRight = rcWindow;
1033 rcTopLeft.right = rcTopLeft.left + infoPtr->nButtonSize;
1034 rcBottomRight.left = rcBottomRight.right - infoPtr->nButtonSize;
1038 rcTopLeft.bottom = rcTopLeft.top + infoPtr->nButtonSize;
1039 rcBottomRight.top = rcBottomRight.bottom - infoPtr->nButtonSize;
1042 PAGER_DrawButton(hdc, infoPtr->clrBk, rcTopLeft,
1043 bHorizontal, TRUE, infoPtr->TLbtnState);
1044 PAGER_DrawButton(hdc, infoPtr->clrBk, rcBottomRight,
1045 bHorizontal, FALSE, infoPtr->BRbtnState);
1047 ReleaseDC( hwnd, hdc );
1052 PAGER_HitTest (HWND hwnd, LPPOINT pt)
1054 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1056 BOOL bHorizontal = PAGER_IsHorizontal(hwnd);
1058 GetClientRect (hwnd, &clientRect);
1060 if (PtInRect(&clientRect, *pt))
1062 TRACE("HTCLIENT\n");
1066 if (infoPtr->TLbtnState && infoPtr->TLbtnState != PGF_GRAYED)
1070 if (pt->x < clientRect.left)
1078 if (pt->y < clientRect.top)
1086 if (infoPtr->BRbtnState && infoPtr->BRbtnState != PGF_GRAYED)
1090 if (pt->x > clientRect.right)
1098 if (pt->y > clientRect.bottom)
1100 TRACE("HTBOTTOM\n");
1106 TRACE("HTNOWHERE\n");
1111 PAGER_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1113 POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
1114 ScreenToClient (hwnd, &pt);
1115 return PAGER_HitTest(hwnd, &pt);
1119 PAGER_SetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1121 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1122 BOOL notCaptured = FALSE;
1124 switch(LOWORD(lParam))
1128 if ((notCaptured = infoPtr->TLbtnState != PGF_HOT))
1129 infoPtr->TLbtnState = PGF_HOT;
1133 if ((notCaptured = infoPtr->BRbtnState != PGF_HOT))
1134 infoPtr->BRbtnState = PGF_HOT;
1142 PAGER_CaptureandTrack(infoPtr, hwnd);
1144 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
1151 PAGER_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
1153 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1155 KillTimer (hwnd, TIMERID1);
1156 KillTimer (hwnd, TIMERID2);
1158 TRACE("[%08x] ReleaseCapture\n", hwnd);
1160 infoPtr->bCapture = FALSE;
1162 /* Notify parent of released mouse capture */
1165 ZeroMemory (&nmhdr, sizeof (NMHDR));
1166 nmhdr.hwndFrom = hwnd;
1167 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1168 nmhdr.code = NM_RELEASEDCAPTURE;
1169 SendMessageA (GetParent(hwnd), WM_NOTIFY,
1170 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1173 /* make HOT btns NORMAL and hide gray btns */
1174 PAGER_UpdateBtns(hwnd, infoPtr, -1, TRUE);
1180 PAGER_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
1182 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1183 POINT clpt, pt = {SLOWORD(lParam), SHIWORD(lParam)};
1184 RECT wnrect, TLbtnrect, BRbtnrect, *btnrect = NULL;
1185 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1186 BOOL topLeft = FALSE;
1191 TRACE("[%08x] to (%ld,%ld)\n", hwnd, pt.x, pt.y);
1192 ClientToScreen(hwnd, &pt);
1193 GetWindowRect(hwnd, &wnrect);
1194 if (PtInRect(&wnrect, pt)) {
1197 if (dwStyle & PGS_HORZ) {
1198 TLbtnrect.right = TLbtnrect.left + infoPtr->nButtonSize;
1199 BRbtnrect.left = BRbtnrect.right - infoPtr->nButtonSize;
1202 TLbtnrect.bottom = TLbtnrect.top + infoPtr->nButtonSize;
1203 BRbtnrect.top = BRbtnrect.bottom - infoPtr->nButtonSize;
1207 MapWindowPoints(0, hwnd, &clpt, 1);
1208 hit = PAGER_HitTest(hwnd, &clpt);
1209 if (hit == HTLEFT || hit == HTTOP) {
1211 btnrect = &TLbtnrect;
1212 infoPtr->TLbtnState = PGF_DEPRESSED;
1213 btnstate = infoPtr->TLbtnState;
1215 else if (hit == HTRIGHT || hit == HTBOTTOM) {
1217 btnrect = &BRbtnrect;
1218 infoPtr->BRbtnState = PGF_DEPRESSED;
1219 btnstate = infoPtr->BRbtnState;
1222 /* If in one of the buttons the capture and draw buttons */
1224 TRACE("[%08x] draw btn (%d,%d)-(%d,%d), Capture %s, style %08lx\n",
1225 hwnd, btnrect->left, btnrect->top,
1226 btnrect->right, btnrect->bottom,
1227 (infoPtr->bCapture) ? "TRUE" : "FALSE",
1229 if (!infoPtr->bCapture)
1230 PAGER_CaptureandTrack(infoPtr, hwnd);
1231 if (dwStyle & PGS_AUTOSCROLL)
1232 SetTimer(hwnd, TIMERID1, 0x3e, 0);
1233 MapWindowPoints(0, hwnd, (LPPOINT)btnrect, 2);
1234 hdc = GetWindowDC(hwnd);
1235 /* OffsetRect(wnrect, 0 | 1, 0 | 1) */
1236 PAGER_DrawButton(hdc, infoPtr->clrBk, *btnrect,
1237 PAGER_IsHorizontal(hwnd), topLeft, btnstate);
1238 ReleaseDC(hwnd, hdc);
1239 return DefWindowProcA (hwnd, WM_MOUSEMOVE, wParam, lParam);
1243 /* If we think we are captured, then do release */
1244 if (infoPtr->bCapture) {
1245 infoPtr->bCapture = FALSE;
1247 if (GetCapture() == hwnd) {
1249 /* Notify parent of released mouse capture */
1252 ZeroMemory (&nmhdr, sizeof (NMHDR));
1253 nmhdr.hwndFrom = hwnd;
1254 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1255 nmhdr.code = NM_RELEASEDCAPTURE;
1256 SendMessageA (GetParent(hwnd), WM_NOTIFY,
1257 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1261 KillTimer(hwnd, TIMERID1);
1263 return DefWindowProcA (hwnd, WM_MOUSEMOVE, wParam, lParam);
1267 PAGER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1269 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1270 BOOL repaintBtns = FALSE;
1271 POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
1274 TRACE("[%08x] at (%d,%d)\n", hwnd, SLOWORD(lParam), SHIWORD(lParam));
1276 hit = PAGER_HitTest(hwnd, &pt);
1278 /* put btn in DEPRESSED state */
1279 if (hit == HTLEFT || hit == HTTOP)
1281 repaintBtns = infoPtr->TLbtnState != PGF_DEPRESSED;
1282 infoPtr->TLbtnState = PGF_DEPRESSED;
1283 SetTimer(hwnd, TIMERID1, INITIAL_DELAY, 0);
1285 else if (hit == HTRIGHT || hit == HTBOTTOM)
1287 repaintBtns = infoPtr->BRbtnState != PGF_DEPRESSED;
1288 infoPtr->BRbtnState = PGF_DEPRESSED;
1289 SetTimer(hwnd, TIMERID1, INITIAL_DELAY, 0);
1293 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
1298 TRACE("[%08x] PGF_SCROLLLEFT\n", hwnd);
1299 PAGER_Scroll(hwnd, PGF_SCROLLLEFT);
1302 TRACE("[%08x] PGF_SCROLLUP\n", hwnd);
1303 PAGER_Scroll(hwnd, PGF_SCROLLUP);
1306 TRACE("[%08x] PGF_SCROLLRIGHT\n", hwnd);
1307 PAGER_Scroll(hwnd, PGF_SCROLLRIGHT);
1310 TRACE("[%08x] PGF_SCROLLDOWN\n", hwnd);
1311 PAGER_Scroll(hwnd, PGF_SCROLLDOWN);
1321 PAGER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1323 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1324 TRACE("[%08x]\n", hwnd);
1326 KillTimer (hwnd, TIMERID1);
1327 KillTimer (hwnd, TIMERID2);
1329 /* make PRESSED btns NORMAL but don't hide gray btns */
1330 PAGER_UpdateBtns(hwnd, infoPtr, -1, FALSE);
1336 PAGER_NCLButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1338 POINT pt = {SLOWORD(lParam), SHIWORD(lParam)};
1340 TRACE("[%08x] at (%d,%d)\n", hwnd, SLOWORD(lParam), SHIWORD(lParam));
1341 MapWindowPoints(0, hwnd, &pt, 1);
1342 lParam = MAKELONG(pt.x, pt.y);
1343 return PAGER_LButtonDown (hwnd, wParam, lParam);
1347 PAGER_Timer (HWND hwnd, WPARAM wParam)
1349 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1350 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1353 /* if initial timer, kill it and start the repeat timer */
1354 if (wParam == TIMERID1) {
1355 if (PAGER_IsHorizontal(hwnd)) {
1356 dir = (infoPtr->TLbtnState & PGF_DEPRESSED) ?
1357 PGF_SCROLLLEFT : PGF_SCROLLRIGHT;
1360 dir = (infoPtr->TLbtnState & PGF_DEPRESSED) ?
1361 PGF_SCROLLUP : PGF_SCROLLDOWN;
1363 TRACE("[%08x] TIMERID1: style=%08lx, dir=%d\n", hwnd, dwStyle, dir);
1364 KillTimer(hwnd, TIMERID1);
1365 SetTimer(hwnd, TIMERID1, REPEAT_DELAY, 0);
1366 if (dwStyle & PGS_AUTOSCROLL) {
1367 PAGER_Scroll(hwnd, dir);
1368 SetWindowPos(hwnd, 0,0,0,0,0,
1369 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1370 SWP_NOZORDER | SWP_NOACTIVATE);
1376 TRACE("[%08x] TIMERID2: dir=%d\n", hwnd, infoPtr->direction);
1377 KillTimer(hwnd, TIMERID2);
1378 if (infoPtr->direction > 0) {
1379 PAGER_Scroll(hwnd, infoPtr->direction);
1380 SetTimer(hwnd, TIMERID2, REPEAT_DELAY, 0);
1386 PAGER_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
1389 HDC hdc = (HDC)wParam;
1393 * parent = GetParent(pager)
1394 * pt.x=0; pt.y=0; ?????
1395 * MapWindowPoints(pager, parent, &pt, 1)
1396 * OffsetWindowOrgEx(hdc, pt.x, pt.y, &ptorg)
1397 * SendMessageA(parent, WM_ERASEBKGND, hdc, 0)
1398 * SetWindowOrgEx(hdc, 0, 0, 0)
1403 parent = GetParent(hwnd);
1404 MapWindowPoints(hwnd, parent, &pt, 1);
1405 OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig);
1406 SendMessageA (parent, WM_ERASEBKGND, wParam, lParam);
1407 SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0);
1411 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1412 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
1415 GetClientRect (hwnd, &rect);
1416 FillRect ((HDC)wParam, &rect, hBrush);
1418 /* background color of the child should be the same as the pager */
1419 if (infoPtr->hwndChild)
1421 GetClientRect (infoPtr->hwndChild, &rect);
1422 FillRect ((HDC)wParam, &rect, hBrush);
1425 DeleteObject (hBrush);
1433 PAGER_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
1435 /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
1437 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1438 TRACE("[%08x] %dx%d\n", hwnd, SLOWORD(lParam), SHIWORD(lParam));
1440 if (PAGER_IsHorizontal(hwnd))
1441 infoPtr->nHeight = SHIWORD(lParam);
1443 infoPtr->nWidth = SLOWORD(lParam);
1445 return PAGER_RecalcSize(hwnd);
1449 static LRESULT WINAPI
1450 PAGER_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1452 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1454 if (!infoPtr && (uMsg != WM_CREATE))
1455 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1460 return PAGER_FmtLines(hwnd);
1462 case PGM_FORWARDMOUSE:
1463 return PAGER_ForwardMouse (hwnd, wParam);
1465 case PGM_GETBKCOLOR:
1466 return PAGER_GetBkColor(hwnd);
1469 return PAGER_GetBorder(hwnd);
1471 case PGM_GETBUTTONSIZE:
1472 return PAGER_GetButtonSize(hwnd);
1475 return PAGER_GetPos(hwnd);
1477 case PGM_GETBUTTONSTATE:
1478 return PAGER_GetButtonState (hwnd, wParam, lParam);
1480 /* case PGM_GETDROPTARGET: */
1482 case PGM_RECALCSIZE:
1483 return PAGER_RecalcSize(hwnd);
1485 case PGM_SETBKCOLOR:
1486 return PAGER_SetBkColor (hwnd, wParam, lParam);
1489 return PAGER_SetBorder (hwnd, wParam, lParam);
1491 case PGM_SETBUTTONSIZE:
1492 return PAGER_SetButtonSize (hwnd, wParam, lParam);
1495 return PAGER_SetChild (hwnd, wParam, lParam);
1498 return PAGER_SetPos(hwnd, (INT)lParam, FALSE);
1501 return PAGER_Create (hwnd, wParam, lParam);
1504 return PAGER_Destroy (hwnd, wParam, lParam);
1507 return PAGER_Size (hwnd, wParam, lParam);
1510 return PAGER_NCPaint (hwnd, wParam, lParam);
1512 case WM_WINDOWPOSCHANGING:
1513 return PAGER_HandleWindowPosChanging (hwnd, wParam, (WINDOWPOS*)lParam);
1516 return PAGER_NCCalcSize (hwnd, wParam, lParam);
1519 return PAGER_NCHitTest (hwnd, wParam, lParam);
1523 if (hwnd == (HWND)wParam)
1524 return PAGER_SetCursor(hwnd, wParam, lParam);
1525 else /* its for the child */
1530 if (infoPtr->bForward && infoPtr->hwndChild)
1531 PostMessageA(infoPtr->hwndChild, WM_MOUSEMOVE, wParam, lParam);
1532 return PAGER_MouseMove (hwnd, wParam, lParam);
1535 return PAGER_MouseLeave (hwnd, wParam, lParam);
1537 case WM_NCLBUTTONDOWN:
1538 return PAGER_NCLButtonDown (hwnd, wParam, lParam);
1540 case WM_LBUTTONDOWN:
1541 return PAGER_LButtonDown (hwnd, wParam, lParam);
1543 case WM_NCLBUTTONUP:
1545 return PAGER_LButtonUp (hwnd, wParam, lParam);
1548 return PAGER_EraseBackground (hwnd, wParam, lParam);
1551 return PAGER_Paint (hwnd, wParam);
1554 return PAGER_Timer (hwnd, wParam);
1558 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
1561 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1569 PAGER_Register (void)
1573 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1574 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
1575 wndClass.lpfnWndProc = (WNDPROC)PAGER_WindowProc;
1576 wndClass.cbClsExtra = 0;
1577 wndClass.cbWndExtra = sizeof(PAGER_INFO *);
1578 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1579 wndClass.hbrBackground = 0;
1580 wndClass.lpszClassName = WC_PAGESCROLLERA;
1582 RegisterClassA (&wndClass);
1587 PAGER_Unregister (void)
1589 UnregisterClassA (WC_PAGESCROLLERA, (HINSTANCE)NULL);