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.
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(pager
);
46 HWND hwndChild
; /* handle of the contained wnd */
47 HWND hwndNotify
; /* handle of the parent wnd */
48 BOOL bNoResize
; /* set when created with CCS_NORESIZE */
49 COLORREF clrBk
; /* background color */
50 INT nBorder
; /* border size for the control */
51 INT nButtonSize
;/* size of the pager btns */
52 INT nPos
; /* scroll position */
53 INT nWidth
; /* from child wnd's response to PGN_CALCSIZE */
54 INT nHeight
; /* from child wnd's response to PGN_CALCSIZE */
55 BOOL bForward
; /* forward WM_MOUSEMOVE msgs to the contained wnd */
56 BOOL bCapture
; /* we have captured the mouse */
57 INT TLbtnState
; /* state of top or left btn */
58 INT BRbtnState
; /* state of bottom or right btn */
59 INT direction
; /* direction of the scroll, (e.g. PGF_SCROLLUP) */
62 #define PAGER_GetInfoPtr(hwnd) ((PAGER_INFO *)GetWindowLongA(hwnd, 0))
63 #define PAGER_IsHorizontal(hwnd) ((GetWindowLongA (hwnd, GWL_STYLE) & PGS_HORZ))
65 #define MIN_ARROW_WIDTH 8
66 #define MIN_ARROW_HEIGHT 5
70 #define INITIAL_DELAY 500
71 #define REPEAT_DELAY 50
73 /* the horizontal arrows are:
86 PAGER_DrawHorzArrow (HDC hdc
, RECT r
, INT colorRef
, BOOL left
)
91 w
= r
.right
- r
.left
+ 1;
92 h
= r
.bottom
- r
.top
+ 1;
93 if ((h
< MIN_ARROW_WIDTH
) || (w
< MIN_ARROW_HEIGHT
))
94 return; /* refuse to draw partial arrow */
96 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
97 hOldPen
= SelectObject ( hdc
, hPen
);
100 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 3;
101 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
102 MoveToEx (hdc
, x
, y
, NULL
);
103 LineTo (hdc
, x
--, y
+5); y
++;
104 MoveToEx (hdc
, x
, y
, NULL
);
105 LineTo (hdc
, x
--, y
+3); y
++;
106 MoveToEx (hdc
, x
, y
, NULL
);
107 LineTo (hdc
, x
, y
+1);
111 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
112 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
113 MoveToEx (hdc
, x
, y
, NULL
);
114 LineTo (hdc
, x
++, y
+5); y
++;
115 MoveToEx (hdc
, x
, y
, NULL
);
116 LineTo (hdc
, x
++, y
+3); y
++;
117 MoveToEx (hdc
, x
, y
, NULL
);
118 LineTo (hdc
, x
, y
+1);
121 SelectObject( hdc
, hOldPen
);
122 DeleteObject( hPen
);
125 /* the vertical arrows are:
135 PAGER_DrawVertArrow (HDC hdc
, RECT r
, INT colorRef
, BOOL up
)
140 w
= r
.right
- r
.left
+ 1;
141 h
= r
.bottom
- r
.top
+ 1;
142 if ((h
< MIN_ARROW_WIDTH
) || (w
< MIN_ARROW_HEIGHT
))
143 return; /* refuse to draw partial arrow */
145 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
146 hOldPen
= SelectObject ( hdc
, hPen
);
149 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
150 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 3;
151 MoveToEx (hdc
, x
, y
, NULL
);
152 LineTo (hdc
, x
+5, y
--); x
++;
153 MoveToEx (hdc
, x
, y
, NULL
);
154 LineTo (hdc
, x
+3, y
--); x
++;
155 MoveToEx (hdc
, x
, y
, NULL
);
156 LineTo (hdc
, x
+1, y
);
160 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
161 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
162 MoveToEx (hdc
, x
, y
, NULL
);
163 LineTo (hdc
, x
+5, y
++); x
++;
164 MoveToEx (hdc
, x
, y
, NULL
);
165 LineTo (hdc
, x
+3, y
++); x
++;
166 MoveToEx (hdc
, x
, y
, NULL
);
167 LineTo (hdc
, x
+1, y
);
170 SelectObject( hdc
, hOldPen
);
171 DeleteObject( hPen
);
175 PAGER_DrawButton(HDC hdc
, COLORREF clrBk
, RECT arrowRect
,
176 BOOL horz
, BOOL topLeft
, INT btnState
)
178 HBRUSH hBrush
, hOldBrush
;
181 if (!btnState
) /* PGF_INVISIBLE */
184 if ((rc
.right
- rc
.left
<= 0) || (rc
.bottom
- rc
.top
<= 0))
187 hBrush
= CreateSolidBrush(clrBk
);
188 hOldBrush
= (HBRUSH
)SelectObject(hdc
, hBrush
);
190 FillRect(hdc
, &rc
, hBrush
);
192 if (btnState
== PGF_HOT
)
194 DrawEdge( hdc
, &rc
, BDR_RAISEDINNER
, BF_RECT
);
196 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
198 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
200 else if (btnState
== PGF_NORMAL
)
202 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
204 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
206 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
208 else if (btnState
== PGF_DEPRESSED
)
210 DrawEdge( hdc
, &rc
, BDR_SUNKENOUTER
, BF_RECT
);
212 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
214 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
216 else if (btnState
== PGF_GRAYED
)
218 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
221 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
222 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
223 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
227 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
228 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
229 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
233 SelectObject( hdc
, hOldBrush
);
234 DeleteObject(hBrush
);
237 static void PAGER_CaptureandTrack(PAGER_INFO
*infoPtr
, HWND hwnd
)
239 TRACKMOUSEEVENT trackinfo
;
241 TRACE("[%p] SetCapture\n", hwnd
);
243 infoPtr
->bCapture
= TRUE
;
245 trackinfo
.cbSize
= sizeof(TRACKMOUSEEVENT
);
246 trackinfo
.dwFlags
= TME_QUERY
;
247 trackinfo
.hwndTrack
= hwnd
;
248 trackinfo
.dwHoverTime
= HOVER_DEFAULT
;
250 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
251 _TrackMouseEvent(&trackinfo
);
253 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
254 if(!(trackinfo
.dwFlags
& TME_LEAVE
)) {
255 trackinfo
.dwFlags
= TME_LEAVE
; /* notify upon leaving */
257 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
258 /* and can properly deactivate the hot button */
259 _TrackMouseEvent(&trackinfo
);
264 /* << PAGER_GetDropTarget >> */
266 static inline LRESULT
267 PAGER_ForwardMouse (HWND hwnd
, WPARAM wParam
)
269 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
270 TRACE("[%p]\n", hwnd
);
272 infoPtr
->bForward
= (BOOL
)wParam
;
277 static inline LRESULT
278 PAGER_GetButtonState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
280 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
281 LRESULT btnState
= PGF_INVISIBLE
;
282 INT btn
= (INT
)lParam
;
283 TRACE("[%p]\n", hwnd
);
285 if (btn
== PGB_TOPORLEFT
)
286 btnState
= infoPtr
->TLbtnState
;
287 else if (btn
== PGB_BOTTOMORRIGHT
)
288 btnState
= infoPtr
->BRbtnState
;
294 static inline LRESULT
295 PAGER_GetPos(HWND hwnd
)
297 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
298 TRACE("[%p] returns %d\n", hwnd
, infoPtr
->nPos
);
299 return (LRESULT
)infoPtr
->nPos
;
302 static inline LRESULT
303 PAGER_GetButtonSize(HWND hwnd
)
305 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
306 TRACE("[%p] returns %d\n", hwnd
, infoPtr
->nButtonSize
);
307 return (LRESULT
)infoPtr
->nButtonSize
;
310 static inline LRESULT
311 PAGER_GetBorder(HWND hwnd
)
313 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
314 TRACE("[%p] returns %d\n", hwnd
, infoPtr
->nBorder
);
315 return (LRESULT
)infoPtr
->nBorder
;
318 static inline LRESULT
319 PAGER_GetBkColor(HWND hwnd
)
321 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
322 TRACE("[%p] returns %06lx\n", hwnd
, infoPtr
->clrBk
);
323 return (LRESULT
)infoPtr
->clrBk
;
327 PAGER_CalcSize (HWND hwnd
, INT
* size
, BOOL getWidth
)
329 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
331 ZeroMemory (&nmpgcs
, sizeof (NMPGCALCSIZE
));
332 nmpgcs
.hdr
.hwndFrom
= hwnd
;
333 nmpgcs
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
334 nmpgcs
.hdr
.code
= PGN_CALCSIZE
;
335 nmpgcs
.dwFlag
= getWidth
? PGF_CALCWIDTH
: PGF_CALCHEIGHT
;
336 nmpgcs
.iWidth
= getWidth
? *size
: 0;
337 nmpgcs
.iHeight
= getWidth
? 0 : *size
;
338 SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
339 (WPARAM
)nmpgcs
.hdr
.idFrom
, (LPARAM
)&nmpgcs
);
341 *size
= getWidth
? nmpgcs
.iWidth
: nmpgcs
.iHeight
;
343 TRACE("[%p] PGN_CALCSIZE returns %s=%d\n", hwnd
,
344 getWidth
? "width" : "height", *size
);
348 PAGER_PositionChildWnd(HWND hwnd
, PAGER_INFO
* infoPtr
)
350 if (infoPtr
->hwndChild
)
353 int nPos
= infoPtr
->nPos
;
355 /* compensate for a grayed btn, which will soon become invisible */
356 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
357 nPos
+= infoPtr
->nButtonSize
;
359 GetClientRect(hwnd
, &rcClient
);
361 if (PAGER_IsHorizontal(hwnd
))
363 int wndSize
= max(0, rcClient
.right
- rcClient
.left
);
364 if (infoPtr
->nWidth
< wndSize
)
365 infoPtr
->nWidth
= wndSize
;
367 TRACE("[%p] SWP %dx%d at (%d,%d)\n", hwnd
,
368 infoPtr
->nWidth
, infoPtr
->nHeight
,
370 SetWindowPos(infoPtr
->hwndChild
, 0,
372 infoPtr
->nWidth
, infoPtr
->nHeight
,
377 int wndSize
= max(0, rcClient
.bottom
- rcClient
.top
);
378 if (infoPtr
->nHeight
< wndSize
)
379 infoPtr
->nHeight
= wndSize
;
381 TRACE("[%p] SWP %dx%d at (%d,%d)\n", hwnd
,
382 infoPtr
->nWidth
, infoPtr
->nHeight
,
384 SetWindowPos(infoPtr
->hwndChild
, 0,
386 infoPtr
->nWidth
, infoPtr
->nHeight
,
390 InvalidateRect(infoPtr
->hwndChild
, NULL
, TRUE
);
395 PAGER_GetScrollRange(HWND hwnd
, PAGER_INFO
* infoPtr
)
399 if (infoPtr
->hwndChild
)
401 INT wndSize
, childSize
;
403 GetWindowRect(hwnd
, &wndRect
);
405 if (PAGER_IsHorizontal(hwnd
))
407 wndSize
= wndRect
.right
- wndRect
.left
;
408 PAGER_CalcSize(hwnd
, &infoPtr
->nWidth
, TRUE
);
409 childSize
= infoPtr
->nWidth
;
413 wndSize
= wndRect
.bottom
- wndRect
.top
;
414 PAGER_CalcSize(hwnd
, &infoPtr
->nHeight
, FALSE
);
415 childSize
= infoPtr
->nHeight
;
418 TRACE("childSize = %d, wndSize = %d\n", childSize
, wndSize
);
419 if (childSize
> wndSize
)
420 scrollRange
= childSize
- wndSize
+ infoPtr
->nButtonSize
;
423 TRACE("[%p] returns %d\n", hwnd
, scrollRange
);
428 PAGER_GrayAndRestoreBtns(PAGER_INFO
* infoPtr
, INT scrollRange
,
429 BOOL
* needsResize
, BOOL
* needsRepaint
)
431 if (infoPtr
->nPos
> 0)
433 *needsResize
|= !infoPtr
->TLbtnState
; /* PGF_INVISIBLE */
434 if (infoPtr
->TLbtnState
!= PGF_DEPRESSED
)
435 infoPtr
->TLbtnState
= PGF_NORMAL
;
439 *needsRepaint
|= (infoPtr
->TLbtnState
!= PGF_GRAYED
);
440 infoPtr
->TLbtnState
= PGF_GRAYED
;
443 if (scrollRange
<= 0)
445 *needsRepaint
|= (infoPtr
->TLbtnState
!= PGF_GRAYED
);
446 infoPtr
->TLbtnState
= PGF_GRAYED
;
447 *needsRepaint
|= (infoPtr
->BRbtnState
!= PGF_GRAYED
);
448 infoPtr
->BRbtnState
= PGF_GRAYED
;
450 else if (infoPtr
->nPos
< scrollRange
)
452 *needsResize
|= !infoPtr
->BRbtnState
; /* PGF_INVISIBLE */
453 if (infoPtr
->BRbtnState
!= PGF_DEPRESSED
)
454 infoPtr
->BRbtnState
= PGF_NORMAL
;
458 *needsRepaint
|= (infoPtr
->BRbtnState
!= PGF_GRAYED
);
459 infoPtr
->BRbtnState
= PGF_GRAYED
;
465 PAGER_NormalizeBtns(PAGER_INFO
* infoPtr
, BOOL
* needsRepaint
)
467 if (infoPtr
->TLbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
469 infoPtr
->TLbtnState
= PGF_NORMAL
;
470 *needsRepaint
= TRUE
;
473 if (infoPtr
->BRbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
475 infoPtr
->BRbtnState
= PGF_NORMAL
;
476 *needsRepaint
= TRUE
;
481 PAGER_HideGrayBtns(PAGER_INFO
* infoPtr
, BOOL
* needsResize
)
483 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
485 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
489 if (infoPtr
->BRbtnState
== PGF_GRAYED
)
491 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
497 PAGER_UpdateBtns(HWND hwnd
, PAGER_INFO
*infoPtr
,
498 INT scrollRange
, BOOL hideGrayBtns
)
500 BOOL resizeClient
= FALSE
;
501 BOOL repaintBtns
= FALSE
;
504 PAGER_NormalizeBtns(infoPtr
, &repaintBtns
);
506 PAGER_GrayAndRestoreBtns(infoPtr
, scrollRange
, &resizeClient
, &repaintBtns
);
509 PAGER_HideGrayBtns(infoPtr
, &resizeClient
);
511 if (resizeClient
) /* initiate NCCalcSize to resize client wnd */ {
512 SetWindowPos(hwnd
, 0,0,0,0,0,
513 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
514 SWP_NOZORDER
| SWP_NOACTIVATE
);
518 SendMessageA(hwnd
, WM_NCPAINT
, 0, 0);
522 PAGER_SetPos(HWND hwnd
, INT newPos
, BOOL fromBtnPress
)
524 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
525 INT scrollRange
= PAGER_GetScrollRange(hwnd
, infoPtr
);
526 INT oldPos
= infoPtr
->nPos
;
528 if ((scrollRange
<= 0) || (newPos
< 0))
530 else if (newPos
> scrollRange
)
531 infoPtr
->nPos
= scrollRange
;
533 infoPtr
->nPos
= newPos
;
535 TRACE("[%p] pos=%d, oldpos=%d\n", hwnd
, infoPtr
->nPos
, oldPos
);
537 if (infoPtr
->nPos
!= oldPos
)
539 /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
540 PAGER_UpdateBtns(hwnd
, infoPtr
, scrollRange
, !fromBtnPress
);
541 PAGER_PositionChildWnd(hwnd
, infoPtr
);
548 PAGER_HandleWindowPosChanging(HWND hwnd
, WPARAM wParam
, WINDOWPOS
*winpos
)
550 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
552 if (infoPtr
->bNoResize
&& !(winpos
->flags
& SWP_NOSIZE
))
554 /* don't let the app resize the nonscrollable dimension of a control
555 * that was created with CCS_NORESIZE style
556 * (i.e. height for a horizontal pager, or width for a vertical one) */
558 /* except if the current dimension is 0 and app is setting for
559 * first time, then save amount as dimension. - GA 8/01 */
561 if (PAGER_IsHorizontal(hwnd
))
562 if (!infoPtr
->nHeight
&& winpos
->cy
)
563 infoPtr
->nHeight
= winpos
->cy
;
565 winpos
->cy
= infoPtr
->nHeight
;
567 if (!infoPtr
->nWidth
&& winpos
->cx
)
568 infoPtr
->nWidth
= winpos
->cx
;
570 winpos
->cx
= infoPtr
->nWidth
;
574 DefWindowProcA (hwnd
, WM_WINDOWPOSCHANGING
, wParam
, (LPARAM
)winpos
);
580 PAGER_SetFixedWidth(HWND hwnd
, PAGER_INFO
* infoPtr
)
582 /* Must set the non-scrollable dimension to be less than the full height/width
583 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
584 * size, and experimentation shows that affect is almost right. */
588 GetWindowRect(hwnd
, &wndRect
);
590 /* see what the app says for btn width */
591 PAGER_CalcSize(hwnd
, &infoPtr
->nWidth
, TRUE
);
593 if (infoPtr
->bNoResize
)
595 delta
= wndRect
.right
- wndRect
.left
- infoPtr
->nWidth
;
596 if (delta
> infoPtr
->nButtonSize
)
597 infoPtr
->nWidth
+= 4 * infoPtr
->nButtonSize
/ 3;
599 infoPtr
->nWidth
+= infoPtr
->nButtonSize
/ 3;
602 h
= wndRect
.bottom
- wndRect
.top
+ infoPtr
->nButtonSize
;
604 TRACE("[%p] infoPtr->nWidth set to %d\n",
605 hwnd
, infoPtr
->nWidth
);
611 PAGER_SetFixedHeight(HWND hwnd
, PAGER_INFO
* infoPtr
)
613 /* Must set the non-scrollable dimension to be less than the full height/width
614 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
615 * size, and experimentation shows that affect is almost right. */
619 GetWindowRect(hwnd
, &wndRect
);
621 /* see what the app says for btn height */
622 PAGER_CalcSize(hwnd
, &infoPtr
->nHeight
, FALSE
);
624 if (infoPtr
->bNoResize
)
626 delta
= wndRect
.bottom
- wndRect
.top
- infoPtr
->nHeight
;
627 if (delta
> infoPtr
->nButtonSize
)
628 infoPtr
->nHeight
+= infoPtr
->nButtonSize
;
630 infoPtr
->nHeight
+= infoPtr
->nButtonSize
/ 3;
633 w
= wndRect
.right
- wndRect
.left
+ infoPtr
->nButtonSize
;
635 TRACE("[%p] infoPtr->nHeight set to %d\n",
636 hwnd
, infoPtr
->nHeight
);
641 /******************************************************************
642 * For the PGM_RECALCSIZE message (but not the other uses in *
643 * this module), the native control does only the following: *
645 * if (some condition) *
646 * PostMessageA(hwnd, EM_FMTLINES, 0, 0); *
647 * return DefWindowProcA(hwnd, PGM_RECALCSIZE, 0, 0); *
649 * When we figure out what the "some condition" is we will *
650 * implement that for the message processing. *
651 ******************************************************************/
654 PAGER_RecalcSize(HWND hwnd
)
656 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
658 TRACE("[%p]\n", hwnd
);
660 if (infoPtr
->hwndChild
)
662 INT scrollRange
= PAGER_GetScrollRange(hwnd
, infoPtr
);
664 if (scrollRange
<= 0)
667 PAGER_SetPos(hwnd
, 0, FALSE
);
671 PAGER_UpdateBtns(hwnd
, infoPtr
, scrollRange
, TRUE
);
672 PAGER_PositionChildWnd(hwnd
, infoPtr
);
681 PAGER_SetBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
683 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
684 COLORREF clrTemp
= infoPtr
->clrBk
;
686 infoPtr
->clrBk
= (COLORREF
)lParam
;
687 TRACE("[%p] %06lx\n", hwnd
, infoPtr
->clrBk
);
689 /* the native control seems to do things this way */
690 SetWindowPos(hwnd
, 0,0,0,0,0,
691 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
692 SWP_NOZORDER
| SWP_NOACTIVATE
);
694 RedrawWindow(hwnd
, 0, 0, RDW_ERASE
| RDW_INVALIDATE
);
696 return (LRESULT
)clrTemp
;
701 PAGER_SetBorder (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
703 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
704 INT nTemp
= infoPtr
->nBorder
;
706 infoPtr
->nBorder
= (INT
)lParam
;
707 TRACE("[%p] %d\n", hwnd
, infoPtr
->nBorder
);
709 PAGER_RecalcSize(hwnd
);
711 return (LRESULT
)nTemp
;
716 PAGER_SetButtonSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
718 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
719 INT nTemp
= infoPtr
->nButtonSize
;
721 infoPtr
->nButtonSize
= (INT
)lParam
;
722 TRACE("[%p] %d\n", hwnd
, infoPtr
->nButtonSize
);
724 PAGER_RecalcSize(hwnd
);
726 return (LRESULT
)nTemp
;
731 PAGER_SetChild (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
733 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
736 infoPtr
->hwndChild
= IsWindow ((HWND
)lParam
) ? (HWND
)lParam
: 0;
738 if (infoPtr
->hwndChild
)
740 TRACE("[%p] hwndChild=%p\n", hwnd
, infoPtr
->hwndChild
);
742 if (PAGER_IsHorizontal(hwnd
)) {
743 hw
= PAGER_SetFixedHeight(hwnd
, infoPtr
);
744 /* adjust non-scrollable dimension to fit the child */
745 SetWindowPos(hwnd
, 0, 0,0, hw
, infoPtr
->nHeight
,
746 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
747 SWP_NOSIZE
| SWP_NOACTIVATE
);
750 hw
= PAGER_SetFixedWidth(hwnd
, infoPtr
);
751 /* adjust non-scrollable dimension to fit the child */
752 SetWindowPos(hwnd
, 0, 0,0, infoPtr
->nWidth
, hw
,
753 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
754 SWP_NOSIZE
| SWP_NOACTIVATE
);
757 /* position child within the page scroller */
758 SetWindowPos(infoPtr
->hwndChild
, HWND_TOP
,
760 SWP_SHOWWINDOW
| SWP_NOSIZE
); /* native is 0 */
763 PAGER_SetPos(hwnd
, 0, FALSE
);
770 PAGER_Scroll(HWND hwnd
, INT dir
)
772 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
773 NMPGSCROLL nmpgScroll
;
776 if (infoPtr
->hwndChild
)
778 ZeroMemory (&nmpgScroll
, sizeof (NMPGSCROLL
));
779 nmpgScroll
.hdr
.hwndFrom
= hwnd
;
780 nmpgScroll
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
781 nmpgScroll
.hdr
.code
= PGN_SCROLL
;
783 GetWindowRect(hwnd
, &rcWnd
);
784 GetClientRect(hwnd
, &nmpgScroll
.rcParent
);
785 nmpgScroll
.iXpos
= nmpgScroll
.iYpos
= 0;
786 nmpgScroll
.iDir
= dir
;
788 if (PAGER_IsHorizontal(hwnd
))
790 nmpgScroll
.iScroll
= rcWnd
.right
- rcWnd
.left
;
791 nmpgScroll
.iXpos
= infoPtr
->nPos
;
795 nmpgScroll
.iScroll
= rcWnd
.bottom
- rcWnd
.top
;
796 nmpgScroll
.iYpos
= infoPtr
->nPos
;
798 nmpgScroll
.iScroll
-= 2*infoPtr
->nButtonSize
;
800 SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
801 (WPARAM
)nmpgScroll
.hdr
.idFrom
, (LPARAM
)&nmpgScroll
);
803 TRACE("[%p] PGN_SCROLL returns iScroll=%d\n", hwnd
, nmpgScroll
.iScroll
);
805 if (nmpgScroll
.iScroll
> 0)
807 infoPtr
->direction
= dir
;
809 if (dir
== PGF_SCROLLLEFT
|| dir
== PGF_SCROLLUP
)
810 PAGER_SetPos(hwnd
, infoPtr
->nPos
- nmpgScroll
.iScroll
, TRUE
);
812 PAGER_SetPos(hwnd
, infoPtr
->nPos
+ nmpgScroll
.iScroll
, TRUE
);
815 infoPtr
->direction
= -1;
820 PAGER_FmtLines(HWND hwnd
)
822 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
824 /* initiate NCCalcSize to resize client wnd and get size */
825 SetWindowPos(hwnd
, 0, 0,0,0,0,
826 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
827 SWP_NOZORDER
| SWP_NOACTIVATE
);
829 SetWindowPos(infoPtr
->hwndChild
, 0,
830 0,0,infoPtr
->nWidth
,infoPtr
->nHeight
,
833 return DefWindowProcA (hwnd
, EM_FMTLINES
, 0, 0);
837 PAGER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
840 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
842 /* allocate memory for info structure */
843 infoPtr
= (PAGER_INFO
*)Alloc (sizeof(PAGER_INFO
));
844 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
846 /* set default settings */
847 infoPtr
->hwndChild
= NULL
;
848 infoPtr
->hwndNotify
= ((LPCREATESTRUCTW
)lParam
)->hwndParent
;
849 infoPtr
->bNoResize
= dwStyle
& CCS_NORESIZE
;
850 infoPtr
->clrBk
= GetSysColor(COLOR_BTNFACE
);
851 infoPtr
->nBorder
= 0;
852 infoPtr
->nButtonSize
= 12;
855 infoPtr
->nHeight
= 0;
856 infoPtr
->bForward
= FALSE
;
857 infoPtr
->bCapture
= FALSE
;
858 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
859 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
860 infoPtr
->direction
= -1;
862 if (dwStyle
& PGS_DRAGNDROP
)
863 FIXME("[%p] Drag and Drop style is not implemented yet.\n", hwnd
);
865 * If neither horizontal nor vertical style specified, default to vertical.
866 * This is probably not necessary, since the style may be set later on as
867 * the control is initialized, but just in case it isn't, set it here.
869 if (!(dwStyle
& PGS_HORZ
) && !(dwStyle
& PGS_VERT
))
872 SetWindowLongA(hwnd
, GWL_STYLE
, dwStyle
);
880 PAGER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
882 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
883 /* free pager info data */
885 SetWindowLongA (hwnd
, 0, 0);
890 PAGER_NCCalcSize(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
892 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
893 LPRECT lpRect
= (LPRECT
)lParam
;
894 RECT rcChildw
, rcmyw
, wnrc
, ltrc
, rbrc
;
896 BOOL resizeClient
= FALSE
;
897 BOOL repaintBtns
= FALSE
;
901 * lParam points to a RECT struct. On entry, the struct
902 * contains the proposed wnd rectangle for the window.
903 * On exit, the struct should contain the screen
904 * coordinates of the corresponding window's client area.
907 DefWindowProcA (hwnd
, WM_NCCALCSIZE
, wParam
, lParam
);
909 TRACE("orig rect=(%ld,%ld)-(%ld,%ld)\n",
910 lpRect
->left
, lpRect
->top
, lpRect
->right
, lpRect
->bottom
);
912 if (PAGER_IsHorizontal(hwnd
))
914 infoPtr
->nWidth
= lpRect
->right
- lpRect
->left
;
915 PAGER_CalcSize (hwnd
, &infoPtr
->nWidth
, TRUE
);
916 GetWindowRect (infoPtr
->hwndChild
, &rcChildw
);
917 MapWindowPoints (0, hwnd
, (LPPOINT
)&rcChildw
, 2);
918 GetCursorPos (&cursor
);
919 GetWindowRect (hwnd
, &rcmyw
);
921 /* Reset buttons and hide any grey ones */
922 scrollRange
= infoPtr
->nWidth
- (rcmyw
.right
- rcmyw
.left
);
924 TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%ld,%ld)-(%ld,%ld), cursor=(%ld,%ld)\n",
925 infoPtr
->nPos
, scrollRange
, infoPtr
->nHeight
,
926 rcmyw
.left
, rcmyw
.top
,
927 rcmyw
.right
, rcmyw
.bottom
,
929 PAGER_GrayAndRestoreBtns(infoPtr
, scrollRange
, &resizeClient
, &repaintBtns
);
930 PAGER_HideGrayBtns(infoPtr
, &resizeClient
);
932 if (PtInRect (&rcmyw
, cursor
)) {
933 GetWindowRect (hwnd
, &wnrc
);
935 ltrc
.right
= ltrc
.left
+ infoPtr
->nButtonSize
;
937 rbrc
.left
= rbrc
.right
- infoPtr
->nButtonSize
;
938 TRACE("horz lt rect=(%ld,%ld)-(%ld,%ld), rb rect=(%ld,%ld)-(%ld,%ld)\n",
939 ltrc
.left
, ltrc
.top
, ltrc
.right
, ltrc
.bottom
,
940 rbrc
.left
, rbrc
.top
, rbrc
.right
, rbrc
.bottom
);
941 if (PtInRect (<rc
, cursor
) && infoPtr
->TLbtnState
)
942 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
943 if (PtInRect (&rbrc
, cursor
) && infoPtr
->BRbtnState
)
944 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
946 if (infoPtr
->TLbtnState
&& (lpRect
->left
+ infoPtr
->nButtonSize
< lpRect
->right
))
947 lpRect
->left
+= infoPtr
->nButtonSize
;
948 if (infoPtr
->BRbtnState
&& (lpRect
->right
- infoPtr
->nButtonSize
> lpRect
->left
))
949 lpRect
->right
-= infoPtr
->nButtonSize
;
953 /* native does: (from trace of IE4 opening "Favorites" frame)
955 * WM_NOITFY PGN_CALCSIZE w/ dwFlag=2
956 * GetWindowRect (child, &rc)
957 * MapWindowPoints (0, syspager, &rc, 2)
958 * GetCursorPos( &cur )
959 * GetWindowRect (syspager, &rc2)
960 * PtInRect (&rc2, cur.x, cur.y) rtns 0
961 * returns with rect empty
963 infoPtr
->nHeight
= lpRect
->bottom
- lpRect
->top
;
964 PAGER_CalcSize (hwnd
, &infoPtr
->nHeight
, FALSE
);
965 GetWindowRect (infoPtr
->hwndChild
, &rcChildw
);
966 MapWindowPoints (0, hwnd
, (LPPOINT
)&rcChildw
, 2);
967 GetCursorPos (&cursor
);
968 GetWindowRect (hwnd
, &rcmyw
);
970 /* Reset buttons and hide any grey ones */
971 scrollRange
= infoPtr
->nHeight
- (rcmyw
.bottom
- rcmyw
.top
);
973 TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%ld,%ld)-(%ld,%ld), cursor=(%ld,%ld)\n",
974 infoPtr
->nPos
, scrollRange
, infoPtr
->nHeight
,
975 rcmyw
.left
, rcmyw
.top
,
976 rcmyw
.right
, rcmyw
.bottom
,
978 PAGER_GrayAndRestoreBtns(infoPtr
, scrollRange
, &resizeClient
, &repaintBtns
);
979 PAGER_HideGrayBtns(infoPtr
, &resizeClient
);
981 if (PtInRect (&rcmyw
, cursor
)) {
984 * GetWindowRect(pager, &rc)
985 * PtInRect(btn-left????, cur.x, cur.y)
987 * PtInRect(btn-right????, cur.x, cur.y)
989 * RedrawWindow(pager, 0, 0, 5)
993 GetWindowRect (hwnd
, &wnrc
);
995 ltrc
.right
= ltrc
.left
+ infoPtr
->nButtonSize
;
997 rbrc
.left
= rbrc
.right
- infoPtr
->nButtonSize
;
998 TRACE("vert lt rect=(%ld,%ld)-(%ld,%ld), rb rect=(%ld,%ld)-(%ld,%ld)\n",
999 ltrc
.left
, ltrc
.top
, ltrc
.right
, ltrc
.bottom
,
1000 rbrc
.left
, rbrc
.top
, rbrc
.right
, rbrc
.bottom
);
1001 if (PtInRect (<rc
, cursor
) && infoPtr
->TLbtnState
)
1002 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
1003 if (PtInRect (&rbrc
, cursor
) && infoPtr
->BRbtnState
)
1004 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
1006 if (infoPtr
->TLbtnState
&& (lpRect
->top
+ infoPtr
->nButtonSize
< lpRect
->bottom
))
1007 lpRect
->top
+= infoPtr
->nButtonSize
;
1008 if (infoPtr
->BRbtnState
&& (lpRect
->bottom
- infoPtr
->nButtonSize
> lpRect
->top
))
1009 lpRect
->bottom
-= infoPtr
->nButtonSize
;
1012 TRACE("[%p] client rect set to %ldx%ld at (%ld,%ld) BtnState[%d,%d]\n",
1013 hwnd
, lpRect
->right
-lpRect
->left
, lpRect
->bottom
-lpRect
->top
,
1014 lpRect
->left
, lpRect
->top
,
1015 infoPtr
->TLbtnState
, infoPtr
->BRbtnState
);
1021 PAGER_NCPaint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1023 PAGER_INFO
* infoPtr
= PAGER_GetInfoPtr(hwnd
);
1024 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1025 RECT rcWindow
, rcBottomRight
, rcTopLeft
;
1027 BOOL bHorizontal
= PAGER_IsHorizontal(hwnd
);
1029 if (dwStyle
& WS_MINIMIZE
)
1032 DefWindowProcA (hwnd
, WM_NCPAINT
, wParam
, lParam
);
1034 if (!(hdc
= GetDCEx (hwnd
, 0, DCX_USESTYLE
| DCX_WINDOW
)))
1037 GetWindowRect (hwnd
, &rcWindow
);
1038 OffsetRect (&rcWindow
, -rcWindow
.left
, -rcWindow
.top
);
1040 rcTopLeft
= rcBottomRight
= rcWindow
;
1043 rcTopLeft
.right
= rcTopLeft
.left
+ infoPtr
->nButtonSize
;
1044 rcBottomRight
.left
= rcBottomRight
.right
- infoPtr
->nButtonSize
;
1048 rcTopLeft
.bottom
= rcTopLeft
.top
+ infoPtr
->nButtonSize
;
1049 rcBottomRight
.top
= rcBottomRight
.bottom
- infoPtr
->nButtonSize
;
1052 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcTopLeft
,
1053 bHorizontal
, TRUE
, infoPtr
->TLbtnState
);
1054 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcBottomRight
,
1055 bHorizontal
, FALSE
, infoPtr
->BRbtnState
);
1057 ReleaseDC( hwnd
, hdc
);
1062 PAGER_HitTest (HWND hwnd
, LPPOINT pt
)
1064 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1066 BOOL bHorizontal
= PAGER_IsHorizontal(hwnd
);
1068 GetClientRect (hwnd
, &clientRect
);
1070 if (PtInRect(&clientRect
, *pt
))
1072 TRACE("HTCLIENT\n");
1076 if (infoPtr
->TLbtnState
&& infoPtr
->TLbtnState
!= PGF_GRAYED
)
1080 if (pt
->x
< clientRect
.left
)
1088 if (pt
->y
< clientRect
.top
)
1096 if (infoPtr
->BRbtnState
&& infoPtr
->BRbtnState
!= PGF_GRAYED
)
1100 if (pt
->x
> clientRect
.right
)
1108 if (pt
->y
> clientRect
.bottom
)
1110 TRACE("HTBOTTOM\n");
1116 TRACE("HTNOWHERE\n");
1121 PAGER_NCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1125 pt
.x
= (short)LOWORD(lParam
);
1126 pt
.y
= (short)HIWORD(lParam
);
1128 ScreenToClient (hwnd
, &pt
);
1129 return PAGER_HitTest(hwnd
, &pt
);
1133 PAGER_SetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1135 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1136 BOOL notCaptured
= FALSE
;
1138 switch(LOWORD(lParam
))
1142 if ((notCaptured
= infoPtr
->TLbtnState
!= PGF_HOT
))
1143 infoPtr
->TLbtnState
= PGF_HOT
;
1147 if ((notCaptured
= infoPtr
->BRbtnState
!= PGF_HOT
))
1148 infoPtr
->BRbtnState
= PGF_HOT
;
1156 PAGER_CaptureandTrack(infoPtr
, hwnd
);
1158 SendMessageA(hwnd
, WM_NCPAINT
, 0, 0);
1165 PAGER_MouseLeave (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1167 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1169 KillTimer (hwnd
, TIMERID1
);
1170 KillTimer (hwnd
, TIMERID2
);
1172 TRACE("[%p] ReleaseCapture\n", hwnd
);
1174 infoPtr
->bCapture
= FALSE
;
1176 /* Notify parent of released mouse capture */
1179 ZeroMemory (&nmhdr
, sizeof (NMHDR
));
1180 nmhdr
.hwndFrom
= hwnd
;
1181 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
1182 nmhdr
.code
= NM_RELEASEDCAPTURE
;
1183 SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
1184 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1187 /* make HOT btns NORMAL and hide gray btns */
1188 PAGER_UpdateBtns(hwnd
, infoPtr
, -1, TRUE
);
1194 PAGER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1196 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1198 RECT wnrect
, TLbtnrect
, BRbtnrect
, *btnrect
= NULL
;
1199 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1200 BOOL topLeft
= FALSE
;
1205 pt
.x
= (short)LOWORD(lParam
);
1206 pt
.y
= (short)HIWORD(lParam
);
1208 TRACE("[%p] to (%ld,%ld)\n", hwnd
, pt
.x
, pt
.y
);
1209 ClientToScreen(hwnd
, &pt
);
1210 GetWindowRect(hwnd
, &wnrect
);
1211 if (PtInRect(&wnrect
, pt
)) {
1214 if (dwStyle
& PGS_HORZ
) {
1215 TLbtnrect
.right
= TLbtnrect
.left
+ infoPtr
->nButtonSize
;
1216 BRbtnrect
.left
= BRbtnrect
.right
- infoPtr
->nButtonSize
;
1219 TLbtnrect
.bottom
= TLbtnrect
.top
+ infoPtr
->nButtonSize
;
1220 BRbtnrect
.top
= BRbtnrect
.bottom
- infoPtr
->nButtonSize
;
1224 MapWindowPoints(0, hwnd
, &clpt
, 1);
1225 hit
= PAGER_HitTest(hwnd
, &clpt
);
1226 if (hit
== HTLEFT
|| hit
== HTTOP
) {
1228 btnrect
= &TLbtnrect
;
1229 infoPtr
->TLbtnState
= PGF_DEPRESSED
;
1230 btnstate
= infoPtr
->TLbtnState
;
1232 else if (hit
== HTRIGHT
|| hit
== HTBOTTOM
) {
1234 btnrect
= &BRbtnrect
;
1235 infoPtr
->BRbtnState
= PGF_DEPRESSED
;
1236 btnstate
= infoPtr
->BRbtnState
;
1239 /* If in one of the buttons the capture and draw buttons */
1241 TRACE("[%p] draw btn (%ld,%ld)-(%ld,%ld), Capture %s, style %08lx\n",
1242 hwnd
, btnrect
->left
, btnrect
->top
,
1243 btnrect
->right
, btnrect
->bottom
,
1244 (infoPtr
->bCapture
) ? "TRUE" : "FALSE",
1246 if (!infoPtr
->bCapture
)
1247 PAGER_CaptureandTrack(infoPtr
, hwnd
);
1248 if (dwStyle
& PGS_AUTOSCROLL
)
1249 SetTimer(hwnd
, TIMERID1
, 0x3e, 0);
1250 MapWindowPoints(0, hwnd
, (LPPOINT
)btnrect
, 2);
1251 hdc
= GetWindowDC(hwnd
);
1252 /* OffsetRect(wnrect, 0 | 1, 0 | 1) */
1253 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, *btnrect
,
1254 PAGER_IsHorizontal(hwnd
), topLeft
, btnstate
);
1255 ReleaseDC(hwnd
, hdc
);
1256 return DefWindowProcA (hwnd
, WM_MOUSEMOVE
, wParam
, lParam
);
1260 /* If we think we are captured, then do release */
1261 if (infoPtr
->bCapture
) {
1262 infoPtr
->bCapture
= FALSE
;
1264 if (GetCapture() == hwnd
) {
1266 /* Notify parent of released mouse capture */
1269 ZeroMemory (&nmhdr
, sizeof (NMHDR
));
1270 nmhdr
.hwndFrom
= hwnd
;
1271 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
1272 nmhdr
.code
= NM_RELEASEDCAPTURE
;
1273 SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
1274 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1278 KillTimer(hwnd
, TIMERID1
);
1280 return DefWindowProcA (hwnd
, WM_MOUSEMOVE
, wParam
, lParam
);
1284 PAGER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1286 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1287 BOOL repaintBtns
= FALSE
;
1291 pt
.x
= (short)LOWORD(lParam
);
1292 pt
.y
= (short)HIWORD(lParam
);
1294 TRACE("[%p] at (%d,%d)\n", hwnd
, (short)LOWORD(lParam
), (short)HIWORD(lParam
));
1296 hit
= PAGER_HitTest(hwnd
, &pt
);
1298 /* put btn in DEPRESSED state */
1299 if (hit
== HTLEFT
|| hit
== HTTOP
)
1301 repaintBtns
= infoPtr
->TLbtnState
!= PGF_DEPRESSED
;
1302 infoPtr
->TLbtnState
= PGF_DEPRESSED
;
1303 SetTimer(hwnd
, TIMERID1
, INITIAL_DELAY
, 0);
1305 else if (hit
== HTRIGHT
|| hit
== HTBOTTOM
)
1307 repaintBtns
= infoPtr
->BRbtnState
!= PGF_DEPRESSED
;
1308 infoPtr
->BRbtnState
= PGF_DEPRESSED
;
1309 SetTimer(hwnd
, TIMERID1
, INITIAL_DELAY
, 0);
1313 SendMessageA(hwnd
, WM_NCPAINT
, 0, 0);
1318 TRACE("[%p] PGF_SCROLLLEFT\n", hwnd
);
1319 PAGER_Scroll(hwnd
, PGF_SCROLLLEFT
);
1322 TRACE("[%p] PGF_SCROLLUP\n", hwnd
);
1323 PAGER_Scroll(hwnd
, PGF_SCROLLUP
);
1326 TRACE("[%p] PGF_SCROLLRIGHT\n", hwnd
);
1327 PAGER_Scroll(hwnd
, PGF_SCROLLRIGHT
);
1330 TRACE("[%p] PGF_SCROLLDOWN\n", hwnd
);
1331 PAGER_Scroll(hwnd
, PGF_SCROLLDOWN
);
1341 PAGER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1343 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1344 TRACE("[%p]\n", hwnd
);
1346 KillTimer (hwnd
, TIMERID1
);
1347 KillTimer (hwnd
, TIMERID2
);
1349 /* make PRESSED btns NORMAL but don't hide gray btns */
1350 PAGER_UpdateBtns(hwnd
, infoPtr
, -1, FALSE
);
1356 PAGER_NCLButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1360 pt
.x
= (short)LOWORD(lParam
);
1361 pt
.y
= (short)HIWORD(lParam
);
1363 TRACE("[%p] at (%ld,%ld)\n", hwnd
, pt
.x
, pt
.y
);
1364 MapWindowPoints(0, hwnd
, &pt
, 1);
1365 lParam
= MAKELONG(pt
.x
, pt
.y
);
1366 return PAGER_LButtonDown (hwnd
, wParam
, lParam
);
1370 PAGER_Timer (HWND hwnd
, WPARAM wParam
)
1372 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1373 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1376 /* if initial timer, kill it and start the repeat timer */
1377 if (wParam
== TIMERID1
) {
1378 if (PAGER_IsHorizontal(hwnd
)) {
1379 dir
= (infoPtr
->TLbtnState
& PGF_DEPRESSED
) ?
1380 PGF_SCROLLLEFT
: PGF_SCROLLRIGHT
;
1383 dir
= (infoPtr
->TLbtnState
& PGF_DEPRESSED
) ?
1384 PGF_SCROLLUP
: PGF_SCROLLDOWN
;
1386 TRACE("[%p] TIMERID1: style=%08lx, dir=%d\n", hwnd
, dwStyle
, dir
);
1387 KillTimer(hwnd
, TIMERID1
);
1388 SetTimer(hwnd
, TIMERID1
, REPEAT_DELAY
, 0);
1389 if (dwStyle
& PGS_AUTOSCROLL
) {
1390 PAGER_Scroll(hwnd
, dir
);
1391 SetWindowPos(hwnd
, 0,0,0,0,0,
1392 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1393 SWP_NOZORDER
| SWP_NOACTIVATE
);
1399 TRACE("[%p] TIMERID2: dir=%d\n", hwnd
, infoPtr
->direction
);
1400 KillTimer(hwnd
, TIMERID2
);
1401 if (infoPtr
->direction
> 0) {
1402 PAGER_Scroll(hwnd
, infoPtr
->direction
);
1403 SetTimer(hwnd
, TIMERID2
, REPEAT_DELAY
, 0);
1409 PAGER_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1412 HDC hdc
= (HDC
)wParam
;
1416 * parent = GetParent(pager)
1417 * pt.x=0; pt.y=0; ?????
1418 * MapWindowPoints(pager, parent, &pt, 1)
1419 * OffsetWindowOrgEx(hdc, pt.x, pt.y, &ptorg)
1420 * SendMessageA(parent, WM_ERASEBKGND, hdc, 0)
1421 * SetWindowOrgEx(hdc, 0, 0, 0)
1426 parent
= GetParent(hwnd
);
1427 MapWindowPoints(hwnd
, parent
, &pt
, 1);
1428 OffsetWindowOrgEx (hdc
, pt
.x
, pt
.y
, &ptorig
);
1429 SendMessageA (parent
, WM_ERASEBKGND
, wParam
, lParam
);
1430 SetWindowOrgEx (hdc
, ptorig
.x
, ptorig
.y
, 0);
1434 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1435 HBRUSH hBrush
= CreateSolidBrush(infoPtr
->clrBk
);
1438 GetClientRect (hwnd
, &rect
);
1439 FillRect ((HDC
)wParam
, &rect
, hBrush
);
1441 /* background color of the child should be the same as the pager */
1442 if (infoPtr
->hwndChild
)
1444 GetClientRect (infoPtr
->hwndChild
, &rect
);
1445 FillRect ((HDC
)wParam
, &rect
, hBrush
);
1448 DeleteObject (hBrush
);
1456 PAGER_Size (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1458 /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
1460 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1461 TRACE("[%p] %dx%d\n", hwnd
, (short)LOWORD(lParam
), (short)HIWORD(lParam
));
1463 if (PAGER_IsHorizontal(hwnd
))
1464 infoPtr
->nHeight
= (short)HIWORD(lParam
);
1466 infoPtr
->nWidth
= (short)LOWORD(lParam
);
1468 return PAGER_RecalcSize(hwnd
);
1472 static LRESULT WINAPI
1473 PAGER_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1475 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1477 if (!infoPtr
&& (uMsg
!= WM_CREATE
))
1478 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
1483 return PAGER_FmtLines(hwnd
);
1485 case PGM_FORWARDMOUSE
:
1486 return PAGER_ForwardMouse (hwnd
, wParam
);
1488 case PGM_GETBKCOLOR
:
1489 return PAGER_GetBkColor(hwnd
);
1492 return PAGER_GetBorder(hwnd
);
1494 case PGM_GETBUTTONSIZE
:
1495 return PAGER_GetButtonSize(hwnd
);
1498 return PAGER_GetPos(hwnd
);
1500 case PGM_GETBUTTONSTATE
:
1501 return PAGER_GetButtonState (hwnd
, wParam
, lParam
);
1503 /* case PGM_GETDROPTARGET: */
1505 case PGM_RECALCSIZE
:
1506 return PAGER_RecalcSize(hwnd
);
1508 case PGM_SETBKCOLOR
:
1509 return PAGER_SetBkColor (hwnd
, wParam
, lParam
);
1512 return PAGER_SetBorder (hwnd
, wParam
, lParam
);
1514 case PGM_SETBUTTONSIZE
:
1515 return PAGER_SetButtonSize (hwnd
, wParam
, lParam
);
1518 return PAGER_SetChild (hwnd
, wParam
, lParam
);
1521 return PAGER_SetPos(hwnd
, (INT
)lParam
, FALSE
);
1524 return PAGER_Create (hwnd
, wParam
, lParam
);
1527 return PAGER_Destroy (hwnd
, wParam
, lParam
);
1530 return PAGER_Size (hwnd
, wParam
, lParam
);
1533 return PAGER_NCPaint (hwnd
, wParam
, lParam
);
1535 case WM_WINDOWPOSCHANGING
:
1536 return PAGER_HandleWindowPosChanging (hwnd
, wParam
, (WINDOWPOS
*)lParam
);
1539 return PAGER_NCCalcSize (hwnd
, wParam
, lParam
);
1542 return PAGER_NCHitTest (hwnd
, wParam
, lParam
);
1546 if (hwnd
== (HWND
)wParam
)
1547 return PAGER_SetCursor(hwnd
, wParam
, lParam
);
1548 else /* its for the child */
1553 if (infoPtr
->bForward
&& infoPtr
->hwndChild
)
1554 PostMessageA(infoPtr
->hwndChild
, WM_MOUSEMOVE
, wParam
, lParam
);
1555 return PAGER_MouseMove (hwnd
, wParam
, lParam
);
1558 return PAGER_MouseLeave (hwnd
, wParam
, lParam
);
1560 case WM_NCLBUTTONDOWN
:
1561 return PAGER_NCLButtonDown (hwnd
, wParam
, lParam
);
1563 case WM_LBUTTONDOWN
:
1564 return PAGER_LButtonDown (hwnd
, wParam
, lParam
);
1566 case WM_NCLBUTTONUP
:
1568 return PAGER_LButtonUp (hwnd
, wParam
, lParam
);
1571 return PAGER_EraseBackground (hwnd
, wParam
, lParam
);
1574 return PAGER_Paint (hwnd, wParam);
1577 return PAGER_Timer (hwnd
, wParam
);
1581 return SendMessageA (infoPtr
->hwndNotify
, uMsg
, wParam
, lParam
);
1584 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
1592 PAGER_Register (void)
1596 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
1597 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_SAVEBITS
;
1598 wndClass
.lpfnWndProc
= (WNDPROC
)PAGER_WindowProc
;
1599 wndClass
.cbClsExtra
= 0;
1600 wndClass
.cbWndExtra
= sizeof(PAGER_INFO
*);
1601 wndClass
.hCursor
= LoadCursorA (0, (LPSTR
)IDC_ARROW
);
1602 wndClass
.hbrBackground
= 0;
1603 wndClass
.lpszClassName
= WC_PAGESCROLLERA
;
1605 RegisterClassA (&wndClass
);
1610 PAGER_Unregister (void)
1612 UnregisterClassA (WC_PAGESCROLLERA
, NULL
);