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
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>
65 #include "wine/debug.h"
67 WINE_DEFAULT_DEBUG_CHANNEL(pager
);
71 HWND hwndSelf
; /* handle of the control wnd */
72 HWND hwndChild
; /* handle of the contained wnd */
73 HWND hwndNotify
; /* handle of the parent wnd */
74 DWORD dwStyle
; /* styles for this control */
75 COLORREF clrBk
; /* background color */
76 INT nBorder
; /* border size for the control */
77 INT nButtonSize
;/* size of the pager btns */
78 INT nPos
; /* scroll position */
79 INT nWidth
; /* from child wnd's response to PGN_CALCSIZE */
80 INT nHeight
; /* from child wnd's response to PGN_CALCSIZE */
81 BOOL bForward
; /* forward WM_MOUSEMOVE msgs to the contained wnd */
82 BOOL bCapture
; /* we have captured the mouse */
83 INT TLbtnState
; /* state of top or left btn */
84 INT BRbtnState
; /* state of bottom or right btn */
85 INT direction
; /* direction of the scroll, (e.g. PGF_SCROLLUP) */
88 #define MIN_ARROW_WIDTH 8
89 #define MIN_ARROW_HEIGHT 5
93 #define INITIAL_DELAY 500
94 #define REPEAT_DELAY 50
97 PAGER_GetButtonRects(PAGER_INFO
* infoPtr
, RECT
* prcTopLeft
, RECT
* prcBottomRight
, BOOL bClientCoords
)
100 GetWindowRect (infoPtr
->hwndSelf
, &rcWindow
);
104 POINT pt
= {rcWindow
.left
, rcWindow
.top
};
105 ScreenToClient(infoPtr
->hwndSelf
, &pt
);
106 OffsetRect(&rcWindow
, -(rcWindow
.left
-pt
.x
), -(rcWindow
.top
-pt
.y
));
109 OffsetRect(&rcWindow
, -rcWindow
.left
, -rcWindow
.top
);
111 *prcTopLeft
= *prcBottomRight
= rcWindow
;
112 if (infoPtr
->dwStyle
& PGS_HORZ
)
114 prcTopLeft
->right
= prcTopLeft
->left
+ infoPtr
->nButtonSize
;
115 prcBottomRight
->left
= prcBottomRight
->right
- infoPtr
->nButtonSize
;
119 prcTopLeft
->bottom
= prcTopLeft
->top
+ infoPtr
->nButtonSize
;
120 prcBottomRight
->top
= prcBottomRight
->bottom
- infoPtr
->nButtonSize
;
124 /* the horizontal arrows are:
137 PAGER_DrawHorzArrow (HDC hdc
, RECT r
, INT colorRef
, BOOL left
)
142 w
= r
.right
- r
.left
+ 1;
143 h
= r
.bottom
- r
.top
+ 1;
144 if ((h
< MIN_ARROW_WIDTH
) || (w
< MIN_ARROW_HEIGHT
))
145 return; /* refuse to draw partial arrow */
147 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
148 hOldPen
= SelectObject ( hdc
, hPen
);
151 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 3;
152 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
153 MoveToEx (hdc
, x
, y
, NULL
);
154 LineTo (hdc
, x
--, y
+5); y
++;
155 MoveToEx (hdc
, x
, y
, NULL
);
156 LineTo (hdc
, x
--, y
+3); y
++;
157 MoveToEx (hdc
, x
, y
, NULL
);
158 LineTo (hdc
, x
, y
+1);
162 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
163 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
164 MoveToEx (hdc
, x
, y
, NULL
);
165 LineTo (hdc
, x
++, y
+5); y
++;
166 MoveToEx (hdc
, x
, y
, NULL
);
167 LineTo (hdc
, x
++, y
+3); y
++;
168 MoveToEx (hdc
, x
, y
, NULL
);
169 LineTo (hdc
, x
, y
+1);
172 SelectObject( hdc
, hOldPen
);
173 DeleteObject( hPen
);
176 /* the vertical arrows are:
186 PAGER_DrawVertArrow (HDC hdc
, RECT r
, INT colorRef
, BOOL up
)
191 w
= r
.right
- r
.left
+ 1;
192 h
= r
.bottom
- r
.top
+ 1;
193 if ((h
< MIN_ARROW_WIDTH
) || (w
< MIN_ARROW_HEIGHT
))
194 return; /* refuse to draw partial arrow */
196 if (!(hPen
= CreatePen( PS_SOLID
, 1, GetSysColor( colorRef
)))) return;
197 hOldPen
= SelectObject ( hdc
, hPen
);
200 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
201 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 3;
202 MoveToEx (hdc
, x
, y
, NULL
);
203 LineTo (hdc
, x
+5, y
--); x
++;
204 MoveToEx (hdc
, x
, y
, NULL
);
205 LineTo (hdc
, x
+3, y
--); x
++;
206 MoveToEx (hdc
, x
, y
, NULL
);
207 LineTo (hdc
, x
+1, y
);
211 x
= r
.left
+ ((w
- MIN_ARROW_HEIGHT
) / 2) + 1;
212 y
= r
.top
+ ((h
- MIN_ARROW_WIDTH
) / 2) + 1;
213 MoveToEx (hdc
, x
, y
, NULL
);
214 LineTo (hdc
, x
+5, y
++); x
++;
215 MoveToEx (hdc
, x
, y
, NULL
);
216 LineTo (hdc
, x
+3, y
++); x
++;
217 MoveToEx (hdc
, x
, y
, NULL
);
218 LineTo (hdc
, x
+1, y
);
221 SelectObject( hdc
, hOldPen
);
222 DeleteObject( hPen
);
226 PAGER_DrawButton(HDC hdc
, COLORREF clrBk
, RECT arrowRect
,
227 BOOL horz
, BOOL topLeft
, INT btnState
)
229 HBRUSH hBrush
, hOldBrush
;
232 TRACE("arrowRect = %s, btnState = %d\n", wine_dbgstr_rect(&arrowRect
), btnState
);
234 if (btnState
== PGF_INVISIBLE
)
237 if ((rc
.right
- rc
.left
<= 0) || (rc
.bottom
- rc
.top
<= 0))
240 hBrush
= CreateSolidBrush(clrBk
);
241 hOldBrush
= (HBRUSH
)SelectObject(hdc
, hBrush
);
243 FillRect(hdc
, &rc
, hBrush
);
245 if (btnState
== PGF_HOT
)
247 DrawEdge( hdc
, &rc
, BDR_RAISEDINNER
, BF_RECT
);
249 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
251 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
253 else if (btnState
== PGF_NORMAL
)
255 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
257 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
259 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
261 else if (btnState
== PGF_DEPRESSED
)
263 DrawEdge( hdc
, &rc
, BDR_SUNKENOUTER
, BF_RECT
);
265 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
267 PAGER_DrawVertArrow(hdc
, rc
, COLOR_WINDOWFRAME
, topLeft
);
269 else if (btnState
== PGF_GRAYED
)
271 DrawEdge (hdc
, &rc
, BDR_OUTER
, BF_FLAT
);
274 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
275 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
276 PAGER_DrawHorzArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
280 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DHIGHLIGHT
, topLeft
);
281 rc
.left
++, rc
.top
++; rc
.right
++, rc
.bottom
++;
282 PAGER_DrawVertArrow(hdc
, rc
, COLOR_3DSHADOW
, topLeft
);
286 SelectObject( hdc
, hOldBrush
);
287 DeleteObject(hBrush
);
290 /* << PAGER_GetDropTarget >> */
292 static inline LRESULT
293 PAGER_ForwardMouse (PAGER_INFO
* infoPtr
, BOOL bFwd
)
295 TRACE("[%p]\n", infoPtr
->hwndSelf
);
297 infoPtr
->bForward
= bFwd
;
302 static inline LRESULT
303 PAGER_GetButtonState (PAGER_INFO
* infoPtr
, INT btn
)
305 LRESULT btnState
= PGF_INVISIBLE
;
306 TRACE("[%p]\n", infoPtr
->hwndSelf
);
308 if (btn
== PGB_TOPORLEFT
)
309 btnState
= infoPtr
->TLbtnState
;
310 else if (btn
== PGB_BOTTOMORRIGHT
)
311 btnState
= infoPtr
->BRbtnState
;
318 PAGER_GetPos(PAGER_INFO
*infoPtr
)
320 TRACE("[%p] returns %d\n", infoPtr
->hwndSelf
, infoPtr
->nPos
);
321 return infoPtr
->nPos
;
325 PAGER_GetButtonSize(PAGER_INFO
*infoPtr
)
327 TRACE("[%p] returns %d\n", infoPtr
->hwndSelf
, infoPtr
->nButtonSize
);
328 return infoPtr
->nButtonSize
;
332 PAGER_GetBorder(PAGER_INFO
*infoPtr
)
334 TRACE("[%p] returns %d\n", infoPtr
->hwndSelf
, infoPtr
->nBorder
);
335 return infoPtr
->nBorder
;
338 static inline COLORREF
339 PAGER_GetBkColor(PAGER_INFO
*infoPtr
)
341 TRACE("[%p] returns %06lx\n", infoPtr
->hwndSelf
, infoPtr
->clrBk
);
342 return infoPtr
->clrBk
;
346 PAGER_CalcSize (PAGER_INFO
*infoPtr
, INT
* size
, BOOL getWidth
)
349 ZeroMemory (&nmpgcs
, sizeof (NMPGCALCSIZE
));
350 nmpgcs
.hdr
.hwndFrom
= infoPtr
->hwndSelf
;
351 nmpgcs
.hdr
.idFrom
= GetWindowLongPtrW (infoPtr
->hwndSelf
, GWLP_ID
);
352 nmpgcs
.hdr
.code
= PGN_CALCSIZE
;
353 nmpgcs
.dwFlag
= getWidth
? PGF_CALCWIDTH
: PGF_CALCHEIGHT
;
354 nmpgcs
.iWidth
= getWidth
? *size
: 0;
355 nmpgcs
.iHeight
= getWidth
? 0 : *size
;
356 SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
357 (WPARAM
)nmpgcs
.hdr
.idFrom
, (LPARAM
)&nmpgcs
);
359 *size
= getWidth
? nmpgcs
.iWidth
: nmpgcs
.iHeight
;
361 TRACE("[%p] PGN_CALCSIZE returns %s=%d\n", infoPtr
->hwndSelf
,
362 getWidth
? "width" : "height", *size
);
366 PAGER_PositionChildWnd(PAGER_INFO
* infoPtr
)
368 if (infoPtr
->hwndChild
)
371 int nPos
= infoPtr
->nPos
;
373 /* compensate for a grayed btn, which will soon become invisible */
374 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
375 nPos
+= infoPtr
->nButtonSize
;
377 GetClientRect(infoPtr
->hwndSelf
, &rcClient
);
379 if (infoPtr
->dwStyle
& PGS_HORZ
)
381 int wndSize
= max(0, rcClient
.right
- rcClient
.left
);
382 if (infoPtr
->nWidth
< wndSize
)
383 infoPtr
->nWidth
= wndSize
;
385 TRACE("[%p] SWP %dx%d at (%d,%d)\n", infoPtr
->hwndSelf
,
386 infoPtr
->nWidth
, infoPtr
->nHeight
,
388 SetWindowPos(infoPtr
->hwndChild
, 0,
390 infoPtr
->nWidth
, infoPtr
->nHeight
,
395 int wndSize
= max(0, rcClient
.bottom
- rcClient
.top
);
396 if (infoPtr
->nHeight
< wndSize
)
397 infoPtr
->nHeight
= wndSize
;
399 TRACE("[%p] SWP %dx%d at (%d,%d)\n", infoPtr
->hwndSelf
,
400 infoPtr
->nWidth
, infoPtr
->nHeight
,
402 SetWindowPos(infoPtr
->hwndChild
, 0,
404 infoPtr
->nWidth
, infoPtr
->nHeight
,
408 InvalidateRect(infoPtr
->hwndChild
, NULL
, TRUE
);
413 PAGER_GetScrollRange(PAGER_INFO
* infoPtr
)
417 if (infoPtr
->hwndChild
)
419 INT wndSize
, childSize
;
421 GetWindowRect(infoPtr
->hwndSelf
, &wndRect
);
423 if (infoPtr
->dwStyle
& PGS_HORZ
)
425 wndSize
= wndRect
.right
- wndRect
.left
;
426 PAGER_CalcSize(infoPtr
, &infoPtr
->nWidth
, TRUE
);
427 childSize
= infoPtr
->nWidth
;
431 wndSize
= wndRect
.bottom
- wndRect
.top
;
432 PAGER_CalcSize(infoPtr
, &infoPtr
->nHeight
, FALSE
);
433 childSize
= infoPtr
->nHeight
;
436 TRACE("childSize = %d, wndSize = %d\n", childSize
, wndSize
);
437 if (childSize
> wndSize
)
438 scrollRange
= childSize
- wndSize
+ infoPtr
->nButtonSize
;
441 TRACE("[%p] returns %d\n", infoPtr
->hwndSelf
, scrollRange
);
446 PAGER_UpdateBtns(PAGER_INFO
*infoPtr
, INT scrollRange
, BOOL hideGrayBtns
)
450 INT oldTLbtnState
= infoPtr
->TLbtnState
;
451 INT oldBRbtnState
= infoPtr
->BRbtnState
;
453 RECT rcTopLeft
, rcBottomRight
;
455 /* get button rects */
456 PAGER_GetButtonRects(infoPtr
, &rcTopLeft
, &rcBottomRight
, FALSE
);
460 /* update states based on scroll position */
461 if (infoPtr
->nPos
> 0)
463 if (infoPtr
->TLbtnState
== PGF_INVISIBLE
|| infoPtr
->TLbtnState
== PGF_GRAYED
)
464 infoPtr
->TLbtnState
= PGF_NORMAL
;
466 else if (PtInRect(&rcTopLeft
, pt
))
467 infoPtr
->TLbtnState
= PGF_GRAYED
;
469 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
471 if (scrollRange
<= 0)
473 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
474 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
476 else if (infoPtr
->nPos
< scrollRange
)
478 if (infoPtr
->BRbtnState
== PGF_INVISIBLE
|| infoPtr
->BRbtnState
== PGF_GRAYED
)
479 infoPtr
->BRbtnState
= PGF_NORMAL
;
481 else if (PtInRect(&rcBottomRight
, pt
))
482 infoPtr
->BRbtnState
= PGF_GRAYED
;
484 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
486 /* only need to resize when entering or leaving PGF_INVISIBLE state */
488 ((oldTLbtnState
== PGF_INVISIBLE
) != (infoPtr
->TLbtnState
== PGF_INVISIBLE
)) ||
489 ((oldBRbtnState
== PGF_INVISIBLE
) != (infoPtr
->BRbtnState
== PGF_INVISIBLE
));
490 /* initiate NCCalcSize to resize client wnd if necessary */
492 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
493 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
494 SWP_NOZORDER
| SWP_NOACTIVATE
);
496 /* repaint when changing any state */
497 repaintBtns
= (oldTLbtnState
!= infoPtr
->TLbtnState
) ||
498 (oldBRbtnState
!= infoPtr
->BRbtnState
);
500 SendMessageW(infoPtr
->hwndSelf
, WM_NCPAINT
, 0, 0);
504 PAGER_SetPos(PAGER_INFO
* infoPtr
, INT newPos
, BOOL fromBtnPress
)
506 INT scrollRange
= PAGER_GetScrollRange(infoPtr
);
507 INT oldPos
= infoPtr
->nPos
;
509 if ((scrollRange
<= 0) || (newPos
< 0))
511 else if (newPos
> scrollRange
)
512 infoPtr
->nPos
= scrollRange
;
514 infoPtr
->nPos
= newPos
;
516 TRACE("[%p] pos=%d, oldpos=%d\n", infoPtr
->hwndSelf
, infoPtr
->nPos
, oldPos
);
518 if (infoPtr
->nPos
!= oldPos
)
520 /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
521 PAGER_UpdateBtns(infoPtr
, scrollRange
, !fromBtnPress
);
522 PAGER_PositionChildWnd(infoPtr
);
529 PAGER_WindowPosChanging(PAGER_INFO
* infoPtr
, WINDOWPOS
*winpos
)
531 if ((infoPtr
->dwStyle
& CCS_NORESIZE
) && !(winpos
->flags
& SWP_NOSIZE
))
533 /* don't let the app resize the nonscrollable dimension of a control
534 * that was created with CCS_NORESIZE style
535 * (i.e. height for a horizontal pager, or width for a vertical one) */
537 /* except if the current dimension is 0 and app is setting for
538 * first time, then save amount as dimension. - GA 8/01 */
540 if (infoPtr
->dwStyle
& PGS_HORZ
)
541 if (!infoPtr
->nHeight
&& winpos
->cy
)
542 infoPtr
->nHeight
= winpos
->cy
;
544 winpos
->cy
= infoPtr
->nHeight
;
546 if (!infoPtr
->nWidth
&& winpos
->cx
)
547 infoPtr
->nWidth
= winpos
->cx
;
549 winpos
->cx
= infoPtr
->nWidth
;
553 return DefWindowProcW (infoPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)winpos
);
557 PAGER_SetFixedWidth(PAGER_INFO
* infoPtr
)
559 /* Must set the non-scrollable dimension to be less than the full height/width
560 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
561 * size, and experimentation shows that affect is almost right. */
565 GetWindowRect(infoPtr
->hwndSelf
, &wndRect
);
567 /* see what the app says for btn width */
568 PAGER_CalcSize(infoPtr
, &infoPtr
->nWidth
, TRUE
);
570 if (infoPtr
->dwStyle
& CCS_NORESIZE
)
572 delta
= wndRect
.right
- wndRect
.left
- infoPtr
->nWidth
;
573 if (delta
> infoPtr
->nButtonSize
)
574 infoPtr
->nWidth
+= 4 * infoPtr
->nButtonSize
/ 3;
576 infoPtr
->nWidth
+= infoPtr
->nButtonSize
/ 3;
579 h
= wndRect
.bottom
- wndRect
.top
+ infoPtr
->nButtonSize
;
581 TRACE("[%p] infoPtr->nWidth set to %d\n",
582 infoPtr
->hwndSelf
, infoPtr
->nWidth
);
588 PAGER_SetFixedHeight(PAGER_INFO
* infoPtr
)
590 /* Must set the non-scrollable dimension to be less than the full height/width
591 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
592 * size, and experimentation shows that affect is almost right. */
596 GetWindowRect(infoPtr
->hwndSelf
, &wndRect
);
598 /* see what the app says for btn height */
599 PAGER_CalcSize(infoPtr
, &infoPtr
->nHeight
, FALSE
);
601 if (infoPtr
->dwStyle
& CCS_NORESIZE
)
603 delta
= wndRect
.bottom
- wndRect
.top
- infoPtr
->nHeight
;
604 if (delta
> infoPtr
->nButtonSize
)
605 infoPtr
->nHeight
+= infoPtr
->nButtonSize
;
607 infoPtr
->nHeight
+= infoPtr
->nButtonSize
/ 3;
610 w
= wndRect
.right
- wndRect
.left
+ infoPtr
->nButtonSize
;
612 TRACE("[%p] infoPtr->nHeight set to %d\n",
613 infoPtr
->hwndSelf
, infoPtr
->nHeight
);
618 /******************************************************************
619 * For the PGM_RECALCSIZE message (but not the other uses in *
620 * this module), the native control does only the following: *
622 * if (some condition) *
623 * PostMessageW(hwnd, EM_FMTLINES, 0, 0); *
624 * return DefWindowProcW(hwnd, PGM_RECALCSIZE, 0, 0); *
626 * When we figure out what the "some condition" is we will *
627 * implement that for the message processing. *
628 ******************************************************************/
631 PAGER_RecalcSize(PAGER_INFO
*infoPtr
)
633 TRACE("[%p]\n", infoPtr
->hwndSelf
);
635 if (infoPtr
->hwndChild
)
637 INT scrollRange
= PAGER_GetScrollRange(infoPtr
);
639 if (scrollRange
<= 0)
642 PAGER_SetPos(infoPtr
, 0, FALSE
);
645 PAGER_PositionChildWnd(infoPtr
);
653 PAGER_SetBkColor (PAGER_INFO
* infoPtr
, COLORREF clrBk
)
655 COLORREF clrTemp
= infoPtr
->clrBk
;
657 infoPtr
->clrBk
= clrBk
;
658 TRACE("[%p] %06lx\n", infoPtr
->hwndSelf
, infoPtr
->clrBk
);
660 /* the native control seems to do things this way */
661 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
662 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
663 SWP_NOZORDER
| SWP_NOACTIVATE
);
665 RedrawWindow(infoPtr
->hwndSelf
, 0, 0, RDW_ERASE
| RDW_INVALIDATE
);
672 PAGER_SetBorder (PAGER_INFO
* infoPtr
, INT iBorder
)
674 INT nTemp
= infoPtr
->nBorder
;
676 infoPtr
->nBorder
= iBorder
;
677 TRACE("[%p] %d\n", infoPtr
->hwndSelf
, infoPtr
->nBorder
);
679 PAGER_RecalcSize(infoPtr
);
686 PAGER_SetButtonSize (PAGER_INFO
* infoPtr
, INT iButtonSize
)
688 INT nTemp
= infoPtr
->nButtonSize
;
690 infoPtr
->nButtonSize
= iButtonSize
;
691 TRACE("[%p] %d\n", infoPtr
->hwndSelf
, infoPtr
->nButtonSize
);
693 PAGER_RecalcSize(infoPtr
);
700 PAGER_SetChild (PAGER_INFO
* infoPtr
, HWND hwndChild
)
704 infoPtr
->hwndChild
= IsWindow (hwndChild
) ? hwndChild
: 0;
706 if (infoPtr
->hwndChild
)
708 TRACE("[%p] hwndChild=%p\n", infoPtr
->hwndSelf
, infoPtr
->hwndChild
);
710 if (infoPtr
->dwStyle
& PGS_HORZ
) {
711 hw
= PAGER_SetFixedHeight(infoPtr
);
712 /* adjust non-scrollable dimension to fit the child */
713 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, hw
, infoPtr
->nHeight
,
714 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
715 SWP_NOSIZE
| SWP_NOACTIVATE
);
718 hw
= PAGER_SetFixedWidth(infoPtr
);
719 /* adjust non-scrollable dimension to fit the child */
720 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, infoPtr
->nWidth
, hw
,
721 SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOZORDER
|
722 SWP_NOSIZE
| SWP_NOACTIVATE
);
725 /* position child within the page scroller */
726 SetWindowPos(infoPtr
->hwndChild
, HWND_TOP
,
728 SWP_SHOWWINDOW
| SWP_NOSIZE
); /* native is 0 */
731 PAGER_SetPos(infoPtr
, 0, FALSE
);
738 PAGER_Scroll(PAGER_INFO
* infoPtr
, INT dir
)
740 NMPGSCROLL nmpgScroll
;
743 if (infoPtr
->hwndChild
)
745 ZeroMemory (&nmpgScroll
, sizeof (NMPGSCROLL
));
746 nmpgScroll
.hdr
.hwndFrom
= infoPtr
->hwndSelf
;
747 nmpgScroll
.hdr
.idFrom
= GetWindowLongPtrW (infoPtr
->hwndSelf
, GWLP_ID
);
748 nmpgScroll
.hdr
.code
= PGN_SCROLL
;
750 GetWindowRect(infoPtr
->hwndSelf
, &rcWnd
);
751 GetClientRect(infoPtr
->hwndSelf
, &nmpgScroll
.rcParent
);
752 nmpgScroll
.iXpos
= nmpgScroll
.iYpos
= 0;
753 nmpgScroll
.iDir
= dir
;
755 if (infoPtr
->dwStyle
& PGS_HORZ
)
757 nmpgScroll
.iScroll
= rcWnd
.right
- rcWnd
.left
;
758 nmpgScroll
.iXpos
= infoPtr
->nPos
;
762 nmpgScroll
.iScroll
= rcWnd
.bottom
- rcWnd
.top
;
763 nmpgScroll
.iYpos
= infoPtr
->nPos
;
765 nmpgScroll
.iScroll
-= 2*infoPtr
->nButtonSize
;
767 SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
768 (WPARAM
)nmpgScroll
.hdr
.idFrom
, (LPARAM
)&nmpgScroll
);
770 TRACE("[%p] PGN_SCROLL returns iScroll=%d\n", infoPtr
->hwndSelf
, nmpgScroll
.iScroll
);
772 if (nmpgScroll
.iScroll
> 0)
774 infoPtr
->direction
= dir
;
776 if (dir
== PGF_SCROLLLEFT
|| dir
== PGF_SCROLLUP
)
777 PAGER_SetPos(infoPtr
, infoPtr
->nPos
- nmpgScroll
.iScroll
, TRUE
);
779 PAGER_SetPos(infoPtr
, infoPtr
->nPos
+ nmpgScroll
.iScroll
, TRUE
);
782 infoPtr
->direction
= -1;
787 PAGER_FmtLines(PAGER_INFO
*infoPtr
)
789 /* initiate NCCalcSize to resize client wnd and get size */
790 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
791 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
792 SWP_NOZORDER
| SWP_NOACTIVATE
);
794 SetWindowPos(infoPtr
->hwndChild
, 0,
795 0,0,infoPtr
->nWidth
,infoPtr
->nHeight
,
798 return DefWindowProcW (infoPtr
->hwndSelf
, EM_FMTLINES
, 0, 0);
802 PAGER_Create (HWND hwnd
, LPCREATESTRUCTW lpcs
)
806 /* allocate memory for info structure */
807 infoPtr
= (PAGER_INFO
*)Alloc (sizeof(PAGER_INFO
));
808 if (!infoPtr
) return -1;
809 SetWindowLongPtrW (hwnd
, 0, (DWORD_PTR
)infoPtr
);
811 /* set default settings */
812 infoPtr
->hwndSelf
= hwnd
;
813 infoPtr
->hwndChild
= NULL
;
814 infoPtr
->hwndNotify
= lpcs
->hwndParent
;
815 infoPtr
->dwStyle
= lpcs
->style
;
816 infoPtr
->clrBk
= GetSysColor(COLOR_BTNFACE
);
817 infoPtr
->nBorder
= 0;
818 infoPtr
->nButtonSize
= 12;
821 infoPtr
->nHeight
= 0;
822 infoPtr
->bForward
= FALSE
;
823 infoPtr
->bCapture
= FALSE
;
824 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
825 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
826 infoPtr
->direction
= -1;
828 if (infoPtr
->dwStyle
& PGS_DRAGNDROP
)
829 FIXME("[%p] Drag and Drop style is not implemented yet.\n", infoPtr
->hwndSelf
);
836 PAGER_Destroy (PAGER_INFO
*infoPtr
)
838 SetWindowLongPtrW (infoPtr
->hwndSelf
, 0, 0);
839 Free (infoPtr
); /* free pager info data */
844 PAGER_NCCalcSize(PAGER_INFO
* infoPtr
, WPARAM wParam
, LPRECT lpRect
)
846 RECT rcChild
, rcWindow
;
850 * lpRect points to a RECT struct. On entry, the struct
851 * contains the proposed wnd rectangle for the window.
852 * On exit, the struct should contain the screen
853 * coordinates of the corresponding window's client area.
856 DefWindowProcW (infoPtr
->hwndSelf
, WM_NCCALCSIZE
, wParam
, (LPARAM
)lpRect
);
858 TRACE("orig rect=%s\n", wine_dbgstr_rect(lpRect
));
860 GetWindowRect (infoPtr
->hwndChild
, &rcChild
);
861 MapWindowPoints (0, infoPtr
->hwndSelf
, (LPPOINT
)&rcChild
, 2); /* FIXME: RECT != 2 POINTS */
862 GetWindowRect (infoPtr
->hwndSelf
, &rcWindow
);
864 if (infoPtr
->dwStyle
& PGS_HORZ
)
866 infoPtr
->nWidth
= lpRect
->right
- lpRect
->left
;
867 PAGER_CalcSize (infoPtr
, &infoPtr
->nWidth
, TRUE
);
869 scrollRange
= infoPtr
->nWidth
- (rcWindow
.right
- rcWindow
.left
);
871 if (infoPtr
->TLbtnState
&& (lpRect
->left
+ infoPtr
->nButtonSize
< lpRect
->right
))
872 lpRect
->left
+= infoPtr
->nButtonSize
;
873 if (infoPtr
->BRbtnState
&& (lpRect
->right
- infoPtr
->nButtonSize
> lpRect
->left
))
874 lpRect
->right
-= infoPtr
->nButtonSize
;
878 infoPtr
->nHeight
= lpRect
->bottom
- lpRect
->top
;
879 PAGER_CalcSize (infoPtr
, &infoPtr
->nHeight
, FALSE
);
881 scrollRange
= infoPtr
->nHeight
- (rcWindow
.bottom
- rcWindow
.top
);
883 if (infoPtr
->TLbtnState
&& (lpRect
->top
+ infoPtr
->nButtonSize
< lpRect
->bottom
))
884 lpRect
->top
+= infoPtr
->nButtonSize
;
885 if (infoPtr
->BRbtnState
&& (lpRect
->bottom
- infoPtr
->nButtonSize
> lpRect
->top
))
886 lpRect
->bottom
-= infoPtr
->nButtonSize
;
889 TRACE("nPos=%d, nHeigth=%d, window=%s\n",
890 infoPtr
->nPos
, infoPtr
->nHeight
,
891 wine_dbgstr_rect(&rcWindow
));
893 TRACE("[%p] client rect set to %ldx%ld at (%ld,%ld) BtnState[%d,%d]\n",
894 infoPtr
->hwndSelf
, lpRect
->right
-lpRect
->left
, lpRect
->bottom
-lpRect
->top
,
895 lpRect
->left
, lpRect
->top
,
896 infoPtr
->TLbtnState
, infoPtr
->BRbtnState
);
902 PAGER_NCPaint (PAGER_INFO
* infoPtr
, HRGN hRgn
)
904 RECT rcBottomRight
, rcTopLeft
;
907 if (infoPtr
->dwStyle
& WS_MINIMIZE
)
910 DefWindowProcW (infoPtr
->hwndSelf
, WM_NCPAINT
, (WPARAM
)hRgn
, 0);
912 if (!(hdc
= GetDCEx (infoPtr
->hwndSelf
, 0, DCX_USESTYLE
| DCX_WINDOW
)))
915 PAGER_GetButtonRects(infoPtr
, &rcTopLeft
, &rcBottomRight
, FALSE
);
917 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcTopLeft
,
918 infoPtr
->dwStyle
& PGS_HORZ
, TRUE
, infoPtr
->TLbtnState
);
919 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, rcBottomRight
,
920 infoPtr
->dwStyle
& PGS_HORZ
, FALSE
, infoPtr
->BRbtnState
);
922 ReleaseDC( infoPtr
->hwndSelf
, hdc
);
927 PAGER_HitTest (PAGER_INFO
* infoPtr
, const POINT
* pt
)
929 RECT clientRect
, rcTopLeft
, rcBottomRight
;
932 GetClientRect (infoPtr
->hwndSelf
, &clientRect
);
934 if (PtInRect(&clientRect
, *pt
))
941 PAGER_GetButtonRects(infoPtr
, &rcTopLeft
, &rcBottomRight
, TRUE
);
943 if ((infoPtr
->TLbtnState
!= PGF_INVISIBLE
) && PtInRect(&rcTopLeft
, ptWindow
))
945 TRACE("PGB_TOPORLEFT\n");
946 return PGB_TOPORLEFT
;
948 else if ((infoPtr
->BRbtnState
!= PGF_INVISIBLE
) && PtInRect(&rcBottomRight
, ptWindow
))
950 TRACE("PGB_BOTTOMORRIGHT\n");
951 return PGB_BOTTOMORRIGHT
;
959 PAGER_NCHitTest (PAGER_INFO
* infoPtr
, INT x
, INT y
)
967 ScreenToClient (infoPtr
->hwndSelf
, &pt
);
968 nHit
= PAGER_HitTest(infoPtr
, &pt
);
970 return (nHit
< 0) ? HTTRANSPARENT
: HTCLIENT
;
974 PAGER_MouseMove (PAGER_INFO
* infoPtr
, INT keys
, INT x
, INT y
)
977 RECT wnrect
, *btnrect
= NULL
;
978 BOOL topLeft
= FALSE
;
986 TRACE("[%p] to (%d,%d)\n", infoPtr
->hwndSelf
, x
, y
);
987 ClientToScreen(infoPtr
->hwndSelf
, &pt
);
988 GetWindowRect(infoPtr
->hwndSelf
, &wnrect
);
989 if (PtInRect(&wnrect
, pt
)) {
990 RECT TLbtnrect
, BRbtnrect
;
991 PAGER_GetButtonRects(infoPtr
, &TLbtnrect
, &BRbtnrect
, FALSE
);
994 MapWindowPoints(0, infoPtr
->hwndSelf
, &clpt
, 1);
995 hit
= PAGER_HitTest(infoPtr
, &clpt
);
996 if ((hit
== PGB_TOPORLEFT
) && (infoPtr
->TLbtnState
== PGF_NORMAL
))
999 btnrect
= &TLbtnrect
;
1000 infoPtr
->TLbtnState
= PGF_HOT
;
1001 btnstate
= infoPtr
->TLbtnState
;
1003 else if ((hit
== PGB_BOTTOMORRIGHT
) && (infoPtr
->BRbtnState
== PGF_NORMAL
))
1006 btnrect
= &BRbtnrect
;
1007 infoPtr
->BRbtnState
= PGF_HOT
;
1008 btnstate
= infoPtr
->BRbtnState
;
1011 /* If in one of the buttons the capture and draw buttons */
1014 TRACE("[%p] draw btn (%ld,%ld)-(%ld,%ld), Capture %s, style %08lx\n",
1015 infoPtr
->hwndSelf
, btnrect
->left
, btnrect
->top
,
1016 btnrect
->right
, btnrect
->bottom
,
1017 (infoPtr
->bCapture
) ? "TRUE" : "FALSE",
1019 if (!infoPtr
->bCapture
)
1021 TRACE("[%p] SetCapture\n", infoPtr
->hwndSelf
);
1022 SetCapture(infoPtr
->hwndSelf
);
1023 infoPtr
->bCapture
= TRUE
;
1025 if (infoPtr
->dwStyle
& PGS_AUTOSCROLL
)
1026 SetTimer(infoPtr
->hwndSelf
, TIMERID1
, 0x3e, 0);
1027 hdc
= GetWindowDC(infoPtr
->hwndSelf
);
1028 /* OffsetRect(wnrect, 0 | 1, 0 | 1) */
1029 PAGER_DrawButton(hdc
, infoPtr
->clrBk
, *btnrect
,
1030 infoPtr
->dwStyle
& PGS_HORZ
, topLeft
, btnstate
);
1031 ReleaseDC(infoPtr
->hwndSelf
, hdc
);
1036 /* If we think we are captured, then do release */
1037 if (infoPtr
->bCapture
&& (WindowFromPoint(pt
) != infoPtr
->hwndSelf
))
1041 infoPtr
->bCapture
= FALSE
;
1043 if (GetCapture() == infoPtr
->hwndSelf
)
1047 if (infoPtr
->TLbtnState
== PGF_GRAYED
)
1049 infoPtr
->TLbtnState
= PGF_INVISIBLE
;
1050 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
1051 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1052 SWP_NOZORDER
| SWP_NOACTIVATE
);
1054 else if (infoPtr
->TLbtnState
== PGF_HOT
)
1056 infoPtr
->TLbtnState
= PGF_NORMAL
;
1057 /* FIXME: just invalidate button rect */
1058 RedrawWindow(infoPtr
->hwndSelf
, NULL
, NULL
, RDW_FRAME
| RDW_INVALIDATE
);
1061 if (infoPtr
->BRbtnState
== PGF_GRAYED
)
1063 infoPtr
->BRbtnState
= PGF_INVISIBLE
;
1064 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
1065 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1066 SWP_NOZORDER
| SWP_NOACTIVATE
);
1068 else if (infoPtr
->BRbtnState
== PGF_HOT
)
1070 infoPtr
->BRbtnState
= PGF_NORMAL
;
1071 /* FIXME: just invalidate button rect */
1072 RedrawWindow(infoPtr
->hwndSelf
, NULL
, NULL
, RDW_FRAME
| RDW_INVALIDATE
);
1075 /* Notify parent of released mouse capture */
1076 memset(&nmhdr
, 0, sizeof(NMHDR
));
1077 nmhdr
.hwndFrom
= infoPtr
->hwndSelf
;
1078 nmhdr
.idFrom
= GetWindowLongPtrW(infoPtr
->hwndSelf
, GWLP_ID
);
1079 nmhdr
.code
= NM_RELEASEDCAPTURE
;
1080 SendMessageW(infoPtr
->hwndNotify
, WM_NOTIFY
,
1081 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
1083 if (IsWindow(infoPtr
->hwndSelf
))
1084 KillTimer(infoPtr
->hwndSelf
, TIMERID1
);
1090 PAGER_LButtonDown (PAGER_INFO
* infoPtr
, INT keys
, INT x
, INT y
)
1092 BOOL repaintBtns
= FALSE
;
1099 TRACE("[%p] at (%d,%d)\n", infoPtr
->hwndSelf
, x
, y
);
1101 hit
= PAGER_HitTest(infoPtr
, &pt
);
1103 /* put btn in DEPRESSED state */
1104 if (hit
== PGB_TOPORLEFT
)
1106 repaintBtns
= infoPtr
->TLbtnState
!= PGF_DEPRESSED
;
1107 infoPtr
->TLbtnState
= PGF_DEPRESSED
;
1108 SetTimer(infoPtr
->hwndSelf
, TIMERID1
, INITIAL_DELAY
, 0);
1110 else if (hit
== PGB_BOTTOMORRIGHT
)
1112 repaintBtns
= infoPtr
->BRbtnState
!= PGF_DEPRESSED
;
1113 infoPtr
->BRbtnState
= PGF_DEPRESSED
;
1114 SetTimer(infoPtr
->hwndSelf
, TIMERID1
, INITIAL_DELAY
, 0);
1118 SendMessageW(infoPtr
->hwndSelf
, WM_NCPAINT
, 0, 0);
1123 if (infoPtr
->dwStyle
& PGS_HORZ
)
1125 TRACE("[%p] PGF_SCROLLLEFT\n", infoPtr
->hwndSelf
);
1126 PAGER_Scroll(infoPtr
, PGF_SCROLLLEFT
);
1130 TRACE("[%p] PGF_SCROLLUP\n", infoPtr
->hwndSelf
);
1131 PAGER_Scroll(infoPtr
, PGF_SCROLLUP
);
1134 case PGB_BOTTOMORRIGHT
:
1135 if (infoPtr
->dwStyle
& PGS_HORZ
)
1137 TRACE("[%p] PGF_SCROLLRIGHT\n", infoPtr
->hwndSelf
);
1138 PAGER_Scroll(infoPtr
, PGF_SCROLLRIGHT
);
1142 TRACE("[%p] PGF_SCROLLDOWN\n", infoPtr
->hwndSelf
);
1143 PAGER_Scroll(infoPtr
, PGF_SCROLLDOWN
);
1154 PAGER_LButtonUp (PAGER_INFO
* infoPtr
, INT keys
, INT x
, INT y
)
1156 TRACE("[%p]\n", infoPtr
->hwndSelf
);
1158 KillTimer (infoPtr
->hwndSelf
, TIMERID1
);
1159 KillTimer (infoPtr
->hwndSelf
, TIMERID2
);
1161 /* make PRESSED btns NORMAL but don't hide gray btns */
1162 if (infoPtr
->TLbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
1163 infoPtr
->TLbtnState
= PGF_NORMAL
;
1164 if (infoPtr
->BRbtnState
& (PGF_HOT
| PGF_DEPRESSED
))
1165 infoPtr
->BRbtnState
= PGF_NORMAL
;
1171 PAGER_Timer (PAGER_INFO
* infoPtr
, INT nTimerId
)
1175 /* if initial timer, kill it and start the repeat timer */
1176 if (nTimerId
== TIMERID1
) {
1177 if (infoPtr
->TLbtnState
== PGF_HOT
)
1178 dir
= (infoPtr
->dwStyle
& PGS_HORZ
) ?
1179 PGF_SCROLLLEFT
: PGF_SCROLLUP
;
1181 dir
= (infoPtr
->dwStyle
& PGS_HORZ
) ?
1182 PGF_SCROLLRIGHT
: PGF_SCROLLDOWN
;
1183 TRACE("[%p] TIMERID1: style=%08lx, dir=%d\n",
1184 infoPtr
->hwndSelf
, infoPtr
->dwStyle
, dir
);
1185 KillTimer(infoPtr
->hwndSelf
, TIMERID1
);
1186 SetTimer(infoPtr
->hwndSelf
, TIMERID1
, REPEAT_DELAY
, 0);
1187 if (infoPtr
->dwStyle
& PGS_AUTOSCROLL
) {
1188 PAGER_Scroll(infoPtr
, dir
);
1189 SetWindowPos(infoPtr
->hwndSelf
, 0, 0, 0, 0, 0,
1190 SWP_FRAMECHANGED
| SWP_NOSIZE
| SWP_NOMOVE
|
1191 SWP_NOZORDER
| SWP_NOACTIVATE
);
1197 TRACE("[%p] TIMERID2: dir=%d\n", infoPtr
->hwndSelf
, infoPtr
->direction
);
1198 KillTimer(infoPtr
->hwndSelf
, TIMERID2
);
1199 if (infoPtr
->direction
> 0) {
1200 PAGER_Scroll(infoPtr
, infoPtr
->direction
);
1201 SetTimer(infoPtr
->hwndSelf
, TIMERID2
, REPEAT_DELAY
, 0);
1207 PAGER_EraseBackground (PAGER_INFO
* infoPtr
, HDC hdc
)
1214 parent
= GetParent(infoPtr
->hwndSelf
);
1215 MapWindowPoints(infoPtr
->hwndSelf
, parent
, &pt
, 1);
1216 OffsetWindowOrgEx (hdc
, pt
.x
, pt
.y
, &ptorig
);
1217 SendMessageW (parent
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1218 SetWindowOrgEx (hdc
, ptorig
.x
, ptorig
.y
, 0);
1225 PAGER_Size (PAGER_INFO
* infoPtr
, INT type
, INT x
, INT y
)
1227 /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
1229 TRACE("[%p] %d,%d\n", infoPtr
->hwndSelf
, x
, y
);
1231 if (infoPtr
->dwStyle
& PGS_HORZ
)
1232 infoPtr
->nHeight
= y
;
1234 infoPtr
->nWidth
= x
;
1236 return PAGER_RecalcSize(infoPtr
);
1241 PAGER_StyleChanged(PAGER_INFO
*infoPtr
, WPARAM wStyleType
, LPSTYLESTRUCT lpss
)
1243 DWORD oldStyle
= infoPtr
->dwStyle
;
1245 TRACE("(styletype=%x, styleOld=0x%08lx, styleNew=0x%08lx)\n",
1246 wStyleType
, lpss
->styleOld
, lpss
->styleNew
);
1248 if (wStyleType
!= GWL_STYLE
) return 0;
1250 infoPtr
->dwStyle
= lpss
->styleNew
;
1252 if ((oldStyle
^ lpss
->styleNew
) & (PGS_HORZ
| PGS_VERT
))
1254 PAGER_RecalcSize(infoPtr
);
1260 static LRESULT WINAPI
1261 PAGER_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1263 PAGER_INFO
*infoPtr
= (PAGER_INFO
*)GetWindowLongPtrW(hwnd
, 0);
1265 if (!infoPtr
&& (uMsg
!= WM_CREATE
))
1266 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
1271 return PAGER_FmtLines(infoPtr
);
1273 case PGM_FORWARDMOUSE
:
1274 return PAGER_ForwardMouse (infoPtr
, (BOOL
)wParam
);
1276 case PGM_GETBKCOLOR
:
1277 return PAGER_GetBkColor(infoPtr
);
1280 return PAGER_GetBorder(infoPtr
);
1282 case PGM_GETBUTTONSIZE
:
1283 return PAGER_GetButtonSize(infoPtr
);
1286 return PAGER_GetPos(infoPtr
);
1288 case PGM_GETBUTTONSTATE
:
1289 return PAGER_GetButtonState (infoPtr
, (INT
)lParam
);
1291 /* case PGM_GETDROPTARGET: */
1293 case PGM_RECALCSIZE
:
1294 return PAGER_RecalcSize(infoPtr
);
1296 case PGM_SETBKCOLOR
:
1297 return PAGER_SetBkColor (infoPtr
, (COLORREF
)lParam
);
1300 return PAGER_SetBorder (infoPtr
, (INT
)lParam
);
1302 case PGM_SETBUTTONSIZE
:
1303 return PAGER_SetButtonSize (infoPtr
, (INT
)lParam
);
1306 return PAGER_SetChild (infoPtr
, (HWND
)lParam
);
1309 return PAGER_SetPos(infoPtr
, (INT
)lParam
, FALSE
);
1312 return PAGER_Create (hwnd
, (LPCREATESTRUCTW
)lParam
);
1315 return PAGER_Destroy (infoPtr
);
1318 return PAGER_Size (infoPtr
, (INT
)wParam
, GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
1321 return PAGER_NCPaint (infoPtr
, (HRGN
)wParam
);
1323 case WM_WINDOWPOSCHANGING
:
1324 return PAGER_WindowPosChanging (infoPtr
, (WINDOWPOS
*)lParam
);
1326 case WM_STYLECHANGED
:
1327 return PAGER_StyleChanged(infoPtr
, wParam
, (LPSTYLESTRUCT
)lParam
);
1330 return PAGER_NCCalcSize (infoPtr
, wParam
, (LPRECT
)lParam
);
1333 return PAGER_NCHitTest (infoPtr
, GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
1336 if (infoPtr
->bForward
&& infoPtr
->hwndChild
)
1337 PostMessageW(infoPtr
->hwndChild
, WM_MOUSEMOVE
, wParam
, lParam
);
1338 return PAGER_MouseMove (infoPtr
, (INT
)wParam
, GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
1340 case WM_LBUTTONDOWN
:
1341 return PAGER_LButtonDown (infoPtr
, (INT
)wParam
, GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
1344 return PAGER_LButtonUp (infoPtr
, (INT
)wParam
, GET_X_LPARAM(lParam
), GET_Y_LPARAM(lParam
));
1347 return PAGER_EraseBackground (infoPtr
, (HDC
)wParam
);
1350 return PAGER_Timer (infoPtr
, (INT
)wParam
);
1354 return SendMessageW (infoPtr
->hwndNotify
, uMsg
, wParam
, lParam
);
1357 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
1363 PAGER_Register (void)
1367 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
1368 wndClass
.style
= CS_GLOBALCLASS
;
1369 wndClass
.lpfnWndProc
= PAGER_WindowProc
;
1370 wndClass
.cbClsExtra
= 0;
1371 wndClass
.cbWndExtra
= sizeof(PAGER_INFO
*);
1372 wndClass
.hCursor
= LoadCursorW (0, (LPWSTR
)IDC_ARROW
);
1373 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+1);
1374 wndClass
.lpszClassName
= WC_PAGESCROLLERW
;
1376 RegisterClassW (&wndClass
);
1381 PAGER_Unregister (void)
1383 UnregisterClassW (WC_PAGESCROLLERW
, NULL
);