source: trunk/src/comctl32/pager.c@ 8706

Last change on this file since 8706 was 8382, checked in by sandervl, 23 years ago

merge with latest Wine

File size: 40.6 KB
Line 
1/*
2 * Pager control
3 *
4 * Copyright 1998, 1999 Eric Kohl
5 *
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.
10 *
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.
15 *
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
19 *
20 * NOTES
21 * Tested primarily with the controlspy Pager application.
22 * Susan Farley (susan@codeweavers.com)
23 *
24 * TODO:
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.
29 */
30
31#include <string.h>
32#include "winbase.h"
33#include "commctrl.h"
34#include "wine/debug.h"
35
36WINE_DEFAULT_DEBUG_CHANNEL(pager);
37
38typedef struct
39{
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 INT TLbtnState; /* state of top or left btn */
50 INT BRbtnState; /* state of bottom or right btn */
51 INT direction; /* direction of the scroll, (e.g. PGF_SCROLLUP) */
52} PAGER_INFO;
53
54#define PAGER_GetInfoPtr(hwnd) ((PAGER_INFO *)GetWindowLongA(hwnd, 0))
55#define PAGER_IsHorizontal(hwnd) ((GetWindowLongA (hwnd, GWL_STYLE) & PGS_HORZ))
56
57#define MIN_ARROW_WIDTH 8
58#define MIN_ARROW_HEIGHT 5
59
60#define TIMERID1 1
61#define TIMERID2 2
62#define INITIAL_DELAY 500
63#define REPEAT_DELAY 50
64
65/* the horizontal arrows are:
66 *
67 * 01234 01234
68 * 1 * *
69 * 2 ** **
70 * 3*** ***
71 * 4*** ***
72 * 5 ** **
73 * 6 * *
74 * 7
75 *
76 */
77static void
78PAGER_DrawHorzArrow (HDC hdc, RECT r, INT colorRef, BOOL left)
79{
80 INT x, y, w, h;
81 HPEN hOldPen;
82
83 w = r.right - r.left + 1;
84 h = r.bottom - r.top + 1;
85 if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
86 return; /* refuse to draw partial arrow */
87
88 hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
89 if (left)
90 {
91 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 3;
92 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
93 MoveToEx (hdc, x, y, NULL);
94 LineTo (hdc, x--, y+5); y++;
95 MoveToEx (hdc, x, y, NULL);
96 LineTo (hdc, x--, y+3); y++;
97 MoveToEx (hdc, x, y, NULL);
98 LineTo (hdc, x, y+1);
99 }
100 else
101 {
102 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
103 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
104 MoveToEx (hdc, x, y, NULL);
105 LineTo (hdc, x++, y+5); y++;
106 MoveToEx (hdc, x, y, NULL);
107 LineTo (hdc, x++, y+3); y++;
108 MoveToEx (hdc, x, y, NULL);
109 LineTo (hdc, x, y+1);
110 }
111
112 SelectObject( hdc, hOldPen );
113}
114
115/* the vertical arrows are:
116 *
117 * 01234567 01234567
118 * 1****** **
119 * 2 **** ****
120 * 3 ** ******
121 * 4
122 *
123 */
124static void
125PAGER_DrawVertArrow (HDC hdc, RECT r, INT colorRef, BOOL up)
126{
127 INT x, y, w, h;
128 HPEN hOldPen;
129
130 w = r.right - r.left + 1;
131 h = r.bottom - r.top + 1;
132 if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT))
133 return; /* refuse to draw partial arrow */
134
135 hOldPen = SelectObject ( hdc, GetSysColorPen (colorRef));
136 if (up)
137 {
138 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
139 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 3;
140 MoveToEx (hdc, x, y, NULL);
141 LineTo (hdc, x+5, y--); x++;
142 MoveToEx (hdc, x, y, NULL);
143 LineTo (hdc, x+3, y--); x++;
144 MoveToEx (hdc, x, y, NULL);
145 LineTo (hdc, x+1, y);
146 }
147 else
148 {
149 x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1;
150 y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1;
151 MoveToEx (hdc, x, y, NULL);
152 LineTo (hdc, x+5, y++); x++;
153 MoveToEx (hdc, x, y, NULL);
154 LineTo (hdc, x+3, y++); x++;
155 MoveToEx (hdc, x, y, NULL);
156 LineTo (hdc, x+1, y);
157 }
158
159 SelectObject( hdc, hOldPen );
160}
161
162static void
163PAGER_DrawButton(HDC hdc, COLORREF clrBk, RECT arrowRect,
164 BOOL horz, BOOL topLeft, INT btnState)
165{
166 HBRUSH hBrush, hOldBrush;
167 RECT rc = arrowRect;
168
169 if (!btnState) /* PGF_INVISIBLE */
170 return;
171
172 if ((rc.right - rc.left <= 0) || (rc.bottom - rc.top <= 0))
173 return;
174
175 hBrush = CreateSolidBrush(clrBk);
176 hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
177
178 FillRect(hdc, &rc, hBrush);
179
180 if (btnState == PGF_HOT)
181 {
182 DrawEdge( hdc, &rc, BDR_RAISEDINNER, BF_RECT);
183 if (horz)
184 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
185 else
186 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
187 }
188 else if (btnState == PGF_NORMAL)
189 {
190 DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
191 if (horz)
192 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
193 else
194 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
195 }
196 else if (btnState == PGF_DEPRESSED)
197 {
198 DrawEdge( hdc, &rc, BDR_SUNKENOUTER, BF_RECT);
199 if (horz)
200 PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
201 else
202 PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft);
203 }
204 else if (btnState == PGF_GRAYED)
205 {
206 DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT);
207 if (horz)
208 {
209 PAGER_DrawHorzArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
210 rc.left++, rc.top++; rc.right++, rc.bottom++;
211 PAGER_DrawHorzArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
212 }
213 else
214 {
215 PAGER_DrawVertArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft);
216 rc.left++, rc.top++; rc.right++, rc.bottom++;
217 PAGER_DrawVertArrow(hdc, rc, COLOR_3DSHADOW, topLeft);
218 }
219 }
220
221 SelectObject( hdc, hOldBrush );
222 DeleteObject(hBrush);
223}
224
225/* << PAGER_GetDropTarget >> */
226
227static inline LRESULT
228PAGER_ForwardMouse (HWND hwnd, WPARAM wParam)
229{
230 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
231 TRACE("[%04x]\n", hwnd);
232
233 infoPtr->bForward = (BOOL)wParam;
234
235 return 0;
236}
237
238static inline LRESULT
239PAGER_GetButtonState (HWND hwnd, WPARAM wParam, LPARAM lParam)
240{
241 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
242 LRESULT btnState = PGF_INVISIBLE;
243 INT btn = (INT)lParam;
244 TRACE("[%04x]\n", hwnd);
245
246 if (btn == PGB_TOPORLEFT)
247 btnState = infoPtr->TLbtnState;
248 else if (btn == PGB_BOTTOMORRIGHT)
249 btnState = infoPtr->BRbtnState;
250
251 return btnState;
252}
253
254
255static inline LRESULT
256PAGER_GetPos(HWND hwnd)
257{
258 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
259 TRACE("[%04x] returns %d\n", hwnd, infoPtr->nPos);
260 return (LRESULT)infoPtr->nPos;
261}
262
263static inline LRESULT
264PAGER_GetButtonSize(HWND hwnd)
265{
266 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
267 TRACE("[%04x] returns %d\n", hwnd, infoPtr->nButtonSize);
268 return (LRESULT)infoPtr->nButtonSize;
269}
270
271static inline LRESULT
272PAGER_GetBorder(HWND hwnd)
273{
274 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
275 TRACE("[%04x] returns %d\n", hwnd, infoPtr->nBorder);
276 return (LRESULT)infoPtr->nBorder;
277}
278
279static inline LRESULT
280PAGER_GetBkColor(HWND hwnd)
281{
282 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
283 TRACE("[%04x] returns %06lx\n", hwnd, infoPtr->clrBk);
284 return (LRESULT)infoPtr->clrBk;
285}
286
287static void
288PAGER_CalcSize (HWND hwnd, INT* size, BOOL getWidth)
289{
290 NMPGCALCSIZE nmpgcs;
291 ZeroMemory (&nmpgcs, sizeof (NMPGCALCSIZE));
292 nmpgcs.hdr.hwndFrom = hwnd;
293 nmpgcs.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
294 nmpgcs.hdr.code = PGN_CALCSIZE;
295 nmpgcs.dwFlag = getWidth ? PGF_CALCWIDTH : PGF_CALCHEIGHT;
296 nmpgcs.iWidth = getWidth ? *size : 0;
297 nmpgcs.iHeight = getWidth ? 0 : *size;
298 SendMessageA (GetParent (hwnd), WM_NOTIFY,
299 (WPARAM)nmpgcs.hdr.idFrom, (LPARAM)&nmpgcs);
300
301 *size = getWidth ? nmpgcs.iWidth : nmpgcs.iHeight;
302
303 TRACE("[%04x] PGN_CALCSIZE returns %s=%d\n", hwnd,
304 getWidth ? "width" : "height", *size);
305}
306
307static void
308PAGER_PositionChildWnd(HWND hwnd, PAGER_INFO* infoPtr)
309{
310 if (infoPtr->hwndChild)
311 {
312 RECT rcClient;
313 int nPos = infoPtr->nPos;
314
315 /* compensate for a grayed btn, which will soon become invisible */
316 if (infoPtr->TLbtnState == PGF_GRAYED)
317 nPos += infoPtr->nButtonSize;
318
319 GetClientRect(hwnd, &rcClient);
320
321 if (PAGER_IsHorizontal(hwnd))
322 {
323 int wndSize = max(0, rcClient.right - rcClient.left);
324 if (infoPtr->nWidth < wndSize)
325 infoPtr->nWidth = wndSize;
326
327 TRACE("[%04x] SWP %dx%d at (%d,%d)\n", hwnd,
328 infoPtr->nWidth, infoPtr->nHeight,
329 -nPos, 0);
330 SetWindowPos(infoPtr->hwndChild, 0,
331 -nPos, 0,
332 infoPtr->nWidth, infoPtr->nHeight,
333 SWP_NOZORDER);
334 }
335 else
336 {
337 int wndSize = max(0, rcClient.bottom - rcClient.top);
338 if (infoPtr->nHeight < wndSize)
339 infoPtr->nHeight = wndSize;
340
341 TRACE("[%04x] SWP %dx%d at (%d,%d)\n", hwnd,
342 infoPtr->nWidth, infoPtr->nHeight,
343 0, -nPos);
344 SetWindowPos(infoPtr->hwndChild, 0,
345 0, -nPos,
346 infoPtr->nWidth, infoPtr->nHeight,
347 SWP_NOZORDER);
348 }
349
350 InvalidateRect(infoPtr->hwndChild, NULL, TRUE);
351 }
352}
353
354static INT
355PAGER_GetScrollRange(HWND hwnd, PAGER_INFO* infoPtr)
356{
357 INT scrollRange = 0;
358
359 if (infoPtr->hwndChild)
360 {
361 INT wndSize, childSize;
362 RECT wndRect;
363 GetWindowRect(hwnd, &wndRect);
364
365 if (PAGER_IsHorizontal(hwnd))
366 {
367 wndSize = wndRect.right - wndRect.left;
368 PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
369 childSize = infoPtr->nWidth;
370 }
371 else
372 {
373 wndSize = wndRect.bottom - wndRect.top;
374 PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
375 childSize = infoPtr->nHeight;
376 }
377
378 TRACE("childSize = %d, wndSize = %d\n", childSize, wndSize);
379 if (childSize > wndSize)
380 scrollRange = childSize - wndSize + infoPtr->nButtonSize;
381 }
382
383 TRACE("[%04x] returns %d\n", hwnd, scrollRange);
384 return scrollRange;
385}
386
387static void
388PAGER_GrayAndRestoreBtns(PAGER_INFO* infoPtr, INT scrollRange,
389 BOOL* needsResize, BOOL* needsRepaint)
390{
391 if (infoPtr->nPos > 0)
392 {
393 *needsResize |= !infoPtr->TLbtnState; /* PGF_INVISIBLE */
394 if (infoPtr->TLbtnState != PGF_DEPRESSED)
395 infoPtr->TLbtnState = PGF_NORMAL;
396 }
397 else
398 {
399 *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
400 infoPtr->TLbtnState = PGF_GRAYED;
401 }
402
403 if (scrollRange <= 0)
404 {
405 *needsRepaint |= (infoPtr->TLbtnState != PGF_GRAYED);
406 infoPtr->TLbtnState = PGF_GRAYED;
407 *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
408 infoPtr->BRbtnState = PGF_GRAYED;
409 }
410 else if (infoPtr->nPos < scrollRange)
411 {
412 *needsResize |= !infoPtr->BRbtnState; /* PGF_INVISIBLE */
413 if (infoPtr->BRbtnState != PGF_DEPRESSED)
414 infoPtr->BRbtnState = PGF_NORMAL;
415 }
416 else
417 {
418 *needsRepaint |= (infoPtr->BRbtnState != PGF_GRAYED);
419 infoPtr->BRbtnState = PGF_GRAYED;
420 }
421}
422
423
424static void
425PAGER_NormalizeBtns(PAGER_INFO* infoPtr, BOOL* needsRepaint)
426{
427 if (infoPtr->TLbtnState & (PGF_HOT | PGF_DEPRESSED))
428 {
429 infoPtr->TLbtnState = PGF_NORMAL;
430 *needsRepaint = TRUE;
431 }
432
433 if (infoPtr->BRbtnState & (PGF_HOT | PGF_DEPRESSED))
434 {
435 infoPtr->BRbtnState = PGF_NORMAL;
436 *needsRepaint = TRUE;
437 }
438}
439
440static void
441PAGER_HideGrayBtns(PAGER_INFO* infoPtr, BOOL* needsResize)
442{
443 if (infoPtr->TLbtnState == PGF_GRAYED)
444 {
445 infoPtr->TLbtnState = PGF_INVISIBLE;
446 *needsResize = TRUE;
447 }
448
449 if (infoPtr->BRbtnState == PGF_GRAYED)
450 {
451 infoPtr->BRbtnState = PGF_INVISIBLE;
452 *needsResize = TRUE;
453 }
454}
455
456static void
457PAGER_UpdateBtns(HWND hwnd, PAGER_INFO *infoPtr,
458 INT scrollRange, BOOL hideGrayBtns)
459{
460 BOOL resizeClient = FALSE;
461 BOOL repaintBtns = FALSE;
462
463 if (scrollRange < 0)
464 PAGER_NormalizeBtns(infoPtr, &repaintBtns);
465 else
466 PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
467
468 if (hideGrayBtns)
469 PAGER_HideGrayBtns(infoPtr, &resizeClient);
470
471 if (resizeClient) /* initiate NCCalcSize to resize client wnd */ {
472 SetWindowPos(hwnd, 0,0,0,0,0,
473 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
474 SWP_NOZORDER | SWP_NOACTIVATE);
475 }
476
477 if (repaintBtns)
478 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
479}
480
481static LRESULT
482PAGER_SetPos(HWND hwnd, INT newPos, BOOL fromBtnPress)
483{
484 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
485 INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
486 INT oldPos = infoPtr->nPos;
487
488 if ((scrollRange <= 0) || (newPos < 0))
489 infoPtr->nPos = 0;
490 else if (newPos > scrollRange)
491 infoPtr->nPos = scrollRange;
492 else
493 infoPtr->nPos = newPos;
494
495 TRACE("[%04x] pos=%d\n", hwnd, infoPtr->nPos);
496
497 if (infoPtr->nPos != oldPos)
498 {
499 /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */
500 PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, !fromBtnPress);
501 PAGER_PositionChildWnd(hwnd, infoPtr);
502 }
503
504 return 0;
505}
506
507static LRESULT
508PAGER_HandleWindowPosChanging(HWND hwnd, WPARAM wParam, WINDOWPOS *winpos)
509{
510 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
511
512 if (infoPtr->bNoResize && !(winpos->flags & SWP_NOSIZE))
513 {
514 /* don't let the app resize the nonscrollable dimension of a control
515 * that was created with CCS_NORESIZE style
516 * (i.e. height for a horizontal pager, or width for a vertical one) */
517
518 /* except if the current dimension is 0 and app is setting for
519 * first time, then save amount as dimension. - GA 8/01 */
520
521 if (PAGER_IsHorizontal(hwnd))
522 if (!infoPtr->nHeight && winpos->cy)
523 infoPtr->nHeight = winpos->cy;
524 else
525 winpos->cy = infoPtr->nHeight;
526 else
527 if (!infoPtr->nWidth && winpos->cx)
528 infoPtr->nWidth = winpos->cx;
529 else
530 winpos->cx = infoPtr->nWidth;
531 return 0;
532 }
533
534 DefWindowProcA (hwnd, WM_WINDOWPOSCHANGING, wParam, (LPARAM)winpos);
535
536 return 1;
537}
538
539static INT
540PAGER_SetFixedWidth(HWND hwnd, PAGER_INFO* infoPtr)
541{
542 /* Must set the non-scrollable dimension to be less than the full height/width
543 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
544 * size, and experimentation shows that affect is almost right. */
545
546 RECT wndRect;
547 INT delta, h;
548 GetWindowRect(hwnd, &wndRect);
549
550 /* see what the app says for btn width */
551 PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE);
552
553 if (infoPtr->bNoResize)
554 {
555 delta = wndRect.right - wndRect.left - infoPtr->nWidth;
556 if (delta > infoPtr->nButtonSize)
557 infoPtr->nWidth += 4 * infoPtr->nButtonSize / 3;
558 else if (delta > 0)
559 infoPtr->nWidth += infoPtr->nButtonSize / 3;
560 }
561
562 h = wndRect.bottom - wndRect.top + infoPtr->nButtonSize;
563
564 TRACE("[%04x] infoPtr->nWidth set to %d\n",
565 hwnd, infoPtr->nWidth);
566
567 return h;
568}
569
570static INT
571PAGER_SetFixedHeight(HWND hwnd, PAGER_INFO* infoPtr)
572{
573 /* Must set the non-scrollable dimension to be less than the full height/width
574 * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button
575 * size, and experimentation shows that affect is almost right. */
576
577 RECT wndRect;
578 INT delta, w;
579 GetWindowRect(hwnd, &wndRect);
580
581 /* see what the app says for btn height */
582 PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE);
583
584 if (infoPtr->bNoResize)
585 {
586 delta = wndRect.bottom - wndRect.top - infoPtr->nHeight;
587 if (delta > infoPtr->nButtonSize)
588 infoPtr->nHeight += infoPtr->nButtonSize;
589 else if (delta > 0)
590 infoPtr->nHeight += infoPtr->nButtonSize / 3;
591 }
592
593 w = wndRect.right - wndRect.left + infoPtr->nButtonSize;
594
595 TRACE("[%04x] infoPtr->nHeight set to %d\n",
596 hwnd, infoPtr->nHeight);
597
598 return w;
599}
600
601/******************************************************************
602 * For the PGM_RECALCSIZE message (but not the other uses in *
603 * this module), the native control does only the following: *
604 * *
605 * if (some condition) *
606 * PostMessageA(hwnd, EM_FMTLINES, 0, 0); *
607 * return DefWindowProcA(hwnd, PGM_RECALCSIZE, 0, 0); *
608 * *
609 * When we figure out what the "some condition" is we will *
610 * implement that for the message processing. *
611 ******************************************************************/
612
613static LRESULT
614PAGER_RecalcSize(HWND hwnd)
615{
616 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
617
618 TRACE("[%04x]\n", hwnd);
619
620 if (infoPtr->hwndChild)
621 {
622 INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr);
623
624 if (scrollRange <= 0)
625 {
626 infoPtr->nPos = -1;
627 PAGER_SetPos(hwnd, 0, FALSE);
628 }
629 else
630 {
631 PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, TRUE);
632 PAGER_PositionChildWnd(hwnd, infoPtr);
633 }
634 }
635
636 return 1;
637}
638
639
640static LRESULT
641PAGER_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam)
642{
643 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
644 COLORREF clrTemp = infoPtr->clrBk;
645
646 infoPtr->clrBk = (COLORREF)lParam;
647 TRACE("[%04x] %06lx\n", hwnd, infoPtr->clrBk);
648
649 /* the native control seems to do things this way */
650 SetWindowPos(hwnd, 0,0,0,0,0,
651 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
652 SWP_NOZORDER | SWP_NOACTIVATE);
653
654 RedrawWindow(hwnd, 0, 0, RDW_ERASE | RDW_INVALIDATE);
655
656 return (LRESULT)clrTemp;
657}
658
659
660static LRESULT
661PAGER_SetBorder (HWND hwnd, WPARAM wParam, LPARAM lParam)
662{
663 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
664 INT nTemp = infoPtr->nBorder;
665
666 infoPtr->nBorder = (INT)lParam;
667 TRACE("[%04x] %d\n", hwnd, infoPtr->nBorder);
668
669 PAGER_RecalcSize(hwnd);
670
671 return (LRESULT)nTemp;
672}
673
674
675static LRESULT
676PAGER_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
677{
678 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
679 INT nTemp = infoPtr->nButtonSize;
680
681 infoPtr->nButtonSize = (INT)lParam;
682 TRACE("[%04x] %d\n", hwnd, infoPtr->nButtonSize);
683
684 PAGER_RecalcSize(hwnd);
685
686 return (LRESULT)nTemp;
687}
688
689
690static LRESULT
691PAGER_SetChild (HWND hwnd, WPARAM wParam, LPARAM lParam)
692{
693 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
694 INT hw;
695
696 infoPtr->hwndChild = IsWindow ((HWND)lParam) ? (HWND)lParam : 0;
697
698 if (infoPtr->hwndChild)
699 {
700 TRACE("[%04x] hwndChild=%04x\n", hwnd, infoPtr->hwndChild);
701
702 if (PAGER_IsHorizontal(hwnd)) {
703 hw = PAGER_SetFixedHeight(hwnd, infoPtr);
704 /* adjust non-scrollable dimension to fit the child */
705 SetWindowPos(hwnd, 0, 0,0, hw, infoPtr->nHeight,
706 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER |
707 SWP_NOSIZE | SWP_NOACTIVATE);
708 }
709 else {
710 hw = PAGER_SetFixedWidth(hwnd, infoPtr);
711 /* adjust non-scrollable dimension to fit the child */
712 SetWindowPos(hwnd, 0, 0,0, infoPtr->nWidth, hw,
713 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER |
714 SWP_NOSIZE | SWP_NOACTIVATE);
715 }
716
717 /* position child within the page scroller */
718 SetWindowPos(infoPtr->hwndChild, HWND_TOP,
719 0,0,0,0,
720 SWP_SHOWWINDOW | SWP_NOSIZE); /* native is 0 */
721
722 infoPtr->nPos = -1;
723 PAGER_SetPos(hwnd, 0, FALSE);
724 }
725
726 return 0;
727}
728
729static void
730PAGER_Scroll(HWND hwnd, INT dir)
731{
732 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
733 NMPGSCROLL nmpgScroll;
734 RECT rcWnd;
735
736 if (infoPtr->hwndChild)
737 {
738 ZeroMemory (&nmpgScroll, sizeof (NMPGSCROLL));
739 nmpgScroll.hdr.hwndFrom = hwnd;
740 nmpgScroll.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
741 nmpgScroll.hdr.code = PGN_SCROLL;
742
743 GetWindowRect(hwnd, &rcWnd);
744 GetClientRect(hwnd, &nmpgScroll.rcParent);
745 nmpgScroll.iXpos = nmpgScroll.iYpos = 0;
746 nmpgScroll.iDir = dir;
747
748 if (PAGER_IsHorizontal(hwnd))
749 {
750 nmpgScroll.iScroll = rcWnd.right - rcWnd.left;
751 nmpgScroll.iXpos = infoPtr->nPos;
752 }
753 else
754 {
755 nmpgScroll.iScroll = rcWnd.bottom - rcWnd.top;
756 nmpgScroll.iYpos = infoPtr->nPos;
757 }
758 nmpgScroll.iScroll -= 2*infoPtr->nButtonSize;
759
760 SendMessageA (hwnd, WM_NOTIFY,
761 (WPARAM)nmpgScroll.hdr.idFrom, (LPARAM)&nmpgScroll);
762
763 TRACE("[%04x] PGN_SCROLL returns iScroll=%d\n", hwnd, nmpgScroll.iScroll);
764
765 if (nmpgScroll.iScroll > 0)
766 {
767 infoPtr->direction = dir;
768
769 if (dir == PGF_SCROLLLEFT || dir == PGF_SCROLLUP)
770 PAGER_SetPos(hwnd, infoPtr->nPos - nmpgScroll.iScroll, TRUE);
771 else
772 PAGER_SetPos(hwnd, infoPtr->nPos + nmpgScroll.iScroll, TRUE);
773 }
774 else
775 infoPtr->direction = -1;
776 }
777}
778
779static LRESULT
780PAGER_FmtLines(HWND hwnd)
781{
782 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
783
784 /* initiate NCCalcSize to resize client wnd and get size */
785 SetWindowPos(hwnd, 0, 0,0,0,0,
786 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
787 SWP_NOZORDER | SWP_NOACTIVATE);
788
789 SetWindowPos(infoPtr->hwndChild, 0,
790 0,0,infoPtr->nWidth,infoPtr->nHeight,
791 0);
792
793 return DefWindowProcA (hwnd, EM_FMTLINES, 0, 0);
794}
795
796static LRESULT
797PAGER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
798{
799 PAGER_INFO *infoPtr;
800 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
801
802 /* allocate memory for info structure */
803 infoPtr = (PAGER_INFO *)COMCTL32_Alloc (sizeof(PAGER_INFO));
804 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
805
806 /* set default settings */
807 infoPtr->hwndChild = (HWND)NULL;
808 infoPtr->bNoResize = dwStyle & CCS_NORESIZE;
809 infoPtr->clrBk = GetSysColor(COLOR_BTNFACE);
810 infoPtr->nBorder = 0;
811 infoPtr->nButtonSize = 12;
812 infoPtr->nPos = 0;
813 infoPtr->nWidth = 0;
814 infoPtr->nHeight = 0;
815 infoPtr->bForward = FALSE;
816 infoPtr->TLbtnState = PGF_INVISIBLE;
817 infoPtr->BRbtnState = PGF_INVISIBLE;
818 infoPtr->direction = -1;
819
820 if (dwStyle & PGS_AUTOSCROLL)
821 FIXME("[%04x] Autoscroll style is not implemented yet.\n", hwnd);
822 if (dwStyle & PGS_DRAGNDROP)
823 FIXME("[%04x] Drag and Drop style is not implemented yet.\n", hwnd);
824 /*
825 * If neither horizontal nor vertical style specified, default to vertical.
826 * This is probably not necessary, since the style may be set later on as
827 * the control is initialized, but just in case it isn't, set it here.
828 */
829 if (!(dwStyle & PGS_HORZ) && !(dwStyle & PGS_VERT))
830 {
831 dwStyle |= PGS_VERT;
832 SetWindowLongA(hwnd, GWL_STYLE, dwStyle);
833 }
834
835 return 0;
836}
837
838
839static LRESULT
840PAGER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
841{
842 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
843 /* free pager info data */
844 COMCTL32_Free (infoPtr);
845 SetWindowLongA (hwnd, 0, 0);
846 return 0;
847}
848
849static LRESULT
850PAGER_NCCalcSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
851{
852 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
853 LPRECT lpRect = (LPRECT)lParam;
854 RECT rcChildw, rcmyw, wnrc, lbrc, rbrc;
855 POINT cursor;
856 BOOL resizeClient = FALSE;
857 BOOL repaintBtns = FALSE;
858 INT scrollRange;
859
860 /*
861 * lParam points to a RECT struct. On entry, the struct
862 * contains the proposed wnd rectangle for the window.
863 * On exit, the struct should contain the screen
864 * coordinates of the corresponding window's client area.
865 */
866
867 DefWindowProcA (hwnd, WM_NCCALCSIZE, wParam, lParam);
868
869 TRACE("orig rect=(%d,%d)-(%d,%d)\n",
870 lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
871
872 if (PAGER_IsHorizontal(hwnd))
873 {
874 infoPtr->nWidth = lpRect->right - lpRect->left;
875 PAGER_CalcSize (hwnd, &infoPtr->nWidth, TRUE);
876 GetWindowRect (infoPtr->hwndChild, &rcChildw);
877 MapWindowPoints (0, hwnd, (LPPOINT)&rcChildw, 2);
878 GetCursorPos (&cursor);
879 GetWindowRect (hwnd, &rcmyw);
880
881 /* Reset buttons and hide any grey ones */
882 scrollRange = infoPtr->nWidth - (rcmyw.right - rcmyw.left);
883
884 TRACE("nPos=%d, scrollrange=%d, nWidth=%d, myw=(%d,%d)-(%d,%d)\n",
885 infoPtr->nPos, scrollRange, infoPtr->nWidth,
886 rcmyw.left, rcmyw.top, rcmyw.right, rcmyw.bottom);
887 PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
888 PAGER_HideGrayBtns(infoPtr, &resizeClient);
889
890 if (PtInRect (&rcmyw, cursor)) {
891 GetWindowRect (hwnd, &wnrc);
892 lbrc = wnrc;
893 lbrc.right = lbrc.left + infoPtr->nButtonSize;
894 rbrc = wnrc;
895 rbrc.left = rbrc.right - infoPtr->nButtonSize;
896 TRACE("horz lb rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
897 lbrc.left, lbrc.top, lbrc.right, lbrc.bottom,
898 rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
899 if (PtInRect (&lbrc, cursor) && infoPtr->TLbtnState)
900 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
901 if (PtInRect (&rbrc, cursor) && infoPtr->BRbtnState)
902 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
903 }
904 if (infoPtr->TLbtnState && (lpRect->left + infoPtr->nButtonSize < lpRect->right))
905 lpRect->left += infoPtr->nButtonSize;
906 if (infoPtr->BRbtnState && (lpRect->right - infoPtr->nButtonSize > lpRect->left))
907 lpRect->right -= infoPtr->nButtonSize;
908 }
909 else
910 {
911 /* native does: (from trace of IE4 opening "Favorites" frame)
912 * DefWindowProc
913 * WM_NOITFY PGN_CALCSIZE w/ dwFlag=2
914 * GetWindowRect (child, &rc)
915 * MapWindowPoints (0, syspager, &rc, 2)
916 * GetCursorPos( &cur )
917 * GetWindowRect (syspager, &rc2)
918 * PtInRect (&rc2, cur.x, cur.y) rtns 0
919 * returns with rect empty
920 */
921 infoPtr->nHeight = lpRect->bottom - lpRect->top;
922 PAGER_CalcSize (hwnd, &infoPtr->nHeight, FALSE);
923 GetWindowRect (infoPtr->hwndChild, &rcChildw);
924 MapWindowPoints (0, hwnd, (LPPOINT)&rcChildw, 2);
925 GetCursorPos (&cursor);
926 GetWindowRect (hwnd, &rcmyw);
927
928 /* Reset buttons and hide any grey ones */
929 scrollRange = infoPtr->nHeight - (rcmyw.bottom - rcmyw.top);
930
931 TRACE("nPos=%d, scrollrange=%d, nHeigth=%d, myw=(%d,%d)-(%d,%d)\n",
932 infoPtr->nPos, scrollRange, infoPtr->nHeight,
933 rcmyw.left, rcmyw.top,
934 rcmyw.right, rcmyw.bottom);
935 PAGER_GrayAndRestoreBtns(infoPtr, scrollRange, &resizeClient, &repaintBtns);
936 PAGER_HideGrayBtns(infoPtr, &resizeClient);
937
938 if (PtInRect (&rcmyw, cursor)) {
939
940 /* native does:
941 * GetWindowRect(pager, &rc)
942 * PtInRect(btn-left????, cur.x, cur.y)
943 * if true -> ???
944 * PtInRect(btn-right????, cur.x, cur.y)
945 * if true
946 * RedrawWindow(pager, 0, 0, 5)
947 * return TRUE
948 */
949
950 GetWindowRect (hwnd, &wnrc);
951 lbrc = wnrc;
952 lbrc.right = lbrc.left + infoPtr->nButtonSize;
953 rbrc = wnrc;
954 rbrc.left = rbrc.right - infoPtr->nButtonSize;
955 TRACE("vert lb rect=(%d,%d)-(%d,%d), rb rect=(%d,%d)-(%d,%d)\n",
956 lbrc.left, lbrc.top, lbrc.right, lbrc.bottom,
957 rbrc.left, rbrc.top, rbrc.right, rbrc.bottom);
958 if (PtInRect (&lbrc, cursor) && infoPtr->TLbtnState)
959 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
960 if (PtInRect (&rbrc, cursor) && infoPtr->BRbtnState)
961 RedrawWindow (hwnd, 0, 0, RDW_INVALIDATE | RDW_ERASE);
962 }
963 if (infoPtr->TLbtnState && (lpRect->top + infoPtr->nButtonSize < lpRect->bottom))
964 lpRect->top += infoPtr->nButtonSize;
965 if (infoPtr->BRbtnState && (lpRect->bottom - infoPtr->nButtonSize > lpRect->top))
966 lpRect->bottom -= infoPtr->nButtonSize;
967 /* ???? */
968 if ((lpRect->bottom < 0) || (lpRect->bottom > infoPtr->nHeight))
969 lpRect->bottom = infoPtr->nHeight;
970 }
971
972 TRACE("[%04x] client rect set to %dx%d at (%d,%d) BtnState[%d,%d]\n",
973 hwnd, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top,
974 lpRect->left, lpRect->top,
975 infoPtr->TLbtnState, infoPtr->BRbtnState);
976
977 return 0;
978}
979
980static LRESULT
981PAGER_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam)
982{
983 PAGER_INFO* infoPtr = PAGER_GetInfoPtr(hwnd);
984 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
985 RECT rcWindow, rcBottomRight, rcTopLeft;
986 HDC hdc;
987 BOOL bHorizontal = PAGER_IsHorizontal(hwnd);
988
989 if (dwStyle & WS_MINIMIZE)
990 return 0;
991
992 DefWindowProcA (hwnd, WM_NCPAINT, wParam, lParam);
993
994 if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW)))
995 return 0;
996
997 GetWindowRect (hwnd, &rcWindow);
998 OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top);
999
1000 rcTopLeft = rcBottomRight = rcWindow;
1001 if (bHorizontal)
1002 {
1003 rcTopLeft.right = rcTopLeft.left + infoPtr->nButtonSize;
1004 rcBottomRight.left = rcBottomRight.right - infoPtr->nButtonSize;
1005 }
1006 else
1007 {
1008 rcTopLeft.bottom = rcTopLeft.top + infoPtr->nButtonSize;
1009 rcBottomRight.top = rcBottomRight.bottom - infoPtr->nButtonSize;
1010 }
1011
1012 PAGER_DrawButton(hdc, infoPtr->clrBk, rcTopLeft,
1013 bHorizontal, TRUE, infoPtr->TLbtnState);
1014 PAGER_DrawButton(hdc, infoPtr->clrBk, rcBottomRight,
1015 bHorizontal, FALSE, infoPtr->BRbtnState);
1016
1017 ReleaseDC( hwnd, hdc );
1018 return 0;
1019}
1020
1021static INT
1022PAGER_HitTest (HWND hwnd, LPPOINT pt)
1023{
1024 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1025 RECT clientRect;
1026 BOOL bHorizontal = PAGER_IsHorizontal(hwnd);
1027
1028 GetClientRect (hwnd, &clientRect);
1029
1030 if (PtInRect(&clientRect, *pt))
1031 {
1032 /* TRACE("HTCLIENT\n"); */
1033 return HTCLIENT;
1034 }
1035
1036 if (infoPtr->TLbtnState && infoPtr->TLbtnState != PGF_GRAYED)
1037 {
1038 if (bHorizontal)
1039 {
1040 if (pt->x < clientRect.left)
1041 {
1042 /* TRACE("HTLEFT\n"); */
1043 return HTLEFT;
1044 }
1045 }
1046 else
1047 {
1048 if (pt->y < clientRect.top)
1049 {
1050 /* TRACE("HTTOP\n"); */
1051 return HTTOP;
1052 }
1053 }
1054 }
1055
1056 if (infoPtr->BRbtnState && infoPtr->BRbtnState != PGF_GRAYED)
1057 {
1058 if (bHorizontal)
1059 {
1060 if (pt->x > clientRect.right)
1061 {
1062 /* TRACE("HTRIGHT\n"); */
1063 return HTRIGHT;
1064 }
1065 }
1066 else
1067 {
1068 if (pt->y > clientRect.bottom)
1069 {
1070 /* TRACE("HTBOTTOM\n"); */
1071 return HTBOTTOM;
1072 }
1073 }
1074 }
1075
1076 /* TRACE("HTNOWHERE\n"); */
1077 return HTNOWHERE;
1078}
1079
1080static LRESULT
1081PAGER_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1082{
1083 POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
1084 ScreenToClient (hwnd, &pt);
1085 return PAGER_HitTest(hwnd, &pt);
1086}
1087
1088static LRESULT
1089PAGER_SetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1090{
1091 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1092 BOOL notCaptured = FALSE;
1093
1094 switch(LOWORD(lParam))
1095 {
1096 case HTLEFT:
1097 case HTTOP:
1098 if ((notCaptured = infoPtr->TLbtnState != PGF_HOT))
1099 infoPtr->TLbtnState = PGF_HOT;
1100 break;
1101 case HTRIGHT:
1102 case HTBOTTOM:
1103 if ((notCaptured = infoPtr->BRbtnState != PGF_HOT))
1104 infoPtr->BRbtnState = PGF_HOT;
1105 break;
1106 default:
1107 return FALSE;
1108 }
1109
1110 if (notCaptured)
1111 {
1112 TRACKMOUSEEVENT trackinfo;
1113
1114 TRACE("[%04x] SetCapture\n", hwnd);
1115 SetCapture(hwnd);
1116
1117 trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
1118 trackinfo.dwFlags = TME_QUERY;
1119 trackinfo.hwndTrack = hwnd;
1120 trackinfo.dwHoverTime = HOVER_DEFAULT;
1121
1122 /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */
1123 _TrackMouseEvent(&trackinfo);
1124
1125 /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */
1126 if(!(trackinfo.dwFlags & TME_LEAVE)) {
1127 trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */
1128
1129 /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */
1130 /* and can properly deactivate the hot button */
1131 _TrackMouseEvent(&trackinfo);
1132 }
1133
1134 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
1135 }
1136
1137 return TRUE;
1138}
1139
1140static LRESULT
1141PAGER_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
1142{
1143 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1144
1145 KillTimer (hwnd, TIMERID1);
1146 KillTimer (hwnd, TIMERID2);
1147
1148 TRACE("[%04x] ReleaseCapture\n", hwnd);
1149 ReleaseCapture();
1150
1151 /* Notify parent of released mouse capture */
1152 {
1153 NMHDR nmhdr;
1154 ZeroMemory (&nmhdr, sizeof (NMHDR));
1155 nmhdr.hwndFrom = hwnd;
1156 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1157 nmhdr.code = NM_RELEASEDCAPTURE;
1158 SendMessageA (GetParent(hwnd), WM_NOTIFY,
1159 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
1160 }
1161
1162 /* make HOT btns NORMAL and hide gray btns */
1163 PAGER_UpdateBtns(hwnd, infoPtr, -1, TRUE);
1164
1165 return TRUE;
1166}
1167
1168static LRESULT
1169PAGER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1170{
1171 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1172 BOOL repaintBtns = FALSE;
1173 POINT pt = { SLOWORD(lParam), SHIWORD(lParam) };
1174 INT hit;
1175
1176 TRACE("[%04x]\n", hwnd);
1177
1178 hit = PAGER_HitTest(hwnd, &pt);
1179
1180 /* put btn in DEPRESSED state */
1181 if (hit == HTLEFT || hit == HTTOP)
1182 {
1183 repaintBtns = infoPtr->TLbtnState != PGF_DEPRESSED;
1184 infoPtr->TLbtnState = PGF_DEPRESSED;
1185 SetTimer(hwnd, TIMERID1, INITIAL_DELAY, 0);
1186 }
1187 else if (hit == HTRIGHT || hit == HTBOTTOM)
1188 {
1189 repaintBtns = infoPtr->BRbtnState != PGF_DEPRESSED;
1190 infoPtr->BRbtnState = PGF_DEPRESSED;
1191 SetTimer(hwnd, TIMERID1, INITIAL_DELAY, 0);
1192 }
1193
1194 if (repaintBtns)
1195 SendMessageA(hwnd, WM_NCPAINT, 0, 0);
1196
1197 switch(hit)
1198 {
1199 case HTLEFT:
1200 TRACE("[%04x] PGF_SCROLLLEFT\n", hwnd);
1201 PAGER_Scroll(hwnd, PGF_SCROLLLEFT);
1202 break;
1203 case HTTOP:
1204 TRACE("[%04x] PGF_SCROLLUP\n", hwnd);
1205 PAGER_Scroll(hwnd, PGF_SCROLLUP);
1206 break;
1207 case HTRIGHT:
1208 TRACE("[%04x] PGF_SCROLLRIGHT\n", hwnd);
1209 PAGER_Scroll(hwnd, PGF_SCROLLRIGHT);
1210 break;
1211 case HTBOTTOM:
1212 TRACE("[%04x] PGF_SCROLLDOWN\n", hwnd);
1213 PAGER_Scroll(hwnd, PGF_SCROLLDOWN);
1214 break;
1215 default:
1216 break;
1217 }
1218
1219 return TRUE;
1220}
1221
1222static LRESULT
1223PAGER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1224{
1225 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1226 TRACE("[%04x]\n", hwnd);
1227
1228 KillTimer (hwnd, TIMERID1);
1229 KillTimer (hwnd, TIMERID2);
1230
1231 /* make PRESSED btns NORMAL but don't hide gray btns */
1232 PAGER_UpdateBtns(hwnd, infoPtr, -1, FALSE);
1233
1234 return 0;
1235}
1236
1237static LRESULT
1238PAGER_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
1239{
1240 POINT pt, ptorig;
1241 HDC hdc = (HDC)wParam;
1242 HWND parent;
1243
1244 /* native does:
1245 * parent = GetParent(pager)
1246 * pt.x=0; pt.y=0; ?????
1247 * MapWindowPoints(pager, parent, &pt, 1)
1248 * OffsetWindowOrgEx(hdc, pt.x, pt.y, &ptorg)
1249 * SendMessageA(parent, WM_ERASEBKGND, hdc, 0)
1250 * SetWindowOrgEx(hdc, 0, 0, 0)
1251 */
1252
1253 pt.x = 0;
1254 pt.y = 0;
1255 parent = GetParent(hwnd);
1256 MapWindowPoints(hwnd, parent, &pt, 1);
1257 OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig);
1258 SendMessageA (parent, WM_ERASEBKGND, wParam, lParam);
1259 SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0);
1260
1261
1262#if 0
1263 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1264 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
1265 RECT rect;
1266
1267 GetClientRect (hwnd, &rect);
1268 FillRect ((HDC)wParam, &rect, hBrush);
1269
1270 /* background color of the child should be the same as the pager */
1271 if (infoPtr->hwndChild)
1272 {
1273 GetClientRect (infoPtr->hwndChild, &rect);
1274 FillRect ((HDC)wParam, &rect, hBrush);
1275 }
1276
1277 DeleteObject (hBrush);
1278#endif
1279
1280 return TRUE;
1281}
1282
1283
1284static LRESULT
1285PAGER_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
1286{
1287 /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */
1288
1289 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1290 TRACE("[%04x] %dx%d\n", hwnd, LOWORD(lParam), HIWORD(lParam));
1291
1292 if (PAGER_IsHorizontal(hwnd))
1293 infoPtr->nHeight = HIWORD(lParam);
1294 else
1295 infoPtr->nWidth = LOWORD(lParam);
1296
1297 return PAGER_RecalcSize(hwnd);
1298}
1299
1300
1301static LRESULT WINAPI
1302PAGER_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1303{
1304 PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd);
1305
1306 if (!infoPtr && (uMsg != WM_CREATE))
1307 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1308
1309 switch (uMsg)
1310 {
1311 case EM_FMTLINES:
1312 return PAGER_FmtLines(hwnd);
1313
1314 case PGM_FORWARDMOUSE:
1315 return PAGER_ForwardMouse (hwnd, wParam);
1316
1317 case PGM_GETBKCOLOR:
1318 return PAGER_GetBkColor(hwnd);
1319
1320 case PGM_GETBORDER:
1321 return PAGER_GetBorder(hwnd);
1322
1323 case PGM_GETBUTTONSIZE:
1324 return PAGER_GetButtonSize(hwnd);
1325
1326 case PGM_GETPOS:
1327 return PAGER_GetPos(hwnd);
1328
1329 case PGM_GETBUTTONSTATE:
1330 return PAGER_GetButtonState (hwnd, wParam, lParam);
1331
1332/* case PGM_GETDROPTARGET: */
1333
1334 case PGM_RECALCSIZE:
1335 return PAGER_RecalcSize(hwnd);
1336
1337 case PGM_SETBKCOLOR:
1338 return PAGER_SetBkColor (hwnd, wParam, lParam);
1339
1340 case PGM_SETBORDER:
1341 return PAGER_SetBorder (hwnd, wParam, lParam);
1342
1343 case PGM_SETBUTTONSIZE:
1344 return PAGER_SetButtonSize (hwnd, wParam, lParam);
1345
1346 case PGM_SETCHILD:
1347 return PAGER_SetChild (hwnd, wParam, lParam);
1348
1349 case PGM_SETPOS:
1350 return PAGER_SetPos(hwnd, (INT)lParam, FALSE);
1351
1352 case WM_CREATE:
1353 return PAGER_Create (hwnd, wParam, lParam);
1354
1355 case WM_DESTROY:
1356 return PAGER_Destroy (hwnd, wParam, lParam);
1357
1358 case WM_SIZE:
1359 return PAGER_Size (hwnd, wParam, lParam);
1360
1361 case WM_NCPAINT:
1362 return PAGER_NCPaint (hwnd, wParam, lParam);
1363
1364 case WM_WINDOWPOSCHANGING:
1365 return PAGER_HandleWindowPosChanging (hwnd, wParam, (WINDOWPOS*)lParam);
1366
1367 case WM_NCCALCSIZE:
1368 return PAGER_NCCalcSize (hwnd, wParam, lParam);
1369
1370 case WM_NCHITTEST:
1371 return PAGER_NCHitTest (hwnd, wParam, lParam);
1372
1373 case WM_SETCURSOR:
1374 {
1375 if (hwnd == (HWND)wParam)
1376 return PAGER_SetCursor(hwnd, wParam, lParam);
1377 else /* its for the child */
1378 return 0;
1379 }
1380
1381 case WM_MOUSEMOVE:
1382 if (infoPtr->bForward && infoPtr->hwndChild)
1383 PostMessageA(infoPtr->hwndChild, WM_MOUSEMOVE, wParam, lParam);
1384 return TRUE;
1385
1386 case WM_MOUSELEAVE:
1387 return PAGER_MouseLeave (hwnd, wParam, lParam);
1388
1389 case WM_LBUTTONDOWN:
1390 return PAGER_LButtonDown (hwnd, wParam, lParam);
1391
1392 case WM_LBUTTONUP:
1393 return PAGER_LButtonUp (hwnd, wParam, lParam);
1394
1395 case WM_ERASEBKGND:
1396 return PAGER_EraseBackground (hwnd, wParam, lParam);
1397/*
1398 case WM_PAINT:
1399 return PAGER_Paint (hwnd, wParam);
1400*/
1401 case WM_TIMER:
1402 /* if initial timer, kill it and start the repeat timer */
1403 if (wParam == TIMERID1)
1404 {
1405 KillTimer(hwnd, TIMERID1);
1406 SetTimer(hwnd, TIMERID2, REPEAT_DELAY, 0);
1407 }
1408
1409 KillTimer(hwnd, TIMERID2);
1410 if (infoPtr->direction > 0)
1411 {
1412 PAGER_Scroll(hwnd, infoPtr->direction);
1413 SetTimer(hwnd, TIMERID2, REPEAT_DELAY, 0);
1414 }
1415 break;
1416
1417 case WM_NOTIFY:
1418 case WM_COMMAND:
1419 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
1420
1421 default:
1422 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1423 }
1424
1425 return 0;
1426}
1427
1428
1429VOID
1430PAGER_Register (void)
1431{
1432 WNDCLASSA wndClass;
1433
1434 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1435 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
1436 wndClass.lpfnWndProc = (WNDPROC)PAGER_WindowProc;
1437 wndClass.cbClsExtra = 0;
1438 wndClass.cbWndExtra = sizeof(PAGER_INFO *);
1439 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1440 wndClass.hbrBackground = 0;
1441 wndClass.lpszClassName = WC_PAGESCROLLERA;
1442
1443 RegisterClassA (&wndClass);
1444}
1445
1446
1447VOID
1448PAGER_Unregister (void)
1449{
1450 UnregisterClassA (WC_PAGESCROLLERA, (HINSTANCE)NULL);
1451}
1452
Note: See TracBrowser for help on using the repository browser.