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 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
90 hOldPen
= SelectObject ( hdc
, hPen
);
93 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 3;
94 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
95 MoveToEx (hdc
, x
, y
, NULL
);
96 LineTo (hdc
, x
--, y
+5); y
++;
97 MoveToEx (hdc
, x
, y
, NULL
);
98 LineTo (hdc
, x
--, y
+3); y
++;
99 MoveToEx (hdc
, x
, y
, NULL
);
100 LineTo (hdc
, x
, y
+1);
104 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
105 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
106 MoveToEx (hdc
, x
, y
, NULL
);
107 LineTo (hdc
, x
++, y
+5); y
++;
108 MoveToEx (hdc
, x
, y
, NULL
);
109 LineTo (hdc
, x
++, y
+3); y
++;
110 MoveToEx (hdc
, x
, y
, NULL
);
111 LineTo (hdc
, x
, y
+1);
114 SelectObject( hdc
, hOldPen
);
115 DeleteObject( hPen
);
118 /* the vertical arrows are:
128 PAGER_DrawVertArrow (HDC hdc
, RECT r
, INT colorRef
, BOOL up
)
133 w
= r
.right
- r
.left
+ 1;
134 h
= r
.bottom
- r
.top
+ 1;
135 if ((h
< MIN_ARROW_WIDTH
) || (w
< MIN_ARROW_HEIGHT
))
136 return; /* refuse to draw partial arrow */
138 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
139 hOldPen
= SelectObject ( hdc
, hPen
);
142 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
143 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 3;
144 MoveToEx (hdc
, x
, y
, NULL
);
145 LineTo (hdc
, x
+5, y
--); x
++;
146 MoveToEx (hdc
, x
, y
, NULL
);
147 LineTo (hdc
, x
+3, y
--); x
++;
148 MoveToEx (hdc
, x
, y
, NULL
);
149 LineTo (hdc
, x
+1, y
);
153 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
154 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
155 MoveToEx (hdc
, x
, y
, NULL
);
156 LineTo (hdc
, x
+5, y
++); x
++;
157 MoveToEx (hdc
, x
, y
, NULL
);
158 LineTo (hdc
, x
+3, y
++); x
++;
159 MoveToEx (hdc
, x
, y
, NULL
);
160 LineTo (hdc
, x
+1, y
);
163 SelectObject( hdc
, hOldPen
);
164 DeleteObject( hPen
);
168 PAGER_DrawButton(HDC hdc
, COLORREF clrBk
, RECT arrowRect
,
169 BOOL horz
, BOOL topLeft
, INT btnState
)
171 HBRUSH hBrush
, hOldBrush
;
174 if (!btnState
) /* PGF_INVISIBLE */
177 if ((rc
.right
- rc
.left
<= 0) || (rc
.bottom
- rc
.top
<= 0))
180 hBrush
= CreateSolidBrush(clrBk
);
181 hOldBrush
= (HBRUSH
)SelectObject(hdc
, hBrush
);
183 FillRect(hdc
, &rc
, hBrush
);
185 if (btnState
== PGF_HOT
)
187 DrawEdge( hdc
, &rc
, BDR_RAISEDINNER
, BF_RECT
);
189 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
191 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
193 else if (btnState
== PGF_NORMAL
)
195 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
197 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
199 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
201 else if (btnState
== PGF_DEPRESSED
)
203 DrawEdge( hdc
, &rc
, BDR_SUNKENOUTER
, BF_RECT
);
205 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
207 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
209 else if (btnState
== PGF_GRAYED
)
211 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
214 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
215 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
216 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
220 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
221 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
222 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
226 SelectObject( hdc
, hOldBrush
);
227 DeleteObject(hBrush
);
230 static void PAGER_CaptureandTrack(PAGER_INFO
*infoPtr
, HWND hwnd
)
232 TRACKMOUSEEVENT trackinfo
;
234 TRACE("[%p] SetCapture\n", hwnd
);
236 infoPtr
->bCapture
= TRUE
;
238 trackinfo
.cbSize
= sizeof(TRACKMOUSEEVENT
);
239 trackinfo
.dwFlags
= TME_QUERY
;
240 trackinfo
.hwndTrack
= hwnd
;
241 trackinfo
.dwHoverTime
= HOVER_DEFAULT
;
243 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
244 _TrackMouseEvent(&trackinfo
);
246 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
247 if(!(trackinfo
.dwFlags
& TME_LEAVE
)) {
248 trackinfo
.dwFlags
= TME_LEAVE
; /* notify upon leaving */
250 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
251 /* and can properly deactivate the hot button */
252 _TrackMouseEvent(&trackinfo
);
257 /* << PAGER_GetDropTarget >> */
259 static inline LRESULT
260 PAGER_ForwardMouse (HWND hwnd
, WPARAM wParam
)
262 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
263 TRACE("[%p]\n", hwnd
);
265 infoPtr
->bForward
= (BOOL
)wParam
;
270 static inline LRESULT
271 PAGER_GetButtonState (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
273 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
274 LRESULT btnState
= PGF_INVISIBLE
;
275 INT btn
= (INT
)lParam
;
276 TRACE("[%p]\n", hwnd
);
278 if (btn
== PGB_TOPORLEFT
)
279 btnState
= infoPtr
->TLbtnState
;
280 else if (btn
== PGB_BOTTOMORRIGHT
)
281 btnState
= infoPtr
->BRbtnState
;
287 static inline LRESULT
288 PAGER_GetPos(HWND hwnd
)
290 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
291 TRACE("[%p] returns %d\n", hwnd
, infoPtr
->nPos
);
292 return (LRESULT
)infoPtr
->nPos
;
295 static inline LRESULT
296 PAGER_GetButtonSize(HWND hwnd
)
298 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
299 TRACE("[%p] returns %d\n", hwnd
, infoPtr
->nButtonSize
);
300 return (LRESULT
)infoPtr
->nButtonSize
;
303 static inline LRESULT
304 PAGER_GetBorder(HWND hwnd
)
306 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
307 TRACE("[%p] returns %d\n", hwnd
, infoPtr
->nBorder
);
308 return (LRESULT
)infoPtr
->nBorder
;
311 static inline LRESULT
312 PAGER_GetBkColor(HWND hwnd
)
314 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
315 TRACE("[%p] returns %06lx\n", hwnd
, infoPtr
->clrBk
);
316 return (LRESULT
)infoPtr
->clrBk
;
320 PAGER_CalcSize (HWND hwnd
, INT
* size
, BOOL getWidth
)
323 ZeroMemory (&nmpgcs
, sizeof (NMPGCALCSIZE
));
324 nmpgcs
.hdr
.hwndFrom
= hwnd
;
325 nmpgcs
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
326 nmpgcs
.hdr
.code
= PGN_CALCSIZE
;
327 nmpgcs
.dwFlag
= getWidth
? PGF_CALCWIDTH
: PGF_CALCHEIGHT
;
328 nmpgcs
.iWidth
= getWidth
? *size
: 0;
329 nmpgcs
.iHeight
= getWidth
? 0 : *size
;
330 SendMessageA (GetParent (hwnd
), WM_NOTIFY
,
331 (WPARAM
)nmpgcs
.hdr
.idFrom
, (LPARAM
)&nmpgcs
);
333 *size
= getWidth
? nmpgcs
.iWidth
: nmpgcs
.iHeight
;
335 TRACE("[%p] PGN_CALCSIZE returns %s=%d\n", hwnd
,
336 getWidth
? "width" : "height", *size
);
340 PAGER_PositionChildWnd(HWND hwnd
, PAGER_INFO
* infoPtr
)
342 if (infoPtr
->hwndChild
)
345 int nPos
= infoPtr
->nPos
;
347 /* compensate for a grayed btn, which will soon become invisible */
348 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
349 nPos
+= infoPtr
->nButtonSize
;
351 GetClientRect(hwnd
, &rcClient
);
353 if (PAGER_IsHorizontal(hwnd
))
355 int wndSize
= max(0, rcClient
.right
- rcClient
.left
);
356 if (infoPtr
->nWidth
< wndSize
)
357 infoPtr
->nWidth
= wndSize
;
359 TRACE("[%p] SWP %dx%d at (%d,%d)\n", hwnd
,
360 infoPtr
->nWidth
, infoPtr
->nHeight
,
362 SetWindowPos(infoPtr
->hwndChild
, 0,
364 infoPtr
->nWidth
, infoPtr
->nHeight
,
369 int wndSize
= max(0, rcClient
.bottom
- rcClient
.top
);
370 if (infoPtr
->nHeight
< wndSize
)
371 infoPtr
->nHeight
= wndSize
;
373 TRACE("[%p] SWP %dx%d at (%d,%d)\n", hwnd
,
374 infoPtr
->nWidth
, infoPtr
->nHeight
,
376 SetWindowPos(infoPtr
->hwndChild
, 0,
378 infoPtr
->nWidth
, infoPtr
->nHeight
,
382 InvalidateRect(infoPtr
->hwndChild
, NULL
, TRUE
);
387 PAGER_GetScrollRange(HWND hwnd
, PAGER_INFO
* infoPtr
)
391 if (infoPtr
->hwndChild
)
393 INT wndSize
, childSize
;
395 GetWindowRect(hwnd
, &wndRect
);
397 if (PAGER_IsHorizontal(hwnd
))
399 wndSize
= wndRect
.right
- wndRect
.left
;
400 PAGER_CalcSize(hwnd
, &infoPtr
->nWidth
, TRUE
);
401 childSize
= infoPtr
->nWidth
;
405 wndSize
= wndRect
.bottom
- wndRect
.top
;
406 PAGER_CalcSize(hwnd
, &infoPtr
->nHeight
, FALSE
);
407 childSize
= infoPtr
->nHeight
;
410 TRACE("childSize = %d, wndSize = %d\n", childSize
, wndSize
);
411 if (childSize
> wndSize
)
412 scrollRange
= childSize
- wndSize
+ infoPtr
->nButtonSize
;
415 TRACE("[%p] returns %d\n", hwnd
, scrollRange
);
420 PAGER_GrayAndRestoreBtns(PAGER_INFO
* infoPtr
, INT scrollRange
,
421 BOOL
* needsResize
, BOOL
* needsRepaint
)
423 if (infoPtr
->nPos
> 0)
425 *needsResize
|= !infoPtr
->TLbtnState
; /* PGF_INVISIBLE */
426 if (infoPtr
->TLbtnState
!= PGF_DEPRESSED
)
427 infoPtr
->TLbtnState
= PGF_NORMAL
;
431 *needsRepaint
|= (infoPtr
->TLbtnState
!= PGF_GRAYED
);
432 infoPtr
->TLbtnState
= PGF_GRAYED
;
435 if (scrollRange
<= 0)
437 *needsRepaint
|= (infoPtr
->TLbtnState
!= PGF_GRAYED
);
438 infoPtr
->TLbtnState
= PGF_GRAYED
;
439 *needsRepaint
|= (infoPtr
->BRbtnState
!= PGF_GRAYED
);
440 infoPtr
->BRbtnState
= PGF_GRAYED
;
442 else if (infoPtr
->nPos
< scrollRange
)
444 *needsResize
|= !infoPtr
->BRbtnState
; /* PGF_INVISIBLE */
445 if (infoPtr
->BRbtnState
!= PGF_DEPRESSED
)
446 infoPtr
->BRbtnState
= PGF_NORMAL
;
450 *needsRepaint
|= (infoPtr
->BRbtnState
!= PGF_GRAYED
);
451 infoPtr
->BRbtnState
= PGF_GRAYED
;
457 PAGER_NormalizeBtns(PAGER_INFO
* infoPtr
, BOOL
* needsRepaint
)
459 if (infoPtr
->TLbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
461 infoPtr
->TLbtnState
= PGF_NORMAL
;
462 *needsRepaint
= TRUE
;
465 if (infoPtr
->BRbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
467 infoPtr
->BRbtnState
= PGF_NORMAL
;
468 *needsRepaint
= TRUE
;
473 PAGER_HideGrayBtns(PAGER_INFO
* infoPtr
, BOOL
* needsResize
)
475 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
477 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
481 if (infoPtr
->BRbtnState
== PGF_GRAYED
)
483 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
489 PAGER_UpdateBtns(HWND hwnd
, PAGER_INFO
*infoPtr
,
490 INT scrollRange
, BOOL hideGrayBtns
)
492 BOOL resizeClient
= FALSE
;
493 BOOL repaintBtns
= FALSE
;
496 PAGER_NormalizeBtns(infoPtr
, &repaintBtns
);
498 PAGER_GrayAndRestoreBtns(infoPtr
, scrollRange
, &resizeClient
, &repaintBtns
);
501 PAGER_HideGrayBtns(infoPtr
, &resizeClient
);
503 if (resizeClient
) /* initiate NCCalcSize to resize client wnd */ {
504 SetWindowPos(hwnd
, 0,0,0,0,0,
505 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
506 SWP_NOZORDER
| SWP_NOACTIVATE
);
510 SendMessageA(hwnd
, WM_NCPAINT
, 0, 0);
514 PAGER_SetPos(HWND hwnd
, INT newPos
, BOOL fromBtnPress
)
516 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
517 INT scrollRange
= PAGER_GetScrollRange(hwnd
, infoPtr
);
518 INT oldPos
= infoPtr
->nPos
;
520 if ((scrollRange
<= 0) || (newPos
< 0))
522 else if (newPos
> scrollRange
)
523 infoPtr
->nPos
= scrollRange
;
525 infoPtr
->nPos
= newPos
;
527 TRACE("[%p] pos=%d, oldpos=%d\n", hwnd
, infoPtr
->nPos
, oldPos
);
529 if (infoPtr
->nPos
!= oldPos
)
531 /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
532 PAGER_UpdateBtns(hwnd
, infoPtr
, scrollRange
, !fromBtnPress
);
533 PAGER_PositionChildWnd(hwnd
, infoPtr
);
540 PAGER_HandleWindowPosChanging(HWND hwnd
, WPARAM wParam
, WINDOWPOS
*winpos
)
542 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
544 if (infoPtr
->bNoResize
&& !(winpos
->flags
& SWP_NOSIZE
))
546 /* don't let the app resize the nonscrollable dimension of a control
547 * that was created with CCS_NORESIZE style
548 * (i.e. height for a horizontal pager, or width for a vertical one) */
550 /* except if the current dimension is 0 and app is setting for
551 * first time, then save amount as dimension. - GA 8/01 */
553 if (PAGER_IsHorizontal(hwnd
))
554 if (!infoPtr
->nHeight
&& winpos
->cy
)
555 infoPtr
->nHeight
= winpos
->cy
;
557 winpos
->cy
= infoPtr
->nHeight
;
559 if (!infoPtr
->nWidth
&& winpos
->cx
)
560 infoPtr
->nWidth
= winpos
->cx
;
562 winpos
->cx
= infoPtr
->nWidth
;
566 DefWindowProcA (hwnd
, WM_WINDOWPOSCHANGING
, wParam
, (LPARAM
)winpos
);
572 PAGER_SetFixedWidth(HWND hwnd
, PAGER_INFO
* infoPtr
)
574 /* Must set the non-scrollable dimension to be less than the full height/width
575 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
576 * size, and experimentation shows that affect is almost right. */
580 GetWindowRect(hwnd
, &wndRect
);
582 /* see what the app says for btn width */
583 PAGER_CalcSize(hwnd
, &infoPtr
->nWidth
, TRUE
);
585 if (infoPtr
->bNoResize
)
587 delta
= wndRect
.right
- wndRect
.left
- infoPtr
->nWidth
;
588 if (delta
> infoPtr
->nButtonSize
)
589 infoPtr
->nWidth
+= 4 * infoPtr
->nButtonSize
/ 3;
591 infoPtr
->nWidth
+= infoPtr
->nButtonSize
/ 3;
594 h
= wndRect
.bottom
- wndRect
.top
+ infoPtr
->nButtonSize
;
596 TRACE("[%p] infoPtr->nWidth set to %d\n",
597 hwnd
, infoPtr
->nWidth
);
603 PAGER_SetFixedHeight(HWND hwnd
, PAGER_INFO
* infoPtr
)
605 /* Must set the non-scrollable dimension to be less than the full height/width
606 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
607 * size, and experimentation shows that affect is almost right. */
611 GetWindowRect(hwnd
, &wndRect
);
613 /* see what the app says for btn height */
614 PAGER_CalcSize(hwnd
, &infoPtr
->nHeight
, FALSE
);
616 if (infoPtr
->bNoResize
)
618 delta
= wndRect
.bottom
- wndRect
.top
- infoPtr
->nHeight
;
619 if (delta
> infoPtr
->nButtonSize
)
620 infoPtr
->nHeight
+= infoPtr
->nButtonSize
;
622 infoPtr
->nHeight
+= infoPtr
->nButtonSize
/ 3;
625 w
= wndRect
.right
- wndRect
.left
+ infoPtr
->nButtonSize
;
627 TRACE("[%p] infoPtr->nHeight set to %d\n",
628 hwnd
, infoPtr
->nHeight
);
633 /******************************************************************
634 * For the PGM_RECALCSIZE message (but not the other uses in *
635 * this module), the native control does only the following: *
637 * if (some condition) *
638 * PostMessageA(hwnd, EM_FMTLINES, 0, 0); *
639 * return DefWindowProcA(hwnd, PGM_RECALCSIZE, 0, 0); *
641 * When we figure out what the "some condition" is we will *
642 * implement that for the message processing. *
643 ******************************************************************/
646 PAGER_RecalcSize(HWND hwnd
)
648 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
650 TRACE("[%p]\n", hwnd
);
652 if (infoPtr
->hwndChild
)
654 INT scrollRange
= PAGER_GetScrollRange(hwnd
, infoPtr
);
656 if (scrollRange
<= 0)
659 PAGER_SetPos(hwnd
, 0, FALSE
);
663 PAGER_UpdateBtns(hwnd
, infoPtr
, scrollRange
, TRUE
);
664 PAGER_PositionChildWnd(hwnd
, infoPtr
);
673 PAGER_SetBkColor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
675 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
676 COLORREF clrTemp
= infoPtr
->clrBk
;
678 infoPtr
->clrBk
= (COLORREF
)lParam
;
679 TRACE("[%p] %06lx\n", hwnd
, infoPtr
->clrBk
);
681 /* the native control seems to do things this way */
682 SetWindowPos(hwnd
, 0,0,0,0,0,
683 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
684 SWP_NOZORDER
| SWP_NOACTIVATE
);
686 RedrawWindow(hwnd
, 0, 0, RDW_ERASE
| RDW_INVALIDATE
);
688 return (LRESULT
)clrTemp
;
693 PAGER_SetBorder (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
695 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
696 INT nTemp
= infoPtr
->nBorder
;
698 infoPtr
->nBorder
= (INT
)lParam
;
699 TRACE("[%p] %d\n", hwnd
, infoPtr
->nBorder
);
701 PAGER_RecalcSize(hwnd
);
703 return (LRESULT
)nTemp
;
708 PAGER_SetButtonSize (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
710 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
711 INT nTemp
= infoPtr
->nButtonSize
;
713 infoPtr
->nButtonSize
= (INT
)lParam
;
714 TRACE("[%p] %d\n", hwnd
, infoPtr
->nButtonSize
);
716 PAGER_RecalcSize(hwnd
);
718 return (LRESULT
)nTemp
;
723 PAGER_SetChild (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
725 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
728 infoPtr
->hwndChild
= IsWindow ((HWND
)lParam
) ? (HWND
)lParam
: 0;
730 if (infoPtr
->hwndChild
)
732 TRACE("[%p] hwndChild=%p\n", hwnd
, infoPtr
->hwndChild
);
734 if (PAGER_IsHorizontal(hwnd
)) {
735 hw
= PAGER_SetFixedHeight(hwnd
, infoPtr
);
736 /* adjust non-scrollable dimension to fit the child */
737 SetWindowPos(hwnd
, 0, 0,0, hw
, infoPtr
->nHeight
,
738 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
739 SWP_NOSIZE
| SWP_NOACTIVATE
);
742 hw
= PAGER_SetFixedWidth(hwnd
, infoPtr
);
743 /* adjust non-scrollable dimension to fit the child */
744 SetWindowPos(hwnd
, 0, 0,0, infoPtr
->nWidth
, hw
,
745 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
746 SWP_NOSIZE
| SWP_NOACTIVATE
);
749 /* position child within the page scroller */
750 SetWindowPos(infoPtr
->hwndChild
, HWND_TOP
,
752 SWP_SHOWWINDOW
| SWP_NOSIZE
); /* native is 0 */
755 PAGER_SetPos(hwnd
, 0, FALSE
);
762 PAGER_Scroll(HWND hwnd
, INT dir
)
764 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
765 NMPGSCROLL nmpgScroll
;
768 if (infoPtr
->hwndChild
)
770 ZeroMemory (&nmpgScroll
, sizeof (NMPGSCROLL
));
771 nmpgScroll
.hdr
.hwndFrom
= hwnd
;
772 nmpgScroll
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
773 nmpgScroll
.hdr
.code
= PGN_SCROLL
;
775 GetWindowRect(hwnd
, &rcWnd
);
776 GetClientRect(hwnd
, &nmpgScroll
.rcParent
);
777 nmpgScroll
.iXpos
= nmpgScroll
.iYpos
= 0;
778 nmpgScroll
.iDir
= dir
;
780 if (PAGER_IsHorizontal(hwnd
))
782 nmpgScroll
.iScroll
= rcWnd
.right
- rcWnd
.left
;
783 nmpgScroll
.iXpos
= infoPtr
->nPos
;
787 nmpgScroll
.iScroll
= rcWnd
.bottom
- rcWnd
.top
;
788 nmpgScroll
.iYpos
= infoPtr
->nPos
;
790 nmpgScroll
.iScroll
-= 2*infoPtr
->nButtonSize
;
792 SendMessageA (GetParent(hwnd
), WM_NOTIFY
,
793 (WPARAM
)nmpgScroll
.hdr
.idFrom
, (LPARAM
)&nmpgScroll
);
795 TRACE("[%p] PGN_SCROLL returns iScroll=%d\n", hwnd
, nmpgScroll
.iScroll
);
797 if (nmpgScroll
.iScroll
> 0)
799 infoPtr
->direction
= dir
;
801 if (dir
== PGF_SCROLLLEFT
|| dir
== PGF_SCROLLUP
)
802 PAGER_SetPos(hwnd
, infoPtr
->nPos
- nmpgScroll
.iScroll
, TRUE
);
804 PAGER_SetPos(hwnd
, infoPtr
->nPos
+ nmpgScroll
.iScroll
, TRUE
);
807 infoPtr
->direction
= -1;
812 PAGER_FmtLines(HWND hwnd
)
814 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
816 /* initiate NCCalcSize to resize client wnd and get size */
817 SetWindowPos(hwnd
, 0, 0,0,0,0,
818 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
819 SWP_NOZORDER
| SWP_NOACTIVATE
);
821 SetWindowPos(infoPtr
->hwndChild
, 0,
822 0,0,infoPtr
->nWidth
,infoPtr
->nHeight
,
825 return DefWindowProcA (hwnd
, EM_FMTLINES
, 0, 0);
829 PAGER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
832 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
834 /* allocate memory for info structure */
835 infoPtr
= (PAGER_INFO
*)COMCTL32_Alloc (sizeof(PAGER_INFO
));
836 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
838 /* set default settings */
839 infoPtr
->hwndChild
= (HWND
)NULL
;
840 infoPtr
->bNoResize
= dwStyle
& CCS_NORESIZE
;
841 infoPtr
->clrBk
= GetSysColor(COLOR_BTNFACE
);
842 infoPtr
->nBorder
= 0;
843 infoPtr
->nButtonSize
= 12;
846 infoPtr
->nHeight
= 0;
847 infoPtr
->bForward
= FALSE
;
848 infoPtr
->bCapture
= FALSE
;
849 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
850 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
851 infoPtr
->direction
= -1;
853 if (dwStyle
& PGS_DRAGNDROP
)
854 FIXME("[%p] Drag and Drop style is not implemented yet.\n", hwnd
);
856 * If neither horizontal nor vertical style specified, default to vertical.
857 * This is probably not necessary, since the style may be set later on as
858 * the control is initialized, but just in case it isn't, set it here.
860 if (!(dwStyle
& PGS_HORZ
) && !(dwStyle
& PGS_VERT
))
863 SetWindowLongA(hwnd
, GWL_STYLE
, dwStyle
);
871 PAGER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
873 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
874 /* free pager info data */
875 COMCTL32_Free (infoPtr
);
876 SetWindowLongA (hwnd
, 0, 0);
881 PAGER_NCCalcSize(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
883 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
884 LPRECT lpRect
= (LPRECT
)lParam
;
885 RECT rcChildw
, rcmyw
, wnrc
, ltrc
, rbrc
;
887 BOOL resizeClient
= FALSE
;
888 BOOL repaintBtns
= FALSE
;
892 * lParam points to a RECT struct. On entry, the struct
893 * contains the proposed wnd rectangle for the window.
894 * On exit, the struct should contain the screen
895 * coordinates of the corresponding window's client area.
898 DefWindowProcA (hwnd
, WM_NCCALCSIZE
, wParam
, lParam
);
900 TRACE("orig rect=(%d,%d)-(%d,%d)\n",
901 lpRect
->left
, lpRect
->top
, lpRect
->right
, lpRect
->bottom
);
903 if (PAGER_IsHorizontal(hwnd
))
905 infoPtr
->nWidth
= lpRect
->right
- lpRect
->left
;
906 PAGER_CalcSize (hwnd
, &infoPtr
->nWidth
, TRUE
);
907 GetWindowRect (infoPtr
->hwndChild
, &rcChildw
);
908 MapWindowPoints (0, hwnd
, (LPPOINT
)&rcChildw
, 2);
909 GetCursorPos (&cursor
);
910 GetWindowRect (hwnd
, &rcmyw
);
912 /* Reset buttons and hide any grey ones */
913 scrollRange
= infoPtr
->nWidth
- (rcmyw
.right
- rcmyw
.left
);
915 TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%d,%d)-(%d,%d), cursor=(%ld,%ld)\n",
916 infoPtr
->nPos
, scrollRange
, infoPtr
->nHeight
,
917 rcmyw
.left
, rcmyw
.top
,
918 rcmyw
.right
, rcmyw
.bottom
,
920 PAGER_GrayAndRestoreBtns(infoPtr
, scrollRange
, &resizeClient
, &repaintBtns
);
921 PAGER_HideGrayBtns(infoPtr
, &resizeClient
);
923 if (PtInRect (&rcmyw
, cursor
)) {
924 GetWindowRect (hwnd
, &wnrc
);
926 ltrc
.right
= ltrc
.left
+ infoPtr
->nButtonSize
;
928 rbrc
.left
= rbrc
.right
- infoPtr
->nButtonSize
;
929 TRACE("horz lt rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
930 ltrc
.left
, ltrc
.top
, ltrc
.right
, ltrc
.bottom
,
931 rbrc
.left
, rbrc
.top
, rbrc
.right
, rbrc
.bottom
);
932 if (PtInRect (<rc
, cursor
) && infoPtr
->TLbtnState
)
933 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
934 if (PtInRect (&rbrc
, cursor
) && infoPtr
->BRbtnState
)
935 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
937 if (infoPtr
->TLbtnState
&& (lpRect
->left
+ infoPtr
->nButtonSize
< lpRect
->right
))
938 lpRect
->left
+= infoPtr
->nButtonSize
;
939 if (infoPtr
->BRbtnState
&& (lpRect
->right
- infoPtr
->nButtonSize
> lpRect
->left
))
940 lpRect
->right
-= infoPtr
->nButtonSize
;
944 /* native does: (from trace of IE4 opening "Favorites" frame)
946 * WM_NOITFY PGN_CALCSIZE w/ dwFlag=2
947 * GetWindowRect (child, &rc)
948 * MapWindowPoints (0, syspager, &rc, 2)
949 * GetCursorPos( &cur )
950 * GetWindowRect (syspager, &rc2)
951 * PtInRect (&rc2, cur.x, cur.y) rtns 0
952 * returns with rect empty
954 infoPtr
->nHeight
= lpRect
->bottom
- lpRect
->top
;
955 PAGER_CalcSize (hwnd
, &infoPtr
->nHeight
, FALSE
);
956 GetWindowRect (infoPtr
->hwndChild
, &rcChildw
);
957 MapWindowPoints (0, hwnd
, (LPPOINT
)&rcChildw
, 2);
958 GetCursorPos (&cursor
);
959 GetWindowRect (hwnd
, &rcmyw
);
961 /* Reset buttons and hide any grey ones */
962 scrollRange
= infoPtr
->nHeight
- (rcmyw
.bottom
- rcmyw
.top
);
964 TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%d,%d)-(%d,%d), cursor=(%ld,%ld)\n",
965 infoPtr
->nPos
, scrollRange
, infoPtr
->nHeight
,
966 rcmyw
.left
, rcmyw
.top
,
967 rcmyw
.right
, rcmyw
.bottom
,
969 PAGER_GrayAndRestoreBtns(infoPtr
, scrollRange
, &resizeClient
, &repaintBtns
);
970 PAGER_HideGrayBtns(infoPtr
, &resizeClient
);
972 if (PtInRect (&rcmyw
, cursor
)) {
975 * GetWindowRect(pager, &rc)
976 * PtInRect(btn-left????, cur.x, cur.y)
978 * PtInRect(btn-right????, cur.x, cur.y)
980 * RedrawWindow(pager, 0, 0, 5)
984 GetWindowRect (hwnd
, &wnrc
);
986 ltrc
.right
= ltrc
.left
+ infoPtr
->nButtonSize
;
988 rbrc
.left
= rbrc
.right
- infoPtr
->nButtonSize
;
989 TRACE("vert lt rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
990 ltrc
.left
, ltrc
.top
, ltrc
.right
, ltrc
.bottom
,
991 rbrc
.left
, rbrc
.top
, rbrc
.right
, rbrc
.bottom
);
992 if (PtInRect (<rc
, cursor
) && infoPtr
->TLbtnState
)
993 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
994 if (PtInRect (&rbrc
, cursor
) && infoPtr
->BRbtnState
)
995 RedrawWindow (hwnd
, 0, 0, RDW_INVALIDATE
| RDW_ERASE
);
997 if (infoPtr
->TLbtnState
&& (lpRect
->top
+ infoPtr
->nButtonSize
< lpRect
->bottom
))
998 lpRect
->top
+= infoPtr
->nButtonSize
;
999 if (infoPtr
->BRbtnState
&& (lpRect
->bottom
- infoPtr
->nButtonSize
> lpRect
->top
))
1000 lpRect
->bottom
-= infoPtr
->nButtonSize
;
1002 if ((lpRect
->bottom
< 0) || (lpRect
->bottom
> infoPtr
->nHeight
))
1003 lpRect
->bottom
= infoPtr
->nHeight
;
1006 TRACE("[%p] client rect set to %dx%d at (%d,%d) BtnState[%d,%d]\n",
1007 hwnd
, lpRect
->right
-lpRect
->left
, lpRect
->bottom
-lpRect
->top
,
1008 lpRect
->left
, lpRect
->top
,
1009 infoPtr
->TLbtnState
, infoPtr
->BRbtnState
);
1015 PAGER_NCPaint (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1017 PAGER_INFO
* infoPtr
= PAGER_GetInfoPtr(hwnd
);
1018 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1019 RECT rcWindow
, rcBottomRight
, rcTopLeft
;
1021 BOOL bHorizontal
= PAGER_IsHorizontal(hwnd
);
1023 if (dwStyle
& WS_MINIMIZE
)
1026 DefWindowProcA (hwnd
, WM_NCPAINT
, wParam
, lParam
);
1028 if (!(hdc
= GetDCEx (hwnd
, 0, DCX_USESTYLE
| DCX_WINDOW
)))
1031 GetWindowRect (hwnd
, &rcWindow
);
1032 OffsetRect (&rcWindow
, -rcWindow
.left
, -rcWindow
.top
);
1034 rcTopLeft
= rcBottomRight
= rcWindow
;
1037 rcTopLeft
.right
= rcTopLeft
.left
+ infoPtr
->nButtonSize
;
1038 rcBottomRight
.left
= rcBottomRight
.right
- infoPtr
->nButtonSize
;
1042 rcTopLeft
.bottom
= rcTopLeft
.top
+ infoPtr
->nButtonSize
;
1043 rcBottomRight
.top
= rcBottomRight
.bottom
- infoPtr
->nButtonSize
;
1046 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcTopLeft
,
1047 bHorizontal
, TRUE
, infoPtr
->TLbtnState
);
1048 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcBottomRight
,
1049 bHorizontal
, FALSE
, infoPtr
->BRbtnState
);
1051 ReleaseDC( hwnd
, hdc
);
1056 PAGER_HitTest (HWND hwnd
, LPPOINT pt
)
1058 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1060 BOOL bHorizontal
= PAGER_IsHorizontal(hwnd
);
1062 GetClientRect (hwnd
, &clientRect
);
1064 if (PtInRect(&clientRect
, *pt
))
1066 TRACE("HTCLIENT\n");
1070 if (infoPtr
->TLbtnState
&& infoPtr
->TLbtnState
!= PGF_GRAYED
)
1074 if (pt
->x
< clientRect
.left
)
1082 if (pt
->y
< clientRect
.top
)
1090 if (infoPtr
->BRbtnState
&& infoPtr
->BRbtnState
!= PGF_GRAYED
)
1094 if (pt
->x
> clientRect
.right
)
1102 if (pt
->y
> clientRect
.bottom
)
1104 TRACE("HTBOTTOM\n");
1110 TRACE("HTNOWHERE\n");
1115 PAGER_NCHitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1119 pt
.x
= SLOWORD(lParam
);
1120 pt
.y
= SHIWORD(lParam
);
1122 ScreenToClient (hwnd
, &pt
);
1123 return PAGER_HitTest(hwnd
, &pt
);
1127 PAGER_SetCursor( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1129 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1130 BOOL notCaptured
= FALSE
;
1132 switch(LOWORD(lParam
))
1136 if ((notCaptured
= infoPtr
->TLbtnState
!= PGF_HOT
))
1137 infoPtr
->TLbtnState
= PGF_HOT
;
1141 if ((notCaptured
= infoPtr
->BRbtnState
!= PGF_HOT
))
1142 infoPtr
->BRbtnState
= PGF_HOT
;
1150 PAGER_CaptureandTrack(infoPtr
, hwnd
);
1152 SendMessageA(hwnd
, WM_NCPAINT
, 0, 0);
1159 PAGER_MouseLeave (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1161 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1163 KillTimer (hwnd
, TIMERID1
);
1164 KillTimer (hwnd
, TIMERID2
);
1166 TRACE("[%p] ReleaseCapture\n", hwnd
);
1168 infoPtr
->bCapture
= FALSE
;
1170 /* Notify parent of released mouse capture */
1173 ZeroMemory (&nmhdr
, sizeof (NMHDR
));
1174 nmhdr
.hwndFrom
= hwnd
;
1175 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
1176 nmhdr
.code
= NM_RELEASEDCAPTURE
;
1177 SendMessageA (GetParent(hwnd
), WM_NOTIFY
,
1178 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1181 /* make HOT btns NORMAL and hide gray btns */
1182 PAGER_UpdateBtns(hwnd
, infoPtr
, -1, TRUE
);
1188 PAGER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1190 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1192 RECT wnrect
, TLbtnrect
, BRbtnrect
, *btnrect
= NULL
;
1193 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1194 BOOL topLeft
= FALSE
;
1199 pt
.x
= SLOWORD(lParam
);
1200 pt
.y
= SHIWORD(lParam
);
1202 TRACE("[%p] to (%ld,%ld)\n", hwnd
, pt
.x
, pt
.y
);
1203 ClientToScreen(hwnd
, &pt
);
1204 GetWindowRect(hwnd
, &wnrect
);
1205 if (PtInRect(&wnrect
, pt
)) {
1208 if (dwStyle
& PGS_HORZ
) {
1209 TLbtnrect
.right
= TLbtnrect
.left
+ infoPtr
->nButtonSize
;
1210 BRbtnrect
.left
= BRbtnrect
.right
- infoPtr
->nButtonSize
;
1213 TLbtnrect
.bottom
= TLbtnrect
.top
+ infoPtr
->nButtonSize
;
1214 BRbtnrect
.top
= BRbtnrect
.bottom
- infoPtr
->nButtonSize
;
1218 MapWindowPoints(0, hwnd
, &clpt
, 1);
1219 hit
= PAGER_HitTest(hwnd
, &clpt
);
1220 if (hit
== HTLEFT
|| hit
== HTTOP
) {
1222 btnrect
= &TLbtnrect
;
1223 infoPtr
->TLbtnState
= PGF_DEPRESSED
;
1224 btnstate
= infoPtr
->TLbtnState
;
1226 else if (hit
== HTRIGHT
|| hit
== HTBOTTOM
) {
1228 btnrect
= &BRbtnrect
;
1229 infoPtr
->BRbtnState
= PGF_DEPRESSED
;
1230 btnstate
= infoPtr
->BRbtnState
;
1233 /* If in one of the buttons the capture and draw buttons */
1235 TRACE("[%p] draw btn (%d,%d)-(%d,%d), Capture %s, style %08lx\n",
1236 hwnd
, btnrect
->left
, btnrect
->top
,
1237 btnrect
->right
, btnrect
->bottom
,
1238 (infoPtr
->bCapture
) ? "TRUE" : "FALSE",
1240 if (!infoPtr
->bCapture
)
1241 PAGER_CaptureandTrack(infoPtr
, hwnd
);
1242 if (dwStyle
& PGS_AUTOSCROLL
)
1243 SetTimer(hwnd
, TIMERID1
, 0x3e, 0);
1244 MapWindowPoints(0, hwnd
, (LPPOINT
)btnrect
, 2);
1245 hdc
= GetWindowDC(hwnd
);
1246 /* OffsetRect(wnrect, 0 | 1, 0 | 1) */
1247 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, *btnrect
,
1248 PAGER_IsHorizontal(hwnd
), topLeft
, btnstate
);
1249 ReleaseDC(hwnd
, hdc
);
1250 return DefWindowProcA (hwnd
, WM_MOUSEMOVE
, wParam
, lParam
);
1254 /* If we think we are captured, then do release */
1255 if (infoPtr
->bCapture
) {
1256 infoPtr
->bCapture
= FALSE
;
1258 if (GetCapture() == hwnd
) {
1260 /* Notify parent of released mouse capture */
1263 ZeroMemory (&nmhdr
, sizeof (NMHDR
));
1264 nmhdr
.hwndFrom
= hwnd
;
1265 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
1266 nmhdr
.code
= NM_RELEASEDCAPTURE
;
1267 SendMessageA (GetParent(hwnd
), WM_NOTIFY
,
1268 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1272 KillTimer(hwnd
, TIMERID1
);
1274 return DefWindowProcA (hwnd
, WM_MOUSEMOVE
, wParam
, lParam
);
1278 PAGER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1280 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1281 BOOL repaintBtns
= FALSE
;
1285 pt
.x
= SLOWORD(lParam
);
1286 pt
.y
= SHIWORD(lParam
);
1288 TRACE("[%p] at (%d,%d)\n", hwnd
, SLOWORD(lParam
), SHIWORD(lParam
));
1290 hit
= PAGER_HitTest(hwnd
, &pt
);
1292 /* put btn in DEPRESSED state */
1293 if (hit
== HTLEFT
|| hit
== HTTOP
)
1295 repaintBtns
= infoPtr
->TLbtnState
!= PGF_DEPRESSED
;
1296 infoPtr
->TLbtnState
= PGF_DEPRESSED
;
1297 SetTimer(hwnd
, TIMERID1
, INITIAL_DELAY
, 0);
1299 else if (hit
== HTRIGHT
|| hit
== HTBOTTOM
)
1301 repaintBtns
= infoPtr
->BRbtnState
!= PGF_DEPRESSED
;
1302 infoPtr
->BRbtnState
= PGF_DEPRESSED
;
1303 SetTimer(hwnd
, TIMERID1
, INITIAL_DELAY
, 0);
1307 SendMessageA(hwnd
, WM_NCPAINT
, 0, 0);
1312 TRACE("[%p] PGF_SCROLLLEFT\n", hwnd
);
1313 PAGER_Scroll(hwnd
, PGF_SCROLLLEFT
);
1316 TRACE("[%p] PGF_SCROLLUP\n", hwnd
);
1317 PAGER_Scroll(hwnd
, PGF_SCROLLUP
);
1320 TRACE("[%p] PGF_SCROLLRIGHT\n", hwnd
);
1321 PAGER_Scroll(hwnd
, PGF_SCROLLRIGHT
);
1324 TRACE("[%p] PGF_SCROLLDOWN\n", hwnd
);
1325 PAGER_Scroll(hwnd
, PGF_SCROLLDOWN
);
1335 PAGER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1337 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1338 TRACE("[%p]\n", hwnd
);
1340 KillTimer (hwnd
, TIMERID1
);
1341 KillTimer (hwnd
, TIMERID2
);
1343 /* make PRESSED btns NORMAL but don't hide gray btns */
1344 PAGER_UpdateBtns(hwnd
, infoPtr
, -1, FALSE
);
1350 PAGER_NCLButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1354 pt
.x
= SLOWORD(lParam
);
1355 pt
.y
= SHIWORD(lParam
);
1357 TRACE("[%p] at (%d,%d)\n", hwnd
, SLOWORD(lParam
), SHIWORD(lParam
));
1358 MapWindowPoints(0, hwnd
, &pt
, 1);
1359 lParam
= MAKELONG(pt
.x
, pt
.y
);
1360 return PAGER_LButtonDown (hwnd
, wParam
, lParam
);
1364 PAGER_Timer (HWND hwnd
, WPARAM wParam
)
1366 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1367 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1370 /* if initial timer, kill it and start the repeat timer */
1371 if (wParam
== TIMERID1
) {
1372 if (PAGER_IsHorizontal(hwnd
)) {
1373 dir
= (infoPtr
->TLbtnState
& PGF_DEPRESSED
) ?
1374 PGF_SCROLLLEFT
: PGF_SCROLLRIGHT
;
1377 dir
= (infoPtr
->TLbtnState
& PGF_DEPRESSED
) ?
1378 PGF_SCROLLUP
: PGF_SCROLLDOWN
;
1380 TRACE("[%p] TIMERID1: style=%08lx, dir=%d\n", hwnd
, dwStyle
, dir
);
1381 KillTimer(hwnd
, TIMERID1
);
1382 SetTimer(hwnd
, TIMERID1
, REPEAT_DELAY
, 0);
1383 if (dwStyle
& PGS_AUTOSCROLL
) {
1384 PAGER_Scroll(hwnd
, dir
);
1385 SetWindowPos(hwnd
, 0,0,0,0,0,
1386 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1387 SWP_NOZORDER
| SWP_NOACTIVATE
);
1393 TRACE("[%p] TIMERID2: dir=%d\n", hwnd
, infoPtr
->direction
);
1394 KillTimer(hwnd
, TIMERID2
);
1395 if (infoPtr
->direction
> 0) {
1396 PAGER_Scroll(hwnd
, infoPtr
->direction
);
1397 SetTimer(hwnd
, TIMERID2
, REPEAT_DELAY
, 0);
1403 PAGER_EraseBackground (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1406 HDC hdc
= (HDC
)wParam
;
1410 * parent = GetParent(pager)
1411 * pt.x=0; pt.y=0; ?????
1412 * MapWindowPoints(pager, parent, &pt, 1)
1413 * OffsetWindowOrgEx(hdc, pt.x, pt.y, &ptorg)
1414 * SendMessageA(parent, WM_ERASEBKGND, hdc, 0)
1415 * SetWindowOrgEx(hdc, 0, 0, 0)
1420 parent
= GetParent(hwnd
);
1421 MapWindowPoints(hwnd
, parent
, &pt
, 1);
1422 OffsetWindowOrgEx (hdc
, pt
.x
, pt
.y
, &ptorig
);
1423 SendMessageA (parent
, WM_ERASEBKGND
, wParam
, lParam
);
1424 SetWindowOrgEx (hdc
, ptorig
.x
, ptorig
.y
, 0);
1428 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1429 HBRUSH hBrush
= CreateSolidBrush(infoPtr
->clrBk
);
1432 GetClientRect (hwnd
, &rect
);
1433 FillRect ((HDC
)wParam
, &rect
, hBrush
);
1435 /* background color of the child should be the same as the pager */
1436 if (infoPtr
->hwndChild
)
1438 GetClientRect (infoPtr
->hwndChild
, &rect
);
1439 FillRect ((HDC
)wParam
, &rect
, hBrush
);
1442 DeleteObject (hBrush
);
1450 PAGER_Size (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1452 /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
1454 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1455 TRACE("[%p] %dx%d\n", hwnd
, SLOWORD(lParam
), SHIWORD(lParam
));
1457 if (PAGER_IsHorizontal(hwnd
))
1458 infoPtr
->nHeight
= SHIWORD(lParam
);
1460 infoPtr
->nWidth
= SLOWORD(lParam
);
1462 return PAGER_RecalcSize(hwnd
);
1466 static LRESULT WINAPI
1467 PAGER_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1469 PAGER_INFO
*infoPtr
= PAGER_GetInfoPtr (hwnd
);
1471 if (!infoPtr
&& (uMsg
!= WM_CREATE
))
1472 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
1477 return PAGER_FmtLines(hwnd
);
1479 case PGM_FORWARDMOUSE
:
1480 return PAGER_ForwardMouse (hwnd
, wParam
);
1482 case PGM_GETBKCOLOR
:
1483 return PAGER_GetBkColor(hwnd
);
1486 return PAGER_GetBorder(hwnd
);
1488 case PGM_GETBUTTONSIZE
:
1489 return PAGER_GetButtonSize(hwnd
);
1492 return PAGER_GetPos(hwnd
);
1494 case PGM_GETBUTTONSTATE
:
1495 return PAGER_GetButtonState (hwnd
, wParam
, lParam
);
1497 /* case PGM_GETDROPTARGET: */
1499 case PGM_RECALCSIZE
:
1500 return PAGER_RecalcSize(hwnd
);
1502 case PGM_SETBKCOLOR
:
1503 return PAGER_SetBkColor (hwnd
, wParam
, lParam
);
1506 return PAGER_SetBorder (hwnd
, wParam
, lParam
);
1508 case PGM_SETBUTTONSIZE
:
1509 return PAGER_SetButtonSize (hwnd
, wParam
, lParam
);
1512 return PAGER_SetChild (hwnd
, wParam
, lParam
);
1515 return PAGER_SetPos(hwnd
, (INT
)lParam
, FALSE
);
1518 return PAGER_Create (hwnd
, wParam
, lParam
);
1521 return PAGER_Destroy (hwnd
, wParam
, lParam
);
1524 return PAGER_Size (hwnd
, wParam
, lParam
);
1527 return PAGER_NCPaint (hwnd
, wParam
, lParam
);
1529 case WM_WINDOWPOSCHANGING
:
1530 return PAGER_HandleWindowPosChanging (hwnd
, wParam
, (WINDOWPOS
*)lParam
);
1533 return PAGER_NCCalcSize (hwnd
, wParam
, lParam
);
1536 return PAGER_NCHitTest (hwnd
, wParam
, lParam
);
1540 if (hwnd
== (HWND
)wParam
)
1541 return PAGER_SetCursor(hwnd
, wParam
, lParam
);
1542 else /* its for the child */
1547 if (infoPtr
->bForward
&& infoPtr
->hwndChild
)
1548 PostMessageA(infoPtr
->hwndChild
, WM_MOUSEMOVE
, wParam
, lParam
);
1549 return PAGER_MouseMove (hwnd
, wParam
, lParam
);
1552 return PAGER_MouseLeave (hwnd
, wParam
, lParam
);
1554 case WM_NCLBUTTONDOWN
:
1555 return PAGER_NCLButtonDown (hwnd
, wParam
, lParam
);
1557 case WM_LBUTTONDOWN
:
1558 return PAGER_LButtonDown (hwnd
, wParam
, lParam
);
1560 case WM_NCLBUTTONUP
:
1562 return PAGER_LButtonUp (hwnd
, wParam
, lParam
);
1565 return PAGER_EraseBackground (hwnd
, wParam
, lParam
);
1568 return PAGER_Paint (hwnd, wParam);
1571 return PAGER_Timer (hwnd
, wParam
);
1575 return SendMessageA (GetParent (hwnd
), uMsg
, wParam
, lParam
);
1578 return DefWindowProcA (hwnd
, uMsg
, wParam
, lParam
);
1586 PAGER_Register (void)
1590 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
1591 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
| CS_SAVEBITS
;
1592 wndClass
.lpfnWndProc
= (WNDPROC
)PAGER_WindowProc
;
1593 wndClass
.cbClsExtra
= 0;
1594 wndClass
.cbWndExtra
= sizeof(PAGER_INFO
*);
1595 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
1596 wndClass
.hbrBackground
= 0;
1597 wndClass
.lpszClassName
= WC_PAGESCROLLERA
;
1599 RegisterClassA (&wndClass
);
1604 PAGER_Unregister (void)
1606 UnregisterClassA (WC_PAGESCROLLERA
, (HINSTANCE
)NULL
);