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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * This code was audited for completeness against the documented features
23 * of Comctl32.dll version 6.0 on Sep. 18, 2004, by Robert Shearman.
25 * Unless otherwise noted, we believe this code to be complete, as per
26 * the specification mentioned above.
27 * If you discover missing features or bugs please note them below.
30 * Implement repetitive button press.
31 * Adjust arrow size relative to size of button.
32 * Allow border size changes.
38 * WM_PRINT and/or WM_PRINTCLIENT
41 * Tested primarily with the controlspy Pager application.
42 * Susan Farley (susan@codeweavers.com)
44 * IMPLEMENTATION NOTES:
45 * This control uses WM_NCPAINT instead of WM_PAINT to paint itself
46 * as we need to scroll a child window. In order to do this we move
47 * the child window in the control's client area, using the clipping
48 * region that is automatically set around the client area. As the
49 * entire client area now consists of the child window, we must
50 * allocate space (WM_NCCALCSIZE) for the buttons and draw them as
51 * a non-client area (WM_NCPAINT).
52 * Robert Shearman <rob@codeweavers.com>
64 #include "wine/debug.h"
66 WINE_DEFAULT_DEBUG_CHANNEL(pager
);
70 HWND hwndSelf
; /* handle of the control wnd */
71 HWND hwndChild
; /* handle of the contained wnd */
72 HWND hwndNotify
; /* handle of the parent wnd */
73 DWORD dwStyle
; /* styles for this control */
74 COLORREF clrBk
; /* background color */
75 INT nBorder
; /* border size for the control */
76 INT nButtonSize
;/* size of the pager btns */
77 INT nPos
; /* scroll position */
78 INT nWidth
; /* from child wnd's response to PGN_CALCSIZE */
79 INT nHeight
; /* from child wnd's response to PGN_CALCSIZE */
80 BOOL bForward
; /* forward WM_MOUSEMOVE msgs to the contained wnd */
81 BOOL bCapture
; /* we have captured the mouse */
82 INT TLbtnState
; /* state of top or left btn */
83 INT BRbtnState
; /* state of bottom or right btn */
84 INT direction
; /* direction of the scroll, (e.g. PGF_SCROLLUP) */
87 #define MIN_ARROW_WIDTH 8
88 #define MIN_ARROW_HEIGHT 5
92 #define INITIAL_DELAY 500
93 #define REPEAT_DELAY 50
96 PAGER_GetButtonRects(const PAGER_INFO
* infoPtr
, RECT
* prcTopLeft
, RECT
* prcBottomRight
, BOOL bClientCoords
)
99 GetWindowRect (infoPtr
->hwndSelf
, &rcWindow
);
102 MapWindowPoints( 0, infoPtr
->hwndSelf
, (POINT
*)&rcWindow
, 2 );
104 OffsetRect(&rcWindow
, -rcWindow
.left
, -rcWindow
.top
);
106 *prcTopLeft
= *prcBottomRight
= rcWindow
;
107 if (infoPtr
->dwStyle
& PGS_HORZ
)
109 prcTopLeft
->right
= prcTopLeft
->left
+ infoPtr
->nButtonSize
;
110 prcBottomRight
->left
= prcBottomRight
->right
- infoPtr
->nButtonSize
;
114 prcTopLeft
->bottom
= prcTopLeft
->top
+ infoPtr
->nButtonSize
;
115 prcBottomRight
->top
= prcBottomRight
->bottom
- infoPtr
->nButtonSize
;
119 /* the horizontal arrows are:
132 PAGER_DrawHorzArrow (HDC hdc
, RECT r
, INT colorRef
, BOOL left
)
137 w
= r
.right
- r
.left
+ 1;
138 h
= r
.bottom
- r
.top
+ 1;
139 if ((h
< MIN_ARROW_WIDTH
) || (w
< MIN_ARROW_HEIGHT
))
140 return; /* refuse to draw partial arrow */
142 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
143 hOldPen
= SelectObject ( hdc
, hPen
);
146 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 3;
147 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
148 MoveToEx (hdc
, x
, y
, NULL
);
149 LineTo (hdc
, x
--, y
+5); y
++;
150 MoveToEx (hdc
, x
, y
, NULL
);
151 LineTo (hdc
, x
--, y
+3); y
++;
152 MoveToEx (hdc
, x
, y
, NULL
);
153 LineTo (hdc
, x
, y
+1);
157 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
158 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
159 MoveToEx (hdc
, x
, y
, NULL
);
160 LineTo (hdc
, x
++, y
+5); y
++;
161 MoveToEx (hdc
, x
, y
, NULL
);
162 LineTo (hdc
, x
++, y
+3); y
++;
163 MoveToEx (hdc
, x
, y
, NULL
);
164 LineTo (hdc
, x
, y
+1);
167 SelectObject( hdc
, hOldPen
);
168 DeleteObject( hPen
);
171 /* the vertical arrows are:
181 PAGER_DrawVertArrow (HDC hdc
, RECT r
, INT colorRef
, BOOL up
)
186 w
= r
.right
- r
.left
+ 1;
187 h
= r
.bottom
- r
.top
+ 1;
188 if ((h
< MIN_ARROW_WIDTH
) || (w
< MIN_ARROW_HEIGHT
))
189 return; /* refuse to draw partial arrow */
191 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
192 hOldPen
= SelectObject ( hdc
, hPen
);
195 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
196 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 3;
197 MoveToEx (hdc
, x
, y
, NULL
);
198 LineTo (hdc
, x
+5, y
--); x
++;
199 MoveToEx (hdc
, x
, y
, NULL
);
200 LineTo (hdc
, x
+3, y
--); x
++;
201 MoveToEx (hdc
, x
, y
, NULL
);
202 LineTo (hdc
, x
+1, y
);
206 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
207 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
208 MoveToEx (hdc
, x
, y
, NULL
);
209 LineTo (hdc
, x
+5, y
++); x
++;
210 MoveToEx (hdc
, x
, y
, NULL
);
211 LineTo (hdc
, x
+3, y
++); x
++;
212 MoveToEx (hdc
, x
, y
, NULL
);
213 LineTo (hdc
, x
+1, y
);
216 SelectObject( hdc
, hOldPen
);
217 DeleteObject( hPen
);
221 PAGER_DrawButton(HDC hdc
, COLORREF clrBk
, RECT arrowRect
,
222 BOOL horz
, BOOL topLeft
, INT btnState
)
224 HBRUSH hBrush
, hOldBrush
;
227 TRACE("arrowRect = %s, btnState = %d\n", wine_dbgstr_rect(&arrowRect
), btnState
);
229 if (btnState
== PGF_INVISIBLE
)
232 if ((rc
.right
- rc
.left
<= 0) || (rc
.bottom
- rc
.top
<= 0))
235 hBrush
= CreateSolidBrush(clrBk
);
236 hOldBrush
= SelectObject(hdc
, hBrush
);
238 FillRect(hdc
, &rc
, hBrush
);
240 if (btnState
== PGF_HOT
)
242 DrawEdge( hdc
, &rc
, BDR_RAISEDINNER
, BF_RECT
);
244 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
246 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
248 else if (btnState
== PGF_NORMAL
)
250 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
252 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
254 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
256 else if (btnState
== PGF_DEPRESSED
)
258 DrawEdge( hdc
, &rc
, BDR_SUNKENOUTER
, BF_RECT
);
260 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
262 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
264 else if (btnState
== PGF_GRAYED
)
266 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
269 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
270 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
271 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
275 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
276 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
277 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
281 SelectObject( hdc
, hOldBrush
);
282 DeleteObject(hBrush
);
285 /* << PAGER_GetDropTarget >> */
287 static inline LRESULT
288 PAGER_ForwardMouse (PAGER_INFO
* infoPtr
, BOOL bFwd
)
290 TRACE("[%p]\n", infoPtr
->hwndSelf
);
292 infoPtr
->bForward
= bFwd
;
297 static inline LRESULT
298 PAGER_GetButtonState (const PAGER_INFO
* infoPtr
, INT btn
)
300 LRESULT btnState
= PGF_INVISIBLE
;
301 TRACE("[%p]\n", infoPtr
->hwndSelf
);
303 if (btn
== PGB_TOPORLEFT
)
304 btnState
= infoPtr
->TLbtnState
;
305 else if (btn
== PGB_BOTTOMORRIGHT
)
306 btnState
= infoPtr
->BRbtnState
;
313 PAGER_GetPos(const PAGER_INFO
*infoPtr
)
315 TRACE("[%p] returns %d\n", infoPtr
->hwndSelf
, infoPtr
->nPos
);
316 return infoPtr
->nPos
;
320 PAGER_GetButtonSize(const PAGER_INFO
*infoPtr
)
322 TRACE("[%p] returns %d\n", infoPtr
->hwndSelf
, infoPtr
->nButtonSize
);
323 return infoPtr
->nButtonSize
;
327 PAGER_GetBorder(const PAGER_INFO
*infoPtr
)
329 TRACE("[%p] returns %d\n", infoPtr
->hwndSelf
, infoPtr
->nBorder
);
330 return infoPtr
->nBorder
;
333 static inline COLORREF
334 PAGER_GetBkColor(const PAGER_INFO
*infoPtr
)
336 TRACE("[%p] returns %06x\n", infoPtr
->hwndSelf
, infoPtr
->clrBk
);
337 return infoPtr
->clrBk
;
341 PAGER_CalcSize (const PAGER_INFO
*infoPtr
, INT
* size
, BOOL getWidth
)
344 ZeroMemory (&nmpgcs
, sizeof (NMPGCALCSIZE
));
345 nmpgcs
.hdr
.hwndFrom
= infoPtr
->hwndSelf
;
346 nmpgcs
.hdr
.idFrom
= GetWindowLongPtrW (infoPtr
->hwndSelf
, GWLP_ID
);
347 nmpgcs
.hdr
.code
= PGN_CALCSIZE
;
348 nmpgcs
.dwFlag
= getWidth
? PGF_CALCWIDTH
: PGF_CALCHEIGHT
;
349 nmpgcs
.iWidth
= getWidth
? *size
: 0;
350 nmpgcs
.iHeight
= getWidth
? 0 : *size
;
351 SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
, nmpgcs
.hdr
.idFrom
, (LPARAM
)&nmpgcs
);
353 *size
= getWidth
? nmpgcs
.iWidth
: nmpgcs
.iHeight
;
355 TRACE("[%p] PGN_CALCSIZE returns %s=%d\n", infoPtr
->hwndSelf
,
356 getWidth
? "width" : "height", *size
);
360 PAGER_PositionChildWnd(PAGER_INFO
* infoPtr
)
362 if (infoPtr
->hwndChild
)
365 int nPos
= infoPtr
->nPos
;
367 /* compensate for a grayed btn, which will soon become invisible */
368 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
369 nPos
+= infoPtr
->nButtonSize
;
371 GetClientRect(infoPtr
->hwndSelf
, &rcClient
);
373 if (infoPtr
->dwStyle
& PGS_HORZ
)
375 int wndSize
= max(0, rcClient
.right
- rcClient
.left
);
376 if (infoPtr
->nWidth
< wndSize
)
377 infoPtr
->nWidth
= wndSize
;
379 TRACE("[%p] SWP %dx%d at (%d,%d)\n", infoPtr
->hwndSelf
,
380 infoPtr
->nWidth
, infoPtr
->nHeight
,
382 SetWindowPos(infoPtr
->hwndChild
, 0,
384 infoPtr
->nWidth
, infoPtr
->nHeight
,
389 int wndSize
= max(0, rcClient
.bottom
- rcClient
.top
);
390 if (infoPtr
->nHeight
< wndSize
)
391 infoPtr
->nHeight
= wndSize
;
393 TRACE("[%p] SWP %dx%d at (%d,%d)\n", infoPtr
->hwndSelf
,
394 infoPtr
->nWidth
, infoPtr
->nHeight
,
396 SetWindowPos(infoPtr
->hwndChild
, 0,
398 infoPtr
->nWidth
, infoPtr
->nHeight
,
402 InvalidateRect(infoPtr
->hwndChild
, NULL
, TRUE
);
407 PAGER_GetScrollRange(PAGER_INFO
* infoPtr
)
411 if (infoPtr
->hwndChild
)
413 INT wndSize
, childSize
;
415 GetWindowRect(infoPtr
->hwndSelf
, &wndRect
);
417 if (infoPtr
->dwStyle
& PGS_HORZ
)
419 wndSize
= wndRect
.right
- wndRect
.left
;
420 PAGER_CalcSize(infoPtr
, &infoPtr
->nWidth
, TRUE
);
421 childSize
= infoPtr
->nWidth
;
425 wndSize
= wndRect
.bottom
- wndRect
.top
;
426 PAGER_CalcSize(infoPtr
, &infoPtr
->nHeight
, FALSE
);
427 childSize
= infoPtr
->nHeight
;
430 TRACE("childSize = %d, wndSize = %d\n", childSize
, wndSize
);
431 if (childSize
> wndSize
)
432 scrollRange
= childSize
- wndSize
+ infoPtr
->nButtonSize
;
435 TRACE("[%p] returns %d\n", infoPtr
->hwndSelf
, scrollRange
);
440 PAGER_UpdateBtns(PAGER_INFO
*infoPtr
, INT scrollRange
, BOOL hideGrayBtns
)
444 INT oldTLbtnState
= infoPtr
->TLbtnState
;
445 INT oldBRbtnState
= infoPtr
->BRbtnState
;
447 RECT rcTopLeft
, rcBottomRight
;
449 /* get button rects */
450 PAGER_GetButtonRects(infoPtr
, &rcTopLeft
, &rcBottomRight
, FALSE
);
454 /* update states based on scroll position */
455 if (infoPtr
->nPos
> 0)
457 if (infoPtr
->TLbtnState
== PGF_INVISIBLE
|| infoPtr
->TLbtnState
== PGF_GRAYED
)
458 infoPtr
->TLbtnState
= PGF_NORMAL
;
460 else if (PtInRect(&rcTopLeft
, pt
))
461 infoPtr
->TLbtnState
= PGF_GRAYED
;
463 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
465 if (scrollRange
<= 0)
467 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
468 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
470 else if (infoPtr
->nPos
< scrollRange
)
472 if (infoPtr
->BRbtnState
== PGF_INVISIBLE
|| infoPtr
->BRbtnState
== PGF_GRAYED
)
473 infoPtr
->BRbtnState
= PGF_NORMAL
;
475 else if (PtInRect(&rcBottomRight
, pt
))
476 infoPtr
->BRbtnState
= PGF_GRAYED
;
478 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
480 /* only need to resize when entering or leaving PGF_INVISIBLE state */
482 ((oldTLbtnState
== PGF_INVISIBLE
) != (infoPtr
->TLbtnState
== PGF_INVISIBLE
)) ||
483 ((oldBRbtnState
== PGF_INVISIBLE
) != (infoPtr
->BRbtnState
== PGF_INVISIBLE
));
484 /* initiate NCCalcSize to resize client wnd if necessary */
486 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
487 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
488 SWP_NOZORDER
| SWP_NOACTIVATE
);
490 /* repaint when changing any state */
491 repaintBtns
= (oldTLbtnState
!= infoPtr
->TLbtnState
) ||
492 (oldBRbtnState
!= infoPtr
->BRbtnState
);
494 SendMessageW(infoPtr
->hwndSelf
, WM_NCPAINT
, 0, 0);
498 PAGER_SetPos(PAGER_INFO
* infoPtr
, INT newPos
, BOOL fromBtnPress
)
500 INT scrollRange
= PAGER_GetScrollRange(infoPtr
);
501 INT oldPos
= infoPtr
->nPos
;
503 if ((scrollRange
<= 0) || (newPos
< 0))
505 else if (newPos
> scrollRange
)
506 infoPtr
->nPos
= scrollRange
;
508 infoPtr
->nPos
= newPos
;
510 TRACE("[%p] pos=%d, oldpos=%d\n", infoPtr
->hwndSelf
, infoPtr
->nPos
, oldPos
);
512 if (infoPtr
->nPos
!= oldPos
)
514 /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
515 PAGER_UpdateBtns(infoPtr
, scrollRange
, !fromBtnPress
);
516 PAGER_PositionChildWnd(infoPtr
);
523 PAGER_WindowPosChanging(PAGER_INFO
* infoPtr
, WINDOWPOS
*winpos
)
525 if ((infoPtr
->dwStyle
& CCS_NORESIZE
) && !(winpos
->flags
& SWP_NOSIZE
))
527 /* don't let the app resize the nonscrollable dimension of a control
528 * that was created with CCS_NORESIZE style
529 * (i.e. height for a horizontal pager, or width for a vertical one) */
531 /* except if the current dimension is 0 and app is setting for
532 * first time, then save amount as dimension. - GA 8/01 */
534 if (infoPtr
->dwStyle
& PGS_HORZ
)
535 if (!infoPtr
->nHeight
&& winpos
->cy
)
536 infoPtr
->nHeight
= winpos
->cy
;
538 winpos
->cy
= infoPtr
->nHeight
;
540 if (!infoPtr
->nWidth
&& winpos
->cx
)
541 infoPtr
->nWidth
= winpos
->cx
;
543 winpos
->cx
= infoPtr
->nWidth
;
547 return DefWindowProcW (infoPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)winpos
);
551 PAGER_SetFixedWidth(PAGER_INFO
* infoPtr
)
553 /* Must set the non-scrollable dimension to be less than the full height/width
554 * so that NCCalcSize is called. The Microsoft docs mention 3/4 factor for button
555 * size, and experimentation shows that the effect is almost right. */
559 GetWindowRect(infoPtr
->hwndSelf
, &wndRect
);
561 /* see what the app says for btn width */
562 PAGER_CalcSize(infoPtr
, &infoPtr
->nWidth
, TRUE
);
564 if (infoPtr
->dwStyle
& CCS_NORESIZE
)
566 delta
= wndRect
.right
- wndRect
.left
- infoPtr
->nWidth
;
567 if (delta
> infoPtr
->nButtonSize
)
568 infoPtr
->nWidth
+= 4 * infoPtr
->nButtonSize
/ 3;
570 infoPtr
->nWidth
+= infoPtr
->nButtonSize
/ 3;
573 h
= wndRect
.bottom
- wndRect
.top
+ infoPtr
->nButtonSize
;
575 TRACE("[%p] infoPtr->nWidth set to %d\n",
576 infoPtr
->hwndSelf
, infoPtr
->nWidth
);
582 PAGER_SetFixedHeight(PAGER_INFO
* infoPtr
)
584 /* Must set the non-scrollable dimension to be less than the full height/width
585 * so that NCCalcSize is called. The Microsoft docs mention 3/4 factor for button
586 * size, and experimentation shows that the effect is almost right. */
590 GetWindowRect(infoPtr
->hwndSelf
, &wndRect
);
592 /* see what the app says for btn height */
593 PAGER_CalcSize(infoPtr
, &infoPtr
->nHeight
, FALSE
);
595 if (infoPtr
->dwStyle
& CCS_NORESIZE
)
597 delta
= wndRect
.bottom
- wndRect
.top
- infoPtr
->nHeight
;
598 if (delta
> infoPtr
->nButtonSize
)
599 infoPtr
->nHeight
+= infoPtr
->nButtonSize
;
601 infoPtr
->nHeight
+= infoPtr
->nButtonSize
/ 3;
604 w
= wndRect
.right
- wndRect
.left
+ infoPtr
->nButtonSize
;
606 TRACE("[%p] infoPtr->nHeight set to %d\n",
607 infoPtr
->hwndSelf
, infoPtr
->nHeight
);
612 /******************************************************************
613 * For the PGM_RECALCSIZE message (but not the other uses in *
614 * this module), the native control does only the following: *
616 * if (some condition) *
617 * PostMessageW(hwnd, EM_FMTLINES, 0, 0); *
618 * return DefWindowProcW(hwnd, PGM_RECALCSIZE, 0, 0); *
620 * When we figure out what the "some condition" is we will *
621 * implement that for the message processing. *
622 ******************************************************************/
625 PAGER_RecalcSize(PAGER_INFO
*infoPtr
)
627 TRACE("[%p]\n", infoPtr
->hwndSelf
);
629 if (infoPtr
->hwndChild
)
631 INT scrollRange
= PAGER_GetScrollRange(infoPtr
);
633 if (scrollRange
<= 0)
636 PAGER_SetPos(infoPtr
, 0, FALSE
);
639 PAGER_PositionChildWnd(infoPtr
);
647 PAGER_SetBkColor (PAGER_INFO
* infoPtr
, COLORREF clrBk
)
649 COLORREF clrTemp
= infoPtr
->clrBk
;
651 infoPtr
->clrBk
= clrBk
;
652 TRACE("[%p] %06x\n", infoPtr
->hwndSelf
, infoPtr
->clrBk
);
654 /* the native control seems to do things this way */
655 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
656 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
657 SWP_NOZORDER
| SWP_NOACTIVATE
);
659 RedrawWindow(infoPtr
->hwndSelf
, 0, 0, RDW_ERASE
| RDW_INVALIDATE
);
666 PAGER_SetBorder (PAGER_INFO
* infoPtr
, INT iBorder
)
668 INT nTemp
= infoPtr
->nBorder
;
670 infoPtr
->nBorder
= iBorder
;
671 TRACE("[%p] %d\n", infoPtr
->hwndSelf
, infoPtr
->nBorder
);
673 PAGER_RecalcSize(infoPtr
);
680 PAGER_SetButtonSize (PAGER_INFO
* infoPtr
, INT iButtonSize
)
682 INT nTemp
= infoPtr
->nButtonSize
;
684 infoPtr
->nButtonSize
= iButtonSize
;
685 TRACE("[%p] %d\n", infoPtr
->hwndSelf
, infoPtr
->nButtonSize
);
687 PAGER_RecalcSize(infoPtr
);
694 PAGER_SetChild (PAGER_INFO
* infoPtr
, HWND hwndChild
)
698 infoPtr
->hwndChild
= IsWindow (hwndChild
) ? hwndChild
: 0;
700 if (infoPtr
->hwndChild
)
702 TRACE("[%p] hwndChild=%p\n", infoPtr
->hwndSelf
, infoPtr
->hwndChild
);
704 if (infoPtr
->dwStyle
& PGS_HORZ
) {
705 hw
= PAGER_SetFixedHeight(infoPtr
);
706 /* adjust non-scrollable dimension to fit the child */
707 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, hw
, infoPtr
->nHeight
,
708 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
709 SWP_NOSIZE
| SWP_NOACTIVATE
);
712 hw
= PAGER_SetFixedWidth(infoPtr
);
713 /* adjust non-scrollable dimension to fit the child */
714 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, infoPtr
->nWidth
, hw
,
715 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
716 SWP_NOSIZE
| SWP_NOACTIVATE
);
719 /* position child within the page scroller */
720 SetWindowPos(infoPtr
->hwndChild
, HWND_TOP
,
722 SWP_SHOWWINDOW
| SWP_NOSIZE
); /* native is 0 */
725 PAGER_SetPos(infoPtr
, 0, FALSE
);
732 PAGER_Scroll(PAGER_INFO
* infoPtr
, INT dir
)
734 NMPGSCROLL nmpgScroll
;
737 if (infoPtr
->hwndChild
)
739 ZeroMemory (&nmpgScroll
, sizeof (NMPGSCROLL
));
740 nmpgScroll
.hdr
.hwndFrom
= infoPtr
->hwndSelf
;
741 nmpgScroll
.hdr
.idFrom
= GetWindowLongPtrW (infoPtr
->hwndSelf
, GWLP_ID
);
742 nmpgScroll
.hdr
.code
= PGN_SCROLL
;
744 GetWindowRect(infoPtr
->hwndSelf
, &rcWnd
);
745 GetClientRect(infoPtr
->hwndSelf
, &nmpgScroll
.rcParent
);
746 nmpgScroll
.iXpos
= nmpgScroll
.iYpos
= 0;
747 nmpgScroll
.iDir
= dir
;
749 if (infoPtr
->dwStyle
& PGS_HORZ
)
751 nmpgScroll
.iScroll
= rcWnd
.right
- rcWnd
.left
;
752 nmpgScroll
.iXpos
= infoPtr
->nPos
;
756 nmpgScroll
.iScroll
= rcWnd
.bottom
- rcWnd
.top
;
757 nmpgScroll
.iYpos
= infoPtr
->nPos
;
759 nmpgScroll
.iScroll
-= 2*infoPtr
->nButtonSize
;
761 SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
, nmpgScroll
.hdr
.idFrom
, (LPARAM
)&nmpgScroll
);
763 TRACE("[%p] PGN_SCROLL returns iScroll=%d\n", infoPtr
->hwndSelf
, nmpgScroll
.iScroll
);
765 if (nmpgScroll
.iScroll
> 0)
767 infoPtr
->direction
= dir
;
769 if (dir
== PGF_SCROLLLEFT
|| dir
== PGF_SCROLLUP
)
770 PAGER_SetPos(infoPtr
, infoPtr
->nPos
- nmpgScroll
.iScroll
, TRUE
);
772 PAGER_SetPos(infoPtr
, infoPtr
->nPos
+ nmpgScroll
.iScroll
, TRUE
);
775 infoPtr
->direction
= -1;
780 PAGER_FmtLines(const PAGER_INFO
*infoPtr
)
782 /* initiate NCCalcSize to resize client wnd and get size */
783 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
784 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
785 SWP_NOZORDER
| SWP_NOACTIVATE
);
787 SetWindowPos(infoPtr
->hwndChild
, 0,
788 0,0,infoPtr
->nWidth
,infoPtr
->nHeight
,
791 return DefWindowProcW (infoPtr
->hwndSelf
, EM_FMTLINES
, 0, 0);
795 PAGER_Create (HWND hwnd
, const CREATESTRUCTW
*lpcs
)
799 /* allocate memory for info structure */
800 infoPtr
= Alloc (sizeof(PAGER_INFO
));
801 if (!infoPtr
) return -1;
802 SetWindowLongPtrW (hwnd
, 0, (DWORD_PTR
)infoPtr
);
804 /* set default settings */
805 infoPtr
->hwndSelf
= hwnd
;
806 infoPtr
->hwndChild
= NULL
;
807 infoPtr
->hwndNotify
= lpcs
->hwndParent
;
808 infoPtr
->dwStyle
= lpcs
->style
;
809 infoPtr
->clrBk
= GetSysColor(COLOR_BTNFACE
);
810 infoPtr
->nBorder
= 0;
811 infoPtr
->nButtonSize
= 12;
814 infoPtr
->nHeight
= 0;
815 infoPtr
->bForward
= FALSE
;
816 infoPtr
->bCapture
= FALSE
;
817 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
818 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
819 infoPtr
->direction
= -1;
821 if (infoPtr
->dwStyle
& PGS_DRAGNDROP
)
822 FIXME("[%p] Drag and Drop style is not implemented yet.\n", infoPtr
->hwndSelf
);
829 PAGER_Destroy (PAGER_INFO
*infoPtr
)
831 SetWindowLongPtrW (infoPtr
->hwndSelf
, 0, 0);
832 Free (infoPtr
); /* free pager info data */
837 PAGER_NCCalcSize(PAGER_INFO
* infoPtr
, WPARAM wParam
, LPRECT lpRect
)
839 RECT rcChild
, rcWindow
;
842 * lpRect points to a RECT struct. On entry, the struct
843 * contains the proposed wnd rectangle for the window.
844 * On exit, the struct should contain the screen
845 * coordinates of the corresponding window's client area.
848 DefWindowProcW (infoPtr
->hwndSelf
, WM_NCCALCSIZE
, wParam
, (LPARAM
)lpRect
);
850 TRACE("orig rect=%s\n", wine_dbgstr_rect(lpRect
));
852 GetWindowRect (infoPtr
->hwndChild
, &rcChild
);
853 MapWindowPoints (0, infoPtr
->hwndSelf
, (LPPOINT
)&rcChild
, 2); /* FIXME: RECT != 2 POINTS */
854 GetWindowRect (infoPtr
->hwndSelf
, &rcWindow
);
856 if (infoPtr
->dwStyle
& PGS_HORZ
)
858 infoPtr
->nWidth
= lpRect
->right
- lpRect
->left
;
859 PAGER_CalcSize (infoPtr
, &infoPtr
->nWidth
, TRUE
);
861 if (infoPtr
->TLbtnState
&& (lpRect
->left
+ infoPtr
->nButtonSize
< lpRect
->right
))
862 lpRect
->left
+= infoPtr
->nButtonSize
;
863 if (infoPtr
->BRbtnState
&& (lpRect
->right
- infoPtr
->nButtonSize
> lpRect
->left
))
864 lpRect
->right
-= infoPtr
->nButtonSize
;
868 infoPtr
->nHeight
= lpRect
->bottom
- lpRect
->top
;
869 PAGER_CalcSize (infoPtr
, &infoPtr
->nHeight
, FALSE
);
871 if (infoPtr
->TLbtnState
&& (lpRect
->top
+ infoPtr
->nButtonSize
< lpRect
->bottom
))
872 lpRect
->top
+= infoPtr
->nButtonSize
;
873 if (infoPtr
->BRbtnState
&& (lpRect
->bottom
- infoPtr
->nButtonSize
> lpRect
->top
))
874 lpRect
->bottom
-= infoPtr
->nButtonSize
;
877 TRACE("nPos=%d, nHeight=%d, window=%s\n",
878 infoPtr
->nPos
, infoPtr
->nHeight
,
879 wine_dbgstr_rect(&rcWindow
));
881 TRACE("[%p] client rect set to %dx%d at (%d,%d) BtnState[%d,%d]\n",
882 infoPtr
->hwndSelf
, lpRect
->right
-lpRect
->left
, lpRect
->bottom
-lpRect
->top
,
883 lpRect
->left
, lpRect
->top
,
884 infoPtr
->TLbtnState
, infoPtr
->BRbtnState
);
890 PAGER_NCPaint (const PAGER_INFO
* infoPtr
, HRGN hRgn
)
892 RECT rcBottomRight
, rcTopLeft
;
895 if (infoPtr
->dwStyle
& WS_MINIMIZE
)
898 DefWindowProcW (infoPtr
->hwndSelf
, WM_NCPAINT
, (WPARAM
)hRgn
, 0);
900 if (!(hdc
= GetDCEx (infoPtr
->hwndSelf
, 0, DCX_USESTYLE
| DCX_WINDOW
)))
903 PAGER_GetButtonRects(infoPtr
, &rcTopLeft
, &rcBottomRight
, FALSE
);
905 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcTopLeft
,
906 infoPtr
->dwStyle
& PGS_HORZ
, TRUE
, infoPtr
->TLbtnState
);
907 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcBottomRight
,
908 infoPtr
->dwStyle
& PGS_HORZ
, FALSE
, infoPtr
->BRbtnState
);
910 ReleaseDC( infoPtr
->hwndSelf
, hdc
);
915 PAGER_HitTest (const PAGER_INFO
* infoPtr
, const POINT
* pt
)
917 RECT clientRect
, rcTopLeft
, rcBottomRight
;
920 GetClientRect (infoPtr
->hwndSelf
, &clientRect
);
922 if (PtInRect(&clientRect
, *pt
))
929 PAGER_GetButtonRects(infoPtr
, &rcTopLeft
, &rcBottomRight
, TRUE
);
931 if ((infoPtr
->TLbtnState
!= PGF_INVISIBLE
) && PtInRect(&rcTopLeft
, ptWindow
))
933 TRACE("PGB_TOPORLEFT\n");
934 return PGB_TOPORLEFT
;
936 else if ((infoPtr
->BRbtnState
!= PGF_INVISIBLE
) && PtInRect(&rcBottomRight
, ptWindow
))
938 TRACE("PGB_BOTTOMORRIGHT\n");
939 return PGB_BOTTOMORRIGHT
;
947 PAGER_NCHitTest (const PAGER_INFO
* infoPtr
, INT x
, INT y
)
955 ScreenToClient (infoPtr
->hwndSelf
, &pt
);
956 nHit
= PAGER_HitTest(infoPtr
, &pt
);
958 return (nHit
< 0) ? HTTRANSPARENT
: HTCLIENT
;
962 PAGER_MouseMove (PAGER_INFO
* infoPtr
, INT keys
, INT x
, INT y
)
965 RECT wnrect
, *btnrect
= NULL
;
966 BOOL topLeft
= FALSE
;
974 TRACE("[%p] to (%d,%d)\n", infoPtr
->hwndSelf
, x
, y
);
975 ClientToScreen(infoPtr
->hwndSelf
, &pt
);
976 GetWindowRect(infoPtr
->hwndSelf
, &wnrect
);
977 if (PtInRect(&wnrect
, pt
)) {
978 RECT TLbtnrect
, BRbtnrect
;
979 PAGER_GetButtonRects(infoPtr
, &TLbtnrect
, &BRbtnrect
, FALSE
);
982 MapWindowPoints(0, infoPtr
->hwndSelf
, &clpt
, 1);
983 hit
= PAGER_HitTest(infoPtr
, &clpt
);
984 if ((hit
== PGB_TOPORLEFT
) && (infoPtr
->TLbtnState
== PGF_NORMAL
))
987 btnrect
= &TLbtnrect
;
988 infoPtr
->TLbtnState
= PGF_HOT
;
989 btnstate
= infoPtr
->TLbtnState
;
991 else if ((hit
== PGB_BOTTOMORRIGHT
) && (infoPtr
->BRbtnState
== PGF_NORMAL
))
994 btnrect
= &BRbtnrect
;
995 infoPtr
->BRbtnState
= PGF_HOT
;
996 btnstate
= infoPtr
->BRbtnState
;
999 /* If in one of the buttons the capture and draw buttons */
1002 TRACE("[%p] draw btn (%s), Capture %s, style %08x\n",
1003 infoPtr
->hwndSelf
, wine_dbgstr_rect(btnrect
),
1004 (infoPtr
->bCapture
) ? "TRUE" : "FALSE",
1006 if (!infoPtr
->bCapture
)
1008 TRACE("[%p] SetCapture\n", infoPtr
->hwndSelf
);
1009 SetCapture(infoPtr
->hwndSelf
);
1010 infoPtr
->bCapture
= TRUE
;
1012 if (infoPtr
->dwStyle
& PGS_AUTOSCROLL
)
1013 SetTimer(infoPtr
->hwndSelf
, TIMERID1
, 0x3e, 0);
1014 hdc
= GetWindowDC(infoPtr
->hwndSelf
);
1015 /* OffsetRect(wnrect, 0 | 1, 0 | 1) */
1016 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, *btnrect
,
1017 infoPtr
->dwStyle
& PGS_HORZ
, topLeft
, btnstate
);
1018 ReleaseDC(infoPtr
->hwndSelf
, hdc
);
1023 /* If we think we are captured, then do release */
1024 if (infoPtr
->bCapture
&& (WindowFromPoint(pt
) != infoPtr
->hwndSelf
))
1028 infoPtr
->bCapture
= FALSE
;
1030 if (GetCapture() == infoPtr
->hwndSelf
)
1034 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
1036 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
1037 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
1038 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1039 SWP_NOZORDER
| SWP_NOACTIVATE
);
1041 else if (infoPtr
->TLbtnState
== PGF_HOT
)
1043 infoPtr
->TLbtnState
= PGF_NORMAL
;
1044 /* FIXME: just invalidate button rect */
1045 RedrawWindow(infoPtr
->hwndSelf
, NULL
, NULL
, RDW_FRAME
| RDW_INVALIDATE
);
1048 if (infoPtr
->BRbtnState
== PGF_GRAYED
)
1050 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
1051 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
1052 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1053 SWP_NOZORDER
| SWP_NOACTIVATE
);
1055 else if (infoPtr
->BRbtnState
== PGF_HOT
)
1057 infoPtr
->BRbtnState
= PGF_NORMAL
;
1058 /* FIXME: just invalidate button rect */
1059 RedrawWindow(infoPtr
->hwndSelf
, NULL
, NULL
, RDW_FRAME
| RDW_INVALIDATE
);
1062 /* Notify parent of released mouse capture */
1063 memset(&nmhdr
, 0, sizeof(NMHDR
));
1064 nmhdr
.hwndFrom
= infoPtr
->hwndSelf
;
1065 nmhdr
.idFrom
= GetWindowLongPtrW(infoPtr
->hwndSelf
, GWLP_ID
);
1066 nmhdr
.code
= NM_RELEASEDCAPTURE
;
1067 SendMessageW(infoPtr
->hwndNotify
, WM_NOTIFY
, nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1069 if (IsWindow(infoPtr
->hwndSelf
))
1070 KillTimer(infoPtr
->hwndSelf
, TIMERID1
);
1076 PAGER_LButtonDown (PAGER_INFO
* infoPtr
, INT keys
, INT x
, INT y
)
1078 BOOL repaintBtns
= FALSE
;
1085 TRACE("[%p] at (%d,%d)\n", infoPtr
->hwndSelf
, x
, y
);
1087 hit
= PAGER_HitTest(infoPtr
, &pt
);
1089 /* put btn in DEPRESSED state */
1090 if (hit
== PGB_TOPORLEFT
)
1092 repaintBtns
= infoPtr
->TLbtnState
!= PGF_DEPRESSED
;
1093 infoPtr
->TLbtnState
= PGF_DEPRESSED
;
1094 SetTimer(infoPtr
->hwndSelf
, TIMERID1
, INITIAL_DELAY
, 0);
1096 else if (hit
== PGB_BOTTOMORRIGHT
)
1098 repaintBtns
= infoPtr
->BRbtnState
!= PGF_DEPRESSED
;
1099 infoPtr
->BRbtnState
= PGF_DEPRESSED
;
1100 SetTimer(infoPtr
->hwndSelf
, TIMERID1
, INITIAL_DELAY
, 0);
1104 SendMessageW(infoPtr
->hwndSelf
, WM_NCPAINT
, 0, 0);
1109 if (infoPtr
->dwStyle
& PGS_HORZ
)
1111 TRACE("[%p] PGF_SCROLLLEFT\n", infoPtr
->hwndSelf
);
1112 PAGER_Scroll(infoPtr
, PGF_SCROLLLEFT
);
1116 TRACE("[%p] PGF_SCROLLUP\n", infoPtr
->hwndSelf
);
1117 PAGER_Scroll(infoPtr
, PGF_SCROLLUP
);
1120 case PGB_BOTTOMORRIGHT
:
1121 if (infoPtr
->dwStyle
& PGS_HORZ
)
1123 TRACE("[%p] PGF_SCROLLRIGHT\n", infoPtr
->hwndSelf
);
1124 PAGER_Scroll(infoPtr
, PGF_SCROLLRIGHT
);
1128 TRACE("[%p] PGF_SCROLLDOWN\n", infoPtr
->hwndSelf
);
1129 PAGER_Scroll(infoPtr
, PGF_SCROLLDOWN
);
1140 PAGER_LButtonUp (PAGER_INFO
* infoPtr
, INT keys
, INT x
, INT y
)
1142 TRACE("[%p]\n", infoPtr
->hwndSelf
);
1144 KillTimer (infoPtr
->hwndSelf
, TIMERID1
);
1145 KillTimer (infoPtr
->hwndSelf
, TIMERID2
);
1147 /* make PRESSED btns NORMAL but don't hide gray btns */
1148 if (infoPtr
->TLbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
1149 infoPtr
->TLbtnState
= PGF_NORMAL
;
1150 if (infoPtr
->BRbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
1151 infoPtr
->BRbtnState
= PGF_NORMAL
;
1157 PAGER_Timer (PAGER_INFO
* infoPtr
, INT nTimerId
)
1161 /* if initial timer, kill it and start the repeat timer */
1162 if (nTimerId
== TIMERID1
) {
1163 if (infoPtr
->TLbtnState
== PGF_HOT
)
1164 dir
= (infoPtr
->dwStyle
& PGS_HORZ
) ?
1165 PGF_SCROLLLEFT
: PGF_SCROLLUP
;
1167 dir
= (infoPtr
->dwStyle
& PGS_HORZ
) ?
1168 PGF_SCROLLRIGHT
: PGF_SCROLLDOWN
;
1169 TRACE("[%p] TIMERID1: style=%08x, dir=%d\n",
1170 infoPtr
->hwndSelf
, infoPtr
->dwStyle
, dir
);
1171 KillTimer(infoPtr
->hwndSelf
, TIMERID1
);
1172 SetTimer(infoPtr
->hwndSelf
, TIMERID1
, REPEAT_DELAY
, 0);
1173 if (infoPtr
->dwStyle
& PGS_AUTOSCROLL
) {
1174 PAGER_Scroll(infoPtr
, dir
);
1175 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
1176 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1177 SWP_NOZORDER
| SWP_NOACTIVATE
);
1183 TRACE("[%p] TIMERID2: dir=%d\n", infoPtr
->hwndSelf
, infoPtr
->direction
);
1184 KillTimer(infoPtr
->hwndSelf
, TIMERID2
);
1185 if (infoPtr
->direction
> 0) {
1186 PAGER_Scroll(infoPtr
, infoPtr
->direction
);
1187 SetTimer(infoPtr
->hwndSelf
, TIMERID2
, REPEAT_DELAY
, 0);
1193 PAGER_EraseBackground (const PAGER_INFO
* infoPtr
, HDC hdc
)
1200 parent
= GetParent(infoPtr
->hwndSelf
);
1201 MapWindowPoints(infoPtr
->hwndSelf
, parent
, &pt
, 1);
1202 OffsetWindowOrgEx (hdc
, pt
.x
, pt
.y
, &ptorig
);
1203 SendMessageW (parent
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1204 SetWindowOrgEx (hdc
, ptorig
.x
, ptorig
.y
, 0);
1211 PAGER_Size (PAGER_INFO
* infoPtr
, INT type
, INT x
, INT y
)
1213 /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
1215 TRACE("[%p] %d,%d\n", infoPtr
->hwndSelf
, x
, y
);
1217 if (infoPtr
->dwStyle
& PGS_HORZ
)
1218 infoPtr
->nHeight
= y
;
1220 infoPtr
->nWidth
= x
;
1222 return PAGER_RecalcSize(infoPtr
);
1227 PAGER_StyleChanged(PAGER_INFO
*infoPtr
, WPARAM wStyleType
, const STYLESTRUCT
*lpss
)
1229 DWORD oldStyle
= infoPtr
->dwStyle
;
1231 TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n",
1232 wStyleType
, lpss
->styleOld
, lpss
->styleNew
);
1234 if (wStyleType
!= GWL_STYLE
) return 0;
1236 infoPtr
->dwStyle
= lpss
->styleNew
;
1238 if ((oldStyle
^ lpss
->styleNew
) & (PGS_HORZ
| PGS_VERT
))
1240 PAGER_RecalcSize(infoPtr
);
1246 static LRESULT WINAPI
1247 PAGER_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1249 PAGER_INFO
*infoPtr
= (PAGER_INFO
*)GetWindowLongPtrW(hwnd
, 0);
1251 if (!infoPtr
&& (uMsg
!= WM_CREATE
))
1252 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
1257 return PAGER_FmtLines(infoPtr
);
1259 case PGM_FORWARDMOUSE
:
1260 return PAGER_ForwardMouse (infoPtr
, (BOOL
)wParam
);
1262 case PGM_GETBKCOLOR
:
1263 return PAGER_GetBkColor(infoPtr
);
1266 return PAGER_GetBorder(infoPtr
);
1268 case PGM_GETBUTTONSIZE
:
1269 return PAGER_GetButtonSize(infoPtr
);
1272 return PAGER_GetPos(infoPtr
);
1274 case PGM_GETBUTTONSTATE
:
1275 return PAGER_GetButtonState (infoPtr
, (INT
)lParam
);
1277 /* case PGM_GETDROPTARGET: */
1279 case PGM_RECALCSIZE
:
1280 return PAGER_RecalcSize(infoPtr
);
1282 case PGM_SETBKCOLOR
:
1283 return PAGER_SetBkColor (infoPtr
, (COLORREF
)lParam
);
1286 return PAGER_SetBorder (infoPtr
, (INT
)lParam
);
1288 case PGM_SETBUTTONSIZE
:
1289 return PAGER_SetButtonSize (infoPtr
, (INT
)lParam
);
1292 return PAGER_SetChild (infoPtr
, (HWND
)lParam
);
1295 return PAGER_SetPos(infoPtr
, (INT
)lParam
, FALSE
);
1298 return PAGER_Create (hwnd
, (LPCREATESTRUCTW
)lParam
);
1301 return PAGER_Destroy (infoPtr
);
1304 return PAGER_Size (infoPtr
, (INT
)wParam
, (short)LOWORD(lParam
), (short)HIWORD(lParam
));
1307 return PAGER_NCPaint (infoPtr
, (HRGN
)wParam
);
1309 case WM_WINDOWPOSCHANGING
:
1310 return PAGER_WindowPosChanging (infoPtr
, (WINDOWPOS
*)lParam
);
1312 case WM_STYLECHANGED
:
1313 return PAGER_StyleChanged(infoPtr
, wParam
, (LPSTYLESTRUCT
)lParam
);
1316 return PAGER_NCCalcSize (infoPtr
, wParam
, (LPRECT
)lParam
);
1319 return PAGER_NCHitTest (infoPtr
, (short)LOWORD(lParam
), (short)HIWORD(lParam
));
1322 if (infoPtr
->bForward
&& infoPtr
->hwndChild
)
1323 PostMessageW(infoPtr
->hwndChild
, WM_MOUSEMOVE
, wParam
, lParam
);
1324 return PAGER_MouseMove (infoPtr
, (INT
)wParam
, (short)LOWORD(lParam
), (short)HIWORD(lParam
));
1326 case WM_LBUTTONDOWN
:
1327 return PAGER_LButtonDown (infoPtr
, (INT
)wParam
, (short)LOWORD(lParam
), (short)HIWORD(lParam
));
1330 return PAGER_LButtonUp (infoPtr
, (INT
)wParam
, (short)LOWORD(lParam
), (short)HIWORD(lParam
));
1333 return PAGER_EraseBackground (infoPtr
, (HDC
)wParam
);
1336 return PAGER_Timer (infoPtr
, (INT
)wParam
);
1340 return SendMessageW (infoPtr
->hwndNotify
, uMsg
, wParam
, lParam
);
1343 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
1349 PAGER_Register (void)
1353 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
1354 wndClass
.style
= CS_GLOBALCLASS
;
1355 wndClass
.lpfnWndProc
= PAGER_WindowProc
;
1356 wndClass
.cbClsExtra
= 0;
1357 wndClass
.cbWndExtra
= sizeof(PAGER_INFO
*);
1358 wndClass
.hCursor
= LoadCursorW (0, (LPWSTR
)IDC_ARROW
);
1359 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
1360 wndClass
.lpszClassName
= WC_PAGESCROLLERW
;
1362 RegisterClassW (&wndClass
);
1367 PAGER_Unregister (void)
1369 UnregisterClassW (WC_PAGESCROLLERW
, NULL
);