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.
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(pager
);
45 HWND hwndChild
; /* handle of the contained wnd */
46 BOOL bNoResize
; /* set when created with CCS_NORESIZE */
47 COLORREF clrBk
; /* background color */
48 INT nBorder
; /* border size for the control */
49 INT nButtonSize
;/* size of the pager btns */
50 INT nPos
; /* scroll position */
51 INT nWidth
; /* from child wnd's response to PGN_CALCSIZE */
52 INT nHeight
; /* from child wnd's response to PGN_CALCSIZE */
53 BOOL bForward
; /* forward WM_MOUSEMOVE msgs to the contained wnd */
54 BOOL bCapture
; /* we have captured the mouse */
55 INT TLbtnState
; /* state of top or left btn */
56 INT BRbtnState
; /* state of bottom or right btn */
57 INT direction
; /* direction of the scroll, (e.g. PGF_SCROLLUP) */
60 #define PAGER_GetInfoPtr(hwnd) ((PAGER_INFO *)GetWindowLongA(hwnd, 0))
61 #define PAGER_IsHorizontal(hwnd) ((GetWindowLongA (hwnd, GWL_STYLE) & PGS_HORZ))
63 #define MIN_ARROW_WIDTH 8
64 #define MIN_ARROW_HEIGHT 5
68 #define INITIAL_DELAY 500
69 #define REPEAT_DELAY 50
71 /* the horizontal arrows are:
84 PAGER_DrawHorzArrow (HDC hdc
, RECT r
, INT colorRef
, BOOL left
)
89 w
= r
.right
- r
.left
+ 1;
90 h
= r
.bottom
- r
.top
+ 1;
91 if ((h
< MIN_ARROW_WIDTH
) || (w
< MIN_ARROW_HEIGHT
))
92 return; /* refuse to draw partial arrow */
94 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
95 hOldPen
= SelectObject ( hdc
, hPen
);
98 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 3;
99 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
100 MoveToEx (hdc
, x
, y
, NULL
);
101 LineTo (hdc
, x
--, y
+5); y
++;
102 MoveToEx (hdc
, x
, y
, NULL
);
103 LineTo (hdc
, x
--, y
+3); y
++;
104 MoveToEx (hdc
, x
, y
, NULL
);
105 LineTo (hdc
, x
, y
+1);
109 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
110 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
111 MoveToEx (hdc
, x
, y
, NULL
);
112 LineTo (hdc
, x
++, y
+5); y
++;
113 MoveToEx (hdc
, x
, y
, NULL
);
114 LineTo (hdc
, x
++, y
+3); y
++;
115 MoveToEx (hdc
, x
, y
, NULL
);
116 LineTo (hdc
, x
, y
+1);
119 SelectObject( hdc
, hOldPen
);
120 DeleteObject( hPen
);
123 /* the vertical arrows are:
133 PAGER_DrawVertArrow (HDC hdc
, RECT r
, INT colorRef
, BOOL up
)
138 w
= r
.right
- r
.left
+ 1;
139 h
= r
.bottom
- r
.top
+ 1;
140 if ((h
< MIN_ARROW_WIDTH
) || (w
< MIN_ARROW_HEIGHT
))
141 return; /* refuse to draw partial arrow */
143 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
144 hOldPen
= SelectObject ( hdc
, hPen
);
147 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
148 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 3;
149 MoveToEx (hdc
, x
, y
, NULL
);
150 LineTo (hdc
, x
+5, y
--); x
++;
151 MoveToEx (hdc
, x
, y
, NULL
);
152 LineTo (hdc
, x
+3, y
--); x
++;
153 MoveToEx (hdc
, x
, y
, NULL
);
154 LineTo (hdc
, x
+1, y
);
158 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
159 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
160 MoveToEx (hdc
, x
, y
, NULL
);
161 LineTo (hdc
, x
+5, y
++); x
++;
162 MoveToEx (hdc
, x
, y
, NULL
);
163 LineTo (hdc
, x
+3, y
++); x
++;
164 MoveToEx (hdc
, x
, y
, NULL
);
165 LineTo (hdc
, x
+1, y
);
168 SelectObject( hdc
, hOldPen
);
169 DeleteObject( hPen
);
173 PAGER_DrawButton(HDC hdc
, COLORREF clrBk
, RECT arrowRect
,
174 BOOL horz
, BOOL topLeft
, INT btnState
)
176 HBRUSH hBrush
, hOldBrush
;
179 if (!btnState
) /* PGF_INVISIBLE */
182 if ((rc
.right
- rc
.left
<= 0) || (rc
.bottom
- rc
.top
<= 0))
185 hBrush
= CreateSolidBrush(clrBk
);
186 hOldBrush
= (HBRUSH
)SelectObject(hdc
, hBrush
);
188 FillRect(hdc
, &rc
, hBrush
);
190 if (btnState
== PGF_HOT
)
192 DrawEdge( hdc
, &rc
, BDR_RAISEDINNER
, BF_RECT
);
194 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
196 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
198 else if (btnState
== PGF_NORMAL
)
200 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
202 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
204 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
206 else if (btnState
== PGF_DEPRESSED
)
208 DrawEdge( hdc
, &rc
, BDR_SUNKENOUTER
, BF_RECT
);
210 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
212 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
214 else if (btnState
== PGF_GRAYED
)
216 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
219 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
220 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
221 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
225 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
226 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
227 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
231 SelectObject( hdc
, hOldBrush
);
232 DeleteObject(hBrush
);
235 static void PAGER_CaptureandTrack(PAGER_INFO
*infoPtr
, HWND hwnd
)
237 TRACKMOUSEEVENT trackinfo
;
239 TRACE("[%p] SetCapture\n", hwnd
);
241 infoPtr
->bCapture
= TRUE
;
243 trackinfo
.cbSize
= sizeof(TRACKMOUSEEVENT
);
244 trackinfo
.dwFlags
= TME_QUERY
;
245 trackinfo
.hwndTrack
= hwnd
;
246 trackinfo
.dwHoverTime
= HOVER_DEFAULT
;
248 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
249 _TrackMouseEvent(&trackinfo
);
251 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
252 if(!(trackinfo
.dwFlags
& TME_LEAVE
)) {
253 trackinfo
.dwFlags
= TME_LEAVE
; /* notify upon leaving */
255 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
256 /* and can properly deactivate the hot button */
257 _TrackMouseEvent(&trackinfo
);
262 /* << PAGER_GetDropTarget >> */
264 static inline LRESULT
265 PAGER_ForwardMouse (HWND hwnd
, WPARAM wParam
)
267 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
268 TRACE("[%p]\n", hwnd
);
270 infoPtr
->bForward
= (BOOL
)wParam
;
275 static inline LRESULT
276 PAGER_GetButtonState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
278 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
279 LRESULT btnState
= PGF_INVISIBLE
;
280 INT btn
= (INT
)lParam
;
281 TRACE("[%p]\n", hwnd
);
283 if (btn
== PGB_TOPORLEFT
)
284 btnState
= infoPtr
->TLbtnState
;
285 else if (btn
== PGB_BOTTOMORRIGHT
)
286 btnState
= infoPtr
->BRbtnState
;
292 static inline LRESULT
293 PAGER_GetPos(HWND hwnd
)
295 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
296 TRACE("[%p] returns %d\n", hwnd
, infoPtr
->nPos
);
297 return (LRESULT
)infoPtr
->nPos
;
300 static inline LRESULT
301 PAGER_GetButtonSize(HWND hwnd
)
303 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
304 TRACE("[%p] returns %d\n", hwnd
, infoPtr
->nButtonSize
);
305 return (LRESULT
)infoPtr
->nButtonSize
;
308 static inline LRESULT
309 PAGER_GetBorder(HWND hwnd
)
311 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
312 TRACE("[%p] returns %d\n", hwnd
, infoPtr
->nBorder
);
313 return (LRESULT
)infoPtr
->nBorder
;
316 static inline LRESULT
317 PAGER_GetBkColor(HWND hwnd
)
319 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
320 TRACE("[%p] returns %06lx\n", hwnd
, infoPtr
->clrBk
);
321 return (LRESULT
)infoPtr
->clrBk
;
325 PAGER_CalcSize (HWND hwnd
, INT
* size
, BOOL getWidth
)
328 ZeroMemory (&nmpgcs
, sizeof (NMPGCALCSIZE
));
329 nmpgcs
.hdr
.hwndFrom
= hwnd
;
330 nmpgcs
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
331 nmpgcs
.hdr
.code
= PGN_CALCSIZE
;
332 nmpgcs
.dwFlag
= getWidth
? PGF_CALCWIDTH
: PGF_CALCHEIGHT
;
333 nmpgcs
.iWidth
= getWidth
? *size
: 0;
334 nmpgcs
.iHeight
= getWidth
? 0 : *size
;
335 SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
336 (WPARAM
)nmpgcs
.hdr
.idFrom
, (LPARAM
)&nmpgcs
);
338 *size
= getWidth
? nmpgcs
.iWidth
: nmpgcs
.iHeight
;
340 TRACE("[%p] PGN_CALCSIZE returns %s=%d\n", hwnd
,
341 getWidth
? "width" : "height", *size
);
345 PAGER_PositionChildWnd(HWND hwnd
, PAGER_INFO
* infoPtr
)
347 if (infoPtr
->hwndChild
)
350 int nPos
= infoPtr
->nPos
;
352 /* compensate for a grayed btn, which will soon become invisible */
353 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
354 nPos
+= infoPtr
->nButtonSize
;
356 GetClientRect(hwnd
, &rcClient
);
358 if (PAGER_IsHorizontal(hwnd
))
360 int wndSize
= max(0, rcClient
.right
- rcClient
.left
);
361 if (infoPtr
->nWidth
< wndSize
)
362 infoPtr
->nWidth
= wndSize
;
364 TRACE("[%p] SWP %dx%d at (%d,%d)\n", hwnd
,
365 infoPtr
->nWidth
, infoPtr
->nHeight
,
367 SetWindowPos(infoPtr
->hwndChild
, 0,
369 infoPtr
->nWidth
, infoPtr
->nHeight
,
374 int wndSize
= max(0, rcClient
.bottom
- rcClient
.top
);
375 if (infoPtr
->nHeight
< wndSize
)
376 infoPtr
->nHeight
= wndSize
;
378 TRACE("[%p] SWP %dx%d at (%d,%d)\n", hwnd
,
379 infoPtr
->nWidth
, infoPtr
->nHeight
,
381 SetWindowPos(infoPtr
->hwndChild
, 0,
383 infoPtr
->nWidth
, infoPtr
->nHeight
,
387 InvalidateRect(infoPtr
->hwndChild
, NULL
, TRUE
);
392 PAGER_GetScrollRange(HWND hwnd
, PAGER_INFO
* infoPtr
)
396 if (infoPtr
->hwndChild
)
398 INT wndSize
, childSize
;
400 GetWindowRect(hwnd
, &wndRect
);
402 if (PAGER_IsHorizontal(hwnd
))
404 wndSize
= wndRect
.right
- wndRect
.left
;
405 PAGER_CalcSize(hwnd
, &infoPtr
->nWidth
, TRUE
);
406 childSize
= infoPtr
->nWidth
;
410 wndSize
= wndRect
.bottom
- wndRect
.top
;
411 PAGER_CalcSize(hwnd
, &infoPtr
->nHeight
, FALSE
);
412 childSize
= infoPtr
->nHeight
;
415 TRACE("childSize = %d, wndSize = %d\n", childSize
, wndSize
);
416 if (childSize
> wndSize
)
417 scrollRange
= childSize
- wndSize
+ infoPtr
->nButtonSize
;
420 TRACE("[%p] returns %d\n", hwnd
, scrollRange
);
425 PAGER_GrayAndRestoreBtns(PAGER_INFO
* infoPtr
, INT scrollRange
,
426 BOOL
* needsResize
, BOOL
* needsRepaint
)
428 if (infoPtr
->nPos
> 0)
430 *needsResize
|= !infoPtr
->TLbtnState
; /* PGF_INVISIBLE */
431 if (infoPtr
->TLbtnState
!= PGF_DEPRESSED
)
432 infoPtr
->TLbtnState
= PGF_NORMAL
;
436 *needsRepaint
|= (infoPtr
->TLbtnState
!= PGF_GRAYED
);
437 infoPtr
->TLbtnState
= PGF_GRAYED
;
440 if (scrollRange
<= 0)
442 *needsRepaint
|= (infoPtr
->TLbtnState
!= PGF_GRAYED
);
443 infoPtr
->TLbtnState
= PGF_GRAYED
;
444 *needsRepaint
|= (infoPtr
->BRbtnState
!= PGF_GRAYED
);
445 infoPtr
->BRbtnState
= PGF_GRAYED
;
447 else if (infoPtr
->nPos
< scrollRange
)
449 *needsResize
|= !infoPtr
->BRbtnState
; /* PGF_INVISIBLE */
450 if (infoPtr
->BRbtnState
!= PGF_DEPRESSED
)
451 infoPtr
->BRbtnState
= PGF_NORMAL
;
455 *needsRepaint
|= (infoPtr
->BRbtnState
!= PGF_GRAYED
);
456 infoPtr
->BRbtnState
= PGF_GRAYED
;
462 PAGER_NormalizeBtns(PAGER_INFO
* infoPtr
, BOOL
* needsRepaint
)
464 if (infoPtr
->TLbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
466 infoPtr
->TLbtnState
= PGF_NORMAL
;
467 *needsRepaint
= TRUE
;
470 if (infoPtr
->BRbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
472 infoPtr
->BRbtnState
= PGF_NORMAL
;
473 *needsRepaint
= TRUE
;
478 PAGER_HideGrayBtns(PAGER_INFO
* infoPtr
, BOOL
* needsResize
)
480 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
482 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
486 if (infoPtr
->BRbtnState
== PGF_GRAYED
)
488 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
494 PAGER_UpdateBtns(HWND hwnd
, PAGER_INFO
*infoPtr
,
495 INT scrollRange
, BOOL hideGrayBtns
)
497 BOOL resizeClient
= FALSE
;
498 BOOL repaintBtns
= FALSE
;
501 PAGER_NormalizeBtns(infoPtr
, &repaintBtns
);
503 PAGER_GrayAndRestoreBtns(infoPtr
, scrollRange
, &resizeClient
, &repaintBtns
);
506 PAGER_HideGrayBtns(infoPtr
, &resizeClient
);
508 if (resizeClient
) /* initiate NCCalcSize to resize client wnd */ {
509 SetWindowPos(hwnd
, 0,0,0,0,0,
510 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
511 SWP_NOZORDER
| SWP_NOACTIVATE
);
515 SendMessageA(hwnd
, WM_NCPAINT
, 0, 0);
519 PAGER_SetPos(HWND hwnd
, INT newPos
, BOOL fromBtnPress
)
521 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
522 INT scrollRange
= PAGER_GetScrollRange(hwnd
, infoPtr
);
523 INT oldPos
= infoPtr
->nPos
;
525 if ((scrollRange
<= 0) || (newPos
< 0))
527 else if (newPos
> scrollRange
)
528 infoPtr
->nPos
= scrollRange
;
530 infoPtr
->nPos
= newPos
;
532 TRACE("[%p] pos=%d, oldpos=%d\n", hwnd
, infoPtr
->nPos
, oldPos
);
534 if (infoPtr
->nPos
!= oldPos
)
536 /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
537 PAGER_UpdateBtns(hwnd
, infoPtr
, scrollRange
, !fromBtnPress
);
538 PAGER_PositionChildWnd(hwnd
, infoPtr
);
545 PAGER_HandleWindowPosChanging(HWND hwnd
, WPARAM wParam
, WINDOWPOS
*winpos
)
547 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
549 if (infoPtr
->bNoResize
&& !(winpos
->flags
& SWP_NOSIZE
))
551 /* don't let the app resize the nonscrollable dimension of a control
552 * that was created with CCS_NORESIZE style
553 * (i.e. height for a horizontal pager, or width for a vertical one) */
555 /* except if the current dimension is 0 and app is setting for
556 * first time, then save amount as dimension. - GA 8/01 */
558 if (PAGER_IsHorizontal(hwnd
))
559 if (!infoPtr
->nHeight
&& winpos
->cy
)
560 infoPtr
->nHeight
= winpos
->cy
;
562 winpos
->cy
= infoPtr
->nHeight
;
564 if (!infoPtr
->nWidth
&& winpos
->cx
)
565 infoPtr
->nWidth
= winpos
->cx
;
567 winpos
->cx
= infoPtr
->nWidth
;
571 DefWindowProcA (hwnd
, WM_WINDOWPOSCHANGING
, wParam
, (LPARAM
)winpos
);
577 PAGER_SetFixedWidth(HWND hwnd
, PAGER_INFO
* infoPtr
)
579 /* Must set the non-scrollable dimension to be less than the full height/width
580 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
581 * size, and experimentation shows that affect is almost right. */
585 GetWindowRect(hwnd
, &wndRect
);
587 /* see what the app says for btn width */
588 PAGER_CalcSize(hwnd
, &infoPtr
->nWidth
, TRUE
);
590 if (infoPtr
->bNoResize
)
592 delta
= wndRect
.right
- wndRect
.left
- infoPtr
->nWidth
;
593 if (delta
> infoPtr
->nButtonSize
)
594 infoPtr
->nWidth
+= 4 * infoPtr
->nButtonSize
/ 3;
596 infoPtr
->nWidth
+= infoPtr
->nButtonSize
/ 3;
599 h
= wndRect
.bottom
- wndRect
.top
+ infoPtr
->nButtonSize
;
601 TRACE("[%p] infoPtr->nWidth set to %d\n",
602 hwnd
, infoPtr
->nWidth
);
608 PAGER_SetFixedHeight(HWND hwnd
, PAGER_INFO
* infoPtr
)
610 /* Must set the non-scrollable dimension to be less than the full height/width
611 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
612 * size, and experimentation shows that affect is almost right. */
616 GetWindowRect(hwnd
, &wndRect
);
618 /* see what the app says for btn height */
619 PAGER_CalcSize(hwnd
, &infoPtr
->nHeight
, FALSE
);
621 if (infoPtr
->bNoResize
)
623 delta
= wndRect
.bottom
- wndRect
.top
- infoPtr
->nHeight
;
624 if (delta
> infoPtr
->nButtonSize
)
625 infoPtr
->nHeight
+= infoPtr
->nButtonSize
;
627 infoPtr
->nHeight
+= infoPtr
->nButtonSize
/ 3;
630 w
= wndRect
.right
- wndRect
.left
+ infoPtr
->nButtonSize
;
632 TRACE("[%p] infoPtr->nHeight set to %d\n",
633 hwnd
, infoPtr
->nHeight
);
638 /******************************************************************
639 * For the PGM_RECALCSIZE message (but not the other uses in *
640 * this module), the native control does only the following: *
642 * if (some condition) *
643 * PostMessageA(hwnd, EM_FMTLINES, 0, 0); *
644 * return DefWindowProcA(hwnd, PGM_RECALCSIZE, 0, 0); *
646 * When we figure out what the "some condition" is we will *
647 * implement that for the message processing. *
648 ******************************************************************/
651 PAGER_RecalcSize(HWND hwnd
)
653 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
655 TRACE("[%p]\n", hwnd
);
657 if (infoPtr
->hwndChild
)
659 INT scrollRange
= PAGER_GetScrollRange(hwnd
, infoPtr
);
661 if (scrollRange
<= 0)
664 PAGER_SetPos(hwnd
, 0, FALSE
);
668 PAGER_UpdateBtns(hwnd
, infoPtr
, scrollRange
, TRUE
);
669 PAGER_PositionChildWnd(hwnd
, infoPtr
);
678 PAGER_SetBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
680 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
681 COLORREF clrTemp
= infoPtr
->clrBk
;
683 infoPtr
->clrBk
= (COLORREF
)lParam
;
684 TRACE("[%p] %06lx\n", hwnd
, infoPtr
->clrBk
);
686 /* the native control seems to do things this way */
687 SetWindowPos(hwnd
, 0,0,0,0,0,
688 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
689 SWP_NOZORDER
| SWP_NOACTIVATE
);
691 RedrawWindow(hwnd
, 0, 0, RDW_ERASE
| RDW_INVALIDATE
);
693 return (LRESULT
)clrTemp
;
698 PAGER_SetBorder (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
700 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
701 INT nTemp
= infoPtr
->nBorder
;
703 infoPtr
->nBorder
= (INT
)lParam
;
704 TRACE("[%p] %d\n", hwnd
, infoPtr
->nBorder
);
706 PAGER_RecalcSize(hwnd
);
708 return (LRESULT
)nTemp
;
713 PAGER_SetButtonSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
715 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
716 INT nTemp
= infoPtr
->nButtonSize
;
718 infoPtr
->nButtonSize
= (INT
)lParam
;
719 TRACE("[%p] %d\n", hwnd
, infoPtr
->nButtonSize
);
721 PAGER_RecalcSize(hwnd
);
723 return (LRESULT
)nTemp
;
728 PAGER_SetChild (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
730 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
733 infoPtr
->hwndChild
= IsWindow ((HWND
)lParam
) ? (HWND
)lParam
: 0;
735 if (infoPtr
->hwndChild
)
737 TRACE("[%p] hwndChild=%p\n", hwnd
, infoPtr
->hwndChild
);
739 if (PAGER_IsHorizontal(hwnd
)) {
740 hw
= PAGER_SetFixedHeight(hwnd
, infoPtr
);
741 /* adjust non-scrollable dimension to fit the child */
742 SetWindowPos(hwnd
, 0, 0,0, hw
, infoPtr
->nHeight
,
743 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
744 SWP_NOSIZE
| SWP_NOACTIVATE
);
747 hw
= PAGER_SetFixedWidth(hwnd
, infoPtr
);
748 /* adjust non-scrollable dimension to fit the child */
749 SetWindowPos(hwnd
, 0, 0,0, infoPtr
->nWidth
, hw
,
750 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
751 SWP_NOSIZE
| SWP_NOACTIVATE
);
754 /* position child within the page scroller */
755 SetWindowPos(infoPtr
->hwndChild
, HWND_TOP
,
757 SWP_SHOWWINDOW
| SWP_NOSIZE
); /* native is 0 */
760 PAGER_SetPos(hwnd
, 0, FALSE
);
767 PAGER_Scroll(HWND hwnd
, INT dir
)
769 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
770 NMPGSCROLL nmpgScroll
;
773 if (infoPtr
->hwndChild
)
775 ZeroMemory (&nmpgScroll
, sizeof (NMPGSCROLL
));
776 nmpgScroll
.hdr
.hwndFrom
= hwnd
;
777 nmpgScroll
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
778 nmpgScroll
.hdr
.code
= PGN_SCROLL
;
780 GetWindowRect(hwnd
, &rcWnd
);
781 GetClientRect(hwnd
, &nmpgScroll
.rcParent
);
782 nmpgScroll
.iXpos
= nmpgScroll
.iYpos
= 0;
783 nmpgScroll
.iDir
= dir
;
785 if (PAGER_IsHorizontal(hwnd
))
787 nmpgScroll
.iScroll
= rcWnd
.right
- rcWnd
.left
;
788 nmpgScroll
.iXpos
= infoPtr
->nPos
;
792 nmpgScroll
.iScroll
= rcWnd
.bottom
- rcWnd
.top
;
793 nmpgScroll
.iYpos
= infoPtr
->nPos
;
795 nmpgScroll
.iScroll
-= 2*infoPtr
->nButtonSize
;
797 SendMessageA (GetParent(hwnd
), WM_NOTIFY
,
798 (WPARAM
)nmpgScroll
.hdr
.idFrom
, (LPARAM
)&nmpgScroll
);
800 TRACE("[%p] PGN_SCROLL returns iScroll=%d\n", hwnd
, nmpgScroll
.iScroll
);
802 if (nmpgScroll
.iScroll
> 0)
804 infoPtr
->direction
= dir
;
806 if (dir
== PGF_SCROLLLEFT
|| dir
== PGF_SCROLLUP
)
807 PAGER_SetPos(hwnd
, infoPtr
->nPos
- nmpgScroll
.iScroll
, TRUE
);
809 PAGER_SetPos(hwnd
, infoPtr
->nPos
+ nmpgScroll
.iScroll
, TRUE
);
812 infoPtr
->direction
= -1;
817 PAGER_FmtLines(HWND hwnd
)
819 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
821 /* initiate NCCalcSize to resize client wnd and get size */
822 SetWindowPos(hwnd
, 0, 0,0,0,0,
823 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
824 SWP_NOZORDER
| SWP_NOACTIVATE
);
826 SetWindowPos(infoPtr
->hwndChild
, 0,
827 0,0,infoPtr
->nWidth
,infoPtr
->nHeight
,
830 return DefWindowProcA (hwnd
, EM_FMTLINES
, 0, 0);
834 PAGER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
837 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
839 /* allocate memory for info structure */
840 infoPtr
= (PAGER_INFO
*)COMCTL32_Alloc (sizeof(PAGER_INFO
));
841 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
843 /* set default settings */
844 infoPtr
->hwndChild
= NULL
;
845 infoPtr
->bNoResize
= dwStyle
& CCS_NORESIZE
;
846 infoPtr
->clrBk
= GetSysColor(COLOR_BTNFACE
);
847 infoPtr
->nBorder
= 0;
848 infoPtr
->nButtonSize
= 12;
851 infoPtr
->nHeight
= 0;
852 infoPtr
->bForward
= FALSE
;
853 infoPtr
->bCapture
= FALSE
;
854 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
855 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
856 infoPtr
->direction
= -1;
858 if (dwStyle
& PGS_DRAGNDROP
)
859 FIXME("[%p] Drag and Drop style is not implemented yet.\n", hwnd
);
861 * If neither horizontal nor vertical style specified, default to vertical.
862 * This is probably not necessary, since the style may be set later on as
863 * the control is initialized, but just in case it isn't, set it here.
865 if (!(dwStyle
& PGS_HORZ
) && !(dwStyle
& PGS_VERT
))
868 SetWindowLongA(hwnd
, GWL_STYLE
, dwStyle
);
876 PAGER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
878 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
879 /* free pager info data */
880 COMCTL32_Free (infoPtr
);
881 SetWindowLongA (hwnd
, 0, 0);
886 PAGER_NCCalcSize(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
888 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
889 LPRECT lpRect
= (LPRECT
)lParam
;
890 RECT rcChildw
, rcmyw
, wnrc
, ltrc
, rbrc
;
892 BOOL resizeClient
= FALSE
;
893 BOOL repaintBtns
= FALSE
;
897 * lParam points to a RECT struct. On entry, the struct
898 * contains the proposed wnd rectangle for the window.
899 * On exit, the struct should contain the screen
900 * coordinates of the corresponding window's client area.
903 DefWindowProcA (hwnd
, WM_NCCALCSIZE
, wParam
, lParam
);
905 TRACE("orig rect=(%ld,%ld)-(%ld,%ld)\n",
906 lpRect
->left
, lpRect
->top
, lpRect
->right
, lpRect
->bottom
);
908 if (PAGER_IsHorizontal(hwnd
))
910 infoPtr
->nWidth
= lpRect
->right
- lpRect
->left
;
911 PAGER_CalcSize (hwnd
, &infoPtr
->nWidth
, TRUE
);
912 GetWindowRect (infoPtr
->hwndChild
, &rcChildw
);
913 MapWindowPoints (0, hwnd
, (LPPOINT
)&rcChildw
, 2);
914 GetCursorPos (&cursor
);
915 GetWindowRect (hwnd
, &rcmyw
);
917 /* Reset buttons and hide any grey ones */
918 scrollRange
= infoPtr
->nWidth
- (rcmyw
.right
- rcmyw
.left
);
920 TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%ld,%ld)-(%ld,%ld), cursor=(%ld,%ld)\n",
921 infoPtr
->nPos
, scrollRange
, infoPtr
->nHeight
,
922 rcmyw
.left
, rcmyw
.top
,
923 rcmyw
.right
, rcmyw
.bottom
,
925 PAGER_GrayAndRestoreBtns(infoPtr
, scrollRange
, &resizeClient
, &repaintBtns
);
926 PAGER_HideGrayBtns(infoPtr
, &resizeClient
);
928 if (PtInRect (&rcmyw
, cursor
)) {
929 GetWindowRect (hwnd
, &wnrc
);
931 ltrc
.right
= ltrc
.left
+ infoPtr
->nButtonSize
;
933 rbrc
.left
= rbrc
.right
- infoPtr
->nButtonSize
;
934 TRACE("horz lt rect=(%ld,%ld)-(%ld,%ld), rb rect=(%ld,%ld)-(%ld,%ld)\n",
935 ltrc
.left
, ltrc
.top
, ltrc
.right
, ltrc
.bottom
,
936 rbrc
.left
, rbrc
.top
, rbrc
.right
, rbrc
.bottom
);
937 if (PtInRect (<rc
, cursor
) && infoPtr
->TLbtnState
)
938 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
939 if (PtInRect (&rbrc
, cursor
) && infoPtr
->BRbtnState
)
940 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
942 if (infoPtr
->TLbtnState
&& (lpRect
->left
+ infoPtr
->nButtonSize
< lpRect
->right
))
943 lpRect
->left
+= infoPtr
->nButtonSize
;
944 if (infoPtr
->BRbtnState
&& (lpRect
->right
- infoPtr
->nButtonSize
> lpRect
->left
))
945 lpRect
->right
-= infoPtr
->nButtonSize
;
949 /* native does: (from trace of IE4 opening "Favorites" frame)
951 * WM_NOITFY PGN_CALCSIZE w/ dwFlag=2
952 * GetWindowRect (child, &rc)
953 * MapWindowPoints (0, syspager, &rc, 2)
954 * GetCursorPos( &cur )
955 * GetWindowRect (syspager, &rc2)
956 * PtInRect (&rc2, cur.x, cur.y) rtns 0
957 * returns with rect empty
959 infoPtr
->nHeight
= lpRect
->bottom
- lpRect
->top
;
960 PAGER_CalcSize (hwnd
, &infoPtr
->nHeight
, FALSE
);
961 GetWindowRect (infoPtr
->hwndChild
, &rcChildw
);
962 MapWindowPoints (0, hwnd
, (LPPOINT
)&rcChildw
, 2);
963 GetCursorPos (&cursor
);
964 GetWindowRect (hwnd
, &rcmyw
);
966 /* Reset buttons and hide any grey ones */
967 scrollRange
= infoPtr
->nHeight
- (rcmyw
.bottom
- rcmyw
.top
);
969 TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%ld,%ld)-(%ld,%ld), cursor=(%ld,%ld)\n",
970 infoPtr
->nPos
, scrollRange
, infoPtr
->nHeight
,
971 rcmyw
.left
, rcmyw
.top
,
972 rcmyw
.right
, rcmyw
.bottom
,
974 PAGER_GrayAndRestoreBtns(infoPtr
, scrollRange
, &resizeClient
, &repaintBtns
);
975 PAGER_HideGrayBtns(infoPtr
, &resizeClient
);
977 if (PtInRect (&rcmyw
, cursor
)) {
980 * GetWindowRect(pager, &rc)
981 * PtInRect(btn-left????, cur.x, cur.y)
983 * PtInRect(btn-right????, cur.x, cur.y)
985 * RedrawWindow(pager, 0, 0, 5)
989 GetWindowRect (hwnd
, &wnrc
);
991 ltrc
.right
= ltrc
.left
+ infoPtr
->nButtonSize
;
993 rbrc
.left
= rbrc
.right
- infoPtr
->nButtonSize
;
994 TRACE("vert lt rect=(%ld,%ld)-(%ld,%ld), rb rect=(%ld,%ld)-(%ld,%ld)\n",
995 ltrc
.left
, ltrc
.top
, ltrc
.right
, ltrc
.bottom
,
996 rbrc
.left
, rbrc
.top
, rbrc
.right
, rbrc
.bottom
);
997 if (PtInRect (<rc
, cursor
) && infoPtr
->TLbtnState
)
998 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
999 if (PtInRect (&rbrc
, cursor
) && infoPtr
->BRbtnState
)
1000 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
1002 if (infoPtr
->TLbtnState
&& (lpRect
->top
+ infoPtr
->nButtonSize
< lpRect
->bottom
))
1003 lpRect
->top
+= infoPtr
->nButtonSize
;
1004 if (infoPtr
->BRbtnState
&& (lpRect
->bottom
- infoPtr
->nButtonSize
> lpRect
->top
))
1005 lpRect
->bottom
-= infoPtr
->nButtonSize
;
1008 TRACE("[%p] client rect set to %ldx%ld at (%ld,%ld) BtnState[%d,%d]\n",
1009 hwnd
, lpRect
->right
-lpRect
->left
, lpRect
->bottom
-lpRect
->top
,
1010 lpRect
->left
, lpRect
->top
,
1011 infoPtr
->TLbtnState
, infoPtr
->BRbtnState
);
1017 PAGER_NCPaint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1019 PAGER_INFO
* infoPtr
= PAGER_GetInfoPtr(hwnd
);
1020 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1021 RECT rcWindow
, rcBottomRight
, rcTopLeft
;
1023 BOOL bHorizontal
= PAGER_IsHorizontal(hwnd
);
1025 if (dwStyle
& WS_MINIMIZE
)
1028 DefWindowProcA (hwnd
, WM_NCPAINT
, wParam
, lParam
);
1030 if (!(hdc
= GetDCEx (hwnd
, 0, DCX_USESTYLE
| DCX_WINDOW
)))
1033 GetWindowRect (hwnd
, &rcWindow
);
1034 OffsetRect (&rcWindow
, -rcWindow
.left
, -rcWindow
.top
);
1036 rcTopLeft
= rcBottomRight
= rcWindow
;
1039 rcTopLeft
.right
= rcTopLeft
.left
+ infoPtr
->nButtonSize
;
1040 rcBottomRight
.left
= rcBottomRight
.right
- infoPtr
->nButtonSize
;
1044 rcTopLeft
.bottom
= rcTopLeft
.top
+ infoPtr
->nButtonSize
;
1045 rcBottomRight
.top
= rcBottomRight
.bottom
- infoPtr
->nButtonSize
;
1048 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcTopLeft
,
1049 bHorizontal
, TRUE
, infoPtr
->TLbtnState
);
1050 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcBottomRight
,
1051 bHorizontal
, FALSE
, infoPtr
->BRbtnState
);
1053 ReleaseDC( hwnd
, hdc
);
1058 PAGER_HitTest (HWND hwnd
, LPPOINT pt
)
1060 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1062 BOOL bHorizontal
= PAGER_IsHorizontal(hwnd
);
1064 GetClientRect (hwnd
, &clientRect
);
1066 if (PtInRect(&clientRect
, *pt
))
1068 TRACE("HTCLIENT\n");
1072 if (infoPtr
->TLbtnState
&& infoPtr
->TLbtnState
!= PGF_GRAYED
)
1076 if (pt
->x
< clientRect
.left
)
1084 if (pt
->y
< clientRect
.top
)
1092 if (infoPtr
->BRbtnState
&& infoPtr
->BRbtnState
!= PGF_GRAYED
)
1096 if (pt
->x
> clientRect
.right
)
1104 if (pt
->y
> clientRect
.bottom
)
1106 TRACE("HTBOTTOM\n");
1112 TRACE("HTNOWHERE\n");
1117 PAGER_NCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1121 pt
.x
= SLOWORD(lParam
);
1122 pt
.y
= SHIWORD(lParam
);
1124 ScreenToClient (hwnd
, &pt
);
1125 return PAGER_HitTest(hwnd
, &pt
);
1129 PAGER_SetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1131 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1132 BOOL notCaptured
= FALSE
;
1134 switch(LOWORD(lParam
))
1138 if ((notCaptured
= infoPtr
->TLbtnState
!= PGF_HOT
))
1139 infoPtr
->TLbtnState
= PGF_HOT
;
1143 if ((notCaptured
= infoPtr
->BRbtnState
!= PGF_HOT
))
1144 infoPtr
->BRbtnState
= PGF_HOT
;
1152 PAGER_CaptureandTrack(infoPtr
, hwnd
);
1154 SendMessageA(hwnd
, WM_NCPAINT
, 0, 0);
1161 PAGER_MouseLeave (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1163 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1165 KillTimer (hwnd
, TIMERID1
);
1166 KillTimer (hwnd
, TIMERID2
);
1168 TRACE("[%p] ReleaseCapture\n", hwnd
);
1170 infoPtr
->bCapture
= FALSE
;
1172 /* Notify parent of released mouse capture */
1175 ZeroMemory (&nmhdr
, sizeof (NMHDR
));
1176 nmhdr
.hwndFrom
= hwnd
;
1177 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
1178 nmhdr
.code
= NM_RELEASEDCAPTURE
;
1179 SendMessageA (GetParent(hwnd
), WM_NOTIFY
,
1180 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1183 /* make HOT btns NORMAL and hide gray btns */
1184 PAGER_UpdateBtns(hwnd
, infoPtr
, -1, TRUE
);
1190 PAGER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1192 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1194 RECT wnrect
, TLbtnrect
, BRbtnrect
, *btnrect
= NULL
;
1195 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1196 BOOL topLeft
= FALSE
;
1201 pt
.x
= SLOWORD(lParam
);
1202 pt
.y
= SHIWORD(lParam
);
1204 TRACE("[%p] to (%ld,%ld)\n", hwnd
, pt
.x
, pt
.y
);
1205 ClientToScreen(hwnd
, &pt
);
1206 GetWindowRect(hwnd
, &wnrect
);
1207 if (PtInRect(&wnrect
, pt
)) {
1210 if (dwStyle
& PGS_HORZ
) {
1211 TLbtnrect
.right
= TLbtnrect
.left
+ infoPtr
->nButtonSize
;
1212 BRbtnrect
.left
= BRbtnrect
.right
- infoPtr
->nButtonSize
;
1215 TLbtnrect
.bottom
= TLbtnrect
.top
+ infoPtr
->nButtonSize
;
1216 BRbtnrect
.top
= BRbtnrect
.bottom
- infoPtr
->nButtonSize
;
1220 MapWindowPoints(0, hwnd
, &clpt
, 1);
1221 hit
= PAGER_HitTest(hwnd
, &clpt
);
1222 if (hit
== HTLEFT
|| hit
== HTTOP
) {
1224 btnrect
= &TLbtnrect
;
1225 infoPtr
->TLbtnState
= PGF_DEPRESSED
;
1226 btnstate
= infoPtr
->TLbtnState
;
1228 else if (hit
== HTRIGHT
|| hit
== HTBOTTOM
) {
1230 btnrect
= &BRbtnrect
;
1231 infoPtr
->BRbtnState
= PGF_DEPRESSED
;
1232 btnstate
= infoPtr
->BRbtnState
;
1235 /* If in one of the buttons the capture and draw buttons */
1237 TRACE("[%p] draw btn (%ld,%ld)-(%ld,%ld), Capture %s, style %08lx\n",
1238 hwnd
, btnrect
->left
, btnrect
->top
,
1239 btnrect
->right
, btnrect
->bottom
,
1240 (infoPtr
->bCapture
) ? "TRUE" : "FALSE",
1242 if (!infoPtr
->bCapture
)
1243 PAGER_CaptureandTrack(infoPtr
, hwnd
);
1244 if (dwStyle
& PGS_AUTOSCROLL
)
1245 SetTimer(hwnd
, TIMERID1
, 0x3e, 0);
1246 MapWindowPoints(0, hwnd
, (LPPOINT
)btnrect
, 2);
1247 hdc
= GetWindowDC(hwnd
);
1248 /* OffsetRect(wnrect, 0 | 1, 0 | 1) */
1249 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, *btnrect
,
1250 PAGER_IsHorizontal(hwnd
), topLeft
, btnstate
);
1251 ReleaseDC(hwnd
, hdc
);
1252 return DefWindowProcA (hwnd
, WM_MOUSEMOVE
, wParam
, lParam
);
1256 /* If we think we are captured, then do release */
1257 if (infoPtr
->bCapture
) {
1258 infoPtr
->bCapture
= FALSE
;
1260 if (GetCapture() == hwnd
) {
1262 /* Notify parent of released mouse capture */
1265 ZeroMemory (&nmhdr
, sizeof (NMHDR
));
1266 nmhdr
.hwndFrom
= hwnd
;
1267 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
1268 nmhdr
.code
= NM_RELEASEDCAPTURE
;
1269 SendMessageA (GetParent(hwnd
), WM_NOTIFY
,
1270 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1274 KillTimer(hwnd
, TIMERID1
);
1276 return DefWindowProcA (hwnd
, WM_MOUSEMOVE
, wParam
, lParam
);
1280 PAGER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1282 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1283 BOOL repaintBtns
= FALSE
;
1287 pt
.x
= SLOWORD(lParam
);
1288 pt
.y
= SHIWORD(lParam
);
1290 TRACE("[%p] at (%d,%d)\n", hwnd
, SLOWORD(lParam
), SHIWORD(lParam
));
1292 hit
= PAGER_HitTest(hwnd
, &pt
);
1294 /* put btn in DEPRESSED state */
1295 if (hit
== HTLEFT
|| hit
== HTTOP
)
1297 repaintBtns
= infoPtr
->TLbtnState
!= PGF_DEPRESSED
;
1298 infoPtr
->TLbtnState
= PGF_DEPRESSED
;
1299 SetTimer(hwnd
, TIMERID1
, INITIAL_DELAY
, 0);
1301 else if (hit
== HTRIGHT
|| hit
== HTBOTTOM
)
1303 repaintBtns
= infoPtr
->BRbtnState
!= PGF_DEPRESSED
;
1304 infoPtr
->BRbtnState
= PGF_DEPRESSED
;
1305 SetTimer(hwnd
, TIMERID1
, INITIAL_DELAY
, 0);
1309 SendMessageA(hwnd
, WM_NCPAINT
, 0, 0);
1314 TRACE("[%p] PGF_SCROLLLEFT\n", hwnd
);
1315 PAGER_Scroll(hwnd
, PGF_SCROLLLEFT
);
1318 TRACE("[%p] PGF_SCROLLUP\n", hwnd
);
1319 PAGER_Scroll(hwnd
, PGF_SCROLLUP
);
1322 TRACE("[%p] PGF_SCROLLRIGHT\n", hwnd
);
1323 PAGER_Scroll(hwnd
, PGF_SCROLLRIGHT
);
1326 TRACE("[%p] PGF_SCROLLDOWN\n", hwnd
);
1327 PAGER_Scroll(hwnd
, PGF_SCROLLDOWN
);
1337 PAGER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1339 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1340 TRACE("[%p]\n", hwnd
);
1342 KillTimer (hwnd
, TIMERID1
);
1343 KillTimer (hwnd
, TIMERID2
);
1345 /* make PRESSED btns NORMAL but don't hide gray btns */
1346 PAGER_UpdateBtns(hwnd
, infoPtr
, -1, FALSE
);
1352 PAGER_NCLButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1356 pt
.x
= SLOWORD(lParam
);
1357 pt
.y
= SHIWORD(lParam
);
1359 TRACE("[%p] at (%d,%d)\n", hwnd
, SLOWORD(lParam
), SHIWORD(lParam
));
1360 MapWindowPoints(0, hwnd
, &pt
, 1);
1361 lParam
= MAKELONG(pt
.x
, pt
.y
);
1362 return PAGER_LButtonDown (hwnd
, wParam
, lParam
);
1366 PAGER_Timer (HWND hwnd
, WPARAM wParam
)
1368 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1369 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1372 /* if initial timer, kill it and start the repeat timer */
1373 if (wParam
== TIMERID1
) {
1374 if (PAGER_IsHorizontal(hwnd
)) {
1375 dir
= (infoPtr
->TLbtnState
& PGF_DEPRESSED
) ?
1376 PGF_SCROLLLEFT
: PGF_SCROLLRIGHT
;
1379 dir
= (infoPtr
->TLbtnState
& PGF_DEPRESSED
) ?
1380 PGF_SCROLLUP
: PGF_SCROLLDOWN
;
1382 TRACE("[%p] TIMERID1: style=%08lx, dir=%d\n", hwnd
, dwStyle
, dir
);
1383 KillTimer(hwnd
, TIMERID1
);
1384 SetTimer(hwnd
, TIMERID1
, REPEAT_DELAY
, 0);
1385 if (dwStyle
& PGS_AUTOSCROLL
) {
1386 PAGER_Scroll(hwnd
, dir
);
1387 SetWindowPos(hwnd
, 0,0,0,0,0,
1388 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1389 SWP_NOZORDER
| SWP_NOACTIVATE
);
1395 TRACE("[%p] TIMERID2: dir=%d\n", hwnd
, infoPtr
->direction
);
1396 KillTimer(hwnd
, TIMERID2
);
1397 if (infoPtr
->direction
> 0) {
1398 PAGER_Scroll(hwnd
, infoPtr
->direction
);
1399 SetTimer(hwnd
, TIMERID2
, REPEAT_DELAY
, 0);
1405 PAGER_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1408 HDC hdc
= (HDC
)wParam
;
1412 * parent = GetParent(pager)
1413 * pt.x=0; pt.y=0; ?????
1414 * MapWindowPoints(pager, parent, &pt, 1)
1415 * OffsetWindowOrgEx(hdc, pt.x, pt.y, &ptorg)
1416 * SendMessageA(parent, WM_ERASEBKGND, hdc, 0)
1417 * SetWindowOrgEx(hdc, 0, 0, 0)
1422 parent
= GetParent(hwnd
);
1423 MapWindowPoints(hwnd
, parent
, &pt
, 1);
1424 OffsetWindowOrgEx (hdc
, pt
.x
, pt
.y
, &ptorig
);
1425 SendMessageA (parent
, WM_ERASEBKGND
, wParam
, lParam
);
1426 SetWindowOrgEx (hdc
, ptorig
.x
, ptorig
.y
, 0);
1430 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1431 HBRUSH hBrush
= CreateSolidBrush(infoPtr
->clrBk
);
1434 GetClientRect (hwnd
, &rect
);
1435 FillRect ((HDC
)wParam
, &rect
, hBrush
);
1437 /* background color of the child should be the same as the pager */
1438 if (infoPtr
->hwndChild
)
1440 GetClientRect (infoPtr
->hwndChild
, &rect
);
1441 FillRect ((HDC
)wParam
, &rect
, hBrush
);
1444 DeleteObject (hBrush
);
1452 PAGER_Size (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1454 /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
1456 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1457 TRACE("[%p] %dx%d\n", hwnd
, SLOWORD(lParam
), SHIWORD(lParam
));
1459 if (PAGER_IsHorizontal(hwnd
))
1460 infoPtr
->nHeight
= SHIWORD(lParam
);
1462 infoPtr
->nWidth
= SLOWORD(lParam
);
1464 return PAGER_RecalcSize(hwnd
);
1468 static LRESULT WINAPI
1469 PAGER_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1471 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1473 if (!infoPtr
&& (uMsg
!= WM_CREATE
))
1474 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
1479 return PAGER_FmtLines(hwnd
);
1481 case PGM_FORWARDMOUSE
:
1482 return PAGER_ForwardMouse (hwnd
, wParam
);
1484 case PGM_GETBKCOLOR
:
1485 return PAGER_GetBkColor(hwnd
);
1488 return PAGER_GetBorder(hwnd
);
1490 case PGM_GETBUTTONSIZE
:
1491 return PAGER_GetButtonSize(hwnd
);
1494 return PAGER_GetPos(hwnd
);
1496 case PGM_GETBUTTONSTATE
:
1497 return PAGER_GetButtonState (hwnd
, wParam
, lParam
);
1499 /* case PGM_GETDROPTARGET: */
1501 case PGM_RECALCSIZE
:
1502 return PAGER_RecalcSize(hwnd
);
1504 case PGM_SETBKCOLOR
:
1505 return PAGER_SetBkColor (hwnd
, wParam
, lParam
);
1508 return PAGER_SetBorder (hwnd
, wParam
, lParam
);
1510 case PGM_SETBUTTONSIZE
:
1511 return PAGER_SetButtonSize (hwnd
, wParam
, lParam
);
1514 return PAGER_SetChild (hwnd
, wParam
, lParam
);
1517 return PAGER_SetPos(hwnd
, (INT
)lParam
, FALSE
);
1520 return PAGER_Create (hwnd
, wParam
, lParam
);
1523 return PAGER_Destroy (hwnd
, wParam
, lParam
);
1526 return PAGER_Size (hwnd
, wParam
, lParam
);
1529 return PAGER_NCPaint (hwnd
, wParam
, lParam
);
1531 case WM_WINDOWPOSCHANGING
:
1532 return PAGER_HandleWindowPosChanging (hwnd
, wParam
, (WINDOWPOS
*)lParam
);
1535 return PAGER_NCCalcSize (hwnd
, wParam
, lParam
);
1538 return PAGER_NCHitTest (hwnd
, wParam
, lParam
);
1542 if (hwnd
== (HWND
)wParam
)
1543 return PAGER_SetCursor(hwnd
, wParam
, lParam
);
1544 else /* its for the child */
1549 if (infoPtr
->bForward
&& infoPtr
->hwndChild
)
1550 PostMessageA(infoPtr
->hwndChild
, WM_MOUSEMOVE
, wParam
, lParam
);
1551 return PAGER_MouseMove (hwnd
, wParam
, lParam
);
1554 return PAGER_MouseLeave (hwnd
, wParam
, lParam
);
1556 case WM_NCLBUTTONDOWN
:
1557 return PAGER_NCLButtonDown (hwnd
, wParam
, lParam
);
1559 case WM_LBUTTONDOWN
:
1560 return PAGER_LButtonDown (hwnd
, wParam
, lParam
);
1562 case WM_NCLBUTTONUP
:
1564 return PAGER_LButtonUp (hwnd
, wParam
, lParam
);
1567 return PAGER_EraseBackground (hwnd
, wParam
, lParam
);
1570 return PAGER_Paint (hwnd, wParam);
1573 return PAGER_Timer (hwnd
, wParam
);
1577 return SendMessageA (GetParent (hwnd
), uMsg
, wParam
, lParam
);
1580 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
1588 PAGER_Register (void)
1592 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
1593 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_SAVEBITS
;
1594 wndClass
.lpfnWndProc
= (WNDPROC
)PAGER_WindowProc
;
1595 wndClass
.cbClsExtra
= 0;
1596 wndClass
.cbWndExtra
= sizeof(PAGER_INFO
*);
1597 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
1598 wndClass
.hbrBackground
= 0;
1599 wndClass
.lpszClassName
= WC_PAGESCROLLERA
;
1601 RegisterClassA (&wndClass
);
1606 PAGER_Unregister (void)
1608 UnregisterClassA (WC_PAGESCROLLERA
, NULL
);