4 * Copyright 1997 Dimitrie O. Paun
7 * - subclass the buddy window (in UPDOWN_SetBuddy) to process the
9 * - I am not sure about the default values for the Min, Max, Pos
10 * (in the UPDOWN_INFO the fields: MinVal, MaxVal, CurVal)
11 * - I think I do not handle correctly the WS_BORDER style.
12 * (Should be fixed. <ekohl@abo.rhein-zeitung.de>)
15 * Not much. The following have not been tested at all:
17 * - listbox as buddy window
20 * - UDS_ALIGNLEFT, ~UDS_WRAP
21 * (tested - they work)
22 * - integers with thousand separators.
23 * (fixed bugs. <noel@macadamian.com>)
25 * Even though the above list seems rather large, the control seems to
26 * behave very well so I am confident it does work in most (all) of the
29 * I do not like the arrows yet, I'll work more on them later on.
41 /* Control configuration constants */
43 #define INITIAL_DELAY 500 /* initial timer until auto-increment kicks in */
44 #define REPEAT_DELAY 50 /* delay between auto-increments */
46 #define DEFAULT_WIDTH 14 /* default width of the ctrl */
47 #define DEFAULT_XSEP 0 /* default separation between buddy and crtl */
48 #define DEFAULT_ADDTOP 0 /* amount to extend above the buddy window */
49 #define DEFAULT_ADDBOT 0 /* amount to extend below the buddy window */
54 #define FLAG_INCR 0x01
55 #define FLAG_DECR 0x02
56 #define FLAG_MOUSEIN 0x04
57 #define FLAG_CLICKED (FLAG_INCR | FLAG_DECR)
62 static int accelIndex
= -1;
64 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN(updown, \
65 "UpDown Ctrl: Unknown parameter(s) for message " #msg \
66 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
68 #define UPDOWN_GetInfoPtr(wndPtr) ((UPDOWN_INFO *)wndPtr->wExtra[0])
71 /***********************************************************************
73 * Tests if a given value 'val' is between the Min&Max limits
75 static BOOL32
UPDOWN_InBounds(WND
*wndPtr
, int val
)
77 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
79 if(infoPtr
->MaxVal
> infoPtr
->MinVal
)
80 return (infoPtr
->MinVal
<= val
) && (val
<= infoPtr
->MaxVal
);
82 return (infoPtr
->MaxVal
<= val
) && (val
<= infoPtr
->MinVal
);
85 /***********************************************************************
87 * Tests if we can change the current value by delta. If so, it changes
88 * it and returns TRUE. Else, it leaves it unchanged and returns FALSE.
90 static BOOL32
UPDOWN_OffsetVal(WND
*wndPtr
, int delta
)
92 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
94 /* check if we can do the modification first */
95 if(!UPDOWN_InBounds(wndPtr
, infoPtr
->CurVal
+delta
)){
96 if(wndPtr
->dwStyle
& UDS_WRAP
)
97 delta
+= (delta
< 0 ? -1 : 1) *
98 (infoPtr
->MaxVal
< infoPtr
->MinVal
? -1 : 1) *
99 (infoPtr
->MinVal
- infoPtr
->MaxVal
) +
100 (delta
< 0 ? 1 : -1);
105 infoPtr
->CurVal
+= delta
;
109 /***********************************************************************
110 * UPDOWN_GetArrowRect
111 * wndPtr - pointer to the up-down wnd
112 * rect - will hold the rectangle
113 * incr - TRUE get the "increment" rect (up or right)
114 * FALSE get the "decrement" rect (down or left)
117 static void UPDOWN_GetArrowRect(WND
*wndPtr
, RECT32
*rect
, BOOL32 incr
)
119 int len
; /* will hold the width or height */
121 GetClientRect32(wndPtr
->hwndSelf
, rect
);
123 if (wndPtr
->dwStyle
& UDS_HORZ
) {
124 len
= rect
->right
- rect
->left
; /* compute the width */
126 rect
->left
= len
/2+1;
131 len
= rect
->bottom
- rect
->top
; /* compute the height */
133 rect
->bottom
= len
/2;
139 /***********************************************************************
140 * UPDOWN_GetArrowFromPoint
141 * Returns the rectagle (for the up or down arrow) that contains pt.
142 * If it returns the up rect, it returns TRUE.
143 * If it returns the down rect, it returns FALSE.
145 static int UPDOWN_GetArrowFromPoint(WND
*wndPtr
, RECT32
*rect
, POINT32 pt
)
147 UPDOWN_GetArrowRect(wndPtr
, rect
, TRUE
);
148 if(PtInRect32(rect
, pt
))
151 UPDOWN_GetArrowRect(wndPtr
, rect
, FALSE
);
156 /***********************************************************************
157 * UPDOWN_GetThousandSep
158 * Returns the thousand sep. If an error occurs, it returns ','.
160 static char UPDOWN_GetThousandSep()
164 if(GetLocaleInfo32A(LOCALE_USER_DEFAULT
, LOCALE_STHOUSAND
,
165 sep
, sizeof(sep
)) != 1)
171 /***********************************************************************
173 * Tries to read the pos from the buddy window and if it succeeds,
174 * it stores it in the control's CurVal
176 * TRUE - if it read the integer from the buddy successfully
177 * FALSE - if an error occured
179 static BOOL32
UPDOWN_GetBuddyInt(WND
*wndPtr
)
181 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
182 char txt
[20], sep
, *src
, *dst
;
185 if (!IsWindow32(infoPtr
->Buddy
))
188 /*if the buddy is a list window, we must set curr index */
189 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_LISTBOX
)){
190 newVal
= SendMessage32A(infoPtr
->Buddy
, LB_GETCARETINDEX32
, 0, 0);
195 /* we have a regular window, so will get the text */
196 if (!GetWindowText32A(infoPtr
->Buddy
, txt
, sizeof(txt
)))
199 sep
= UPDOWN_GetThousandSep();
201 /* now get rid of the separators */
202 for(src
= dst
= txt
; *src
; src
++)
207 /* try to convert the number and validate it */
208 newVal
= strtol(txt
, &src
, infoPtr
->Base
);
209 if(*src
|| !UPDOWN_InBounds(wndPtr
, newVal
))
212 TRACE(updown
, "new value(%d) read from buddy (old=%d)\n",
213 newVal
, infoPtr
->CurVal
);
216 infoPtr
->CurVal
= newVal
;
221 /***********************************************************************
223 * Tries to set the pos to the buddy window based on current pos
225 * TRUE - if it set the caption of the buddy successfully
226 * FALSE - if an error occured
228 static BOOL32
UPDOWN_SetBuddyInt(WND
*wndPtr
)
230 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
234 if (!IsWindow32(infoPtr
->Buddy
))
237 TRACE(updown
, "set new value(%d) to buddy.\n",
240 /*if the buddy is a list window, we must set curr index */
241 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_LISTBOX
)){
242 SendMessage32A(infoPtr
->Buddy
, LB_SETCURSEL32
, infoPtr
->CurVal
, 0);
244 else{ /* Regular window, so set caption to the number */
245 len
= sprintf(txt1
, (infoPtr
->Base
==16) ? "%X" : "%d", infoPtr
->CurVal
);
247 sep
= UPDOWN_GetThousandSep();
249 /* Do thousands seperation if necessary */
250 if (!(wndPtr
->dwStyle
& UDS_NOTHOUSANDS
) && (len
> 3)) {
251 char txt2
[20], *src
= txt1
, *dst
= txt2
;
253 lstrcpyn32A (dst
, src
, len
%3 + 1); /* need to include the null */
257 for(len
=0; *src
; len
++){
262 *dst
= 0; /* null terminate it */
263 strcpy(txt1
, txt2
); /* move it to the proper place */
265 SetWindowText32A(infoPtr
->Buddy
, txt1
);
271 /***********************************************************************
272 * UPDOWN_Draw [Internal]
274 * Draw the arrows. The background need not be erased.
276 static void UPDOWN_Draw (WND
*wndPtr
, HDC32 hdc
)
278 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
282 /* Draw the incr button */
283 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
284 prssed
= (infoPtr
->Flags
& FLAG_INCR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
285 DrawFrameControl32(hdc
, &rect
, DFC_SCROLL
,
286 (wndPtr
->dwStyle
& UDS_HORZ
? DFCS_SCROLLLEFT
: DFCS_SCROLLUP
) |
287 (prssed
? DFCS_PUSHED
: 0) |
288 (wndPtr
->dwStyle
&WS_DISABLED
? DFCS_INACTIVE
: 0) );
290 /* Draw the space between the buttons */
291 rect
.top
= rect
.bottom
; rect
.bottom
++;
292 DrawEdge32(hdc
, &rect
, 0, BF_MIDDLE
);
294 /* Draw the decr button */
295 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
296 prssed
= (infoPtr
->Flags
& FLAG_DECR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
297 DrawFrameControl32(hdc
, &rect
, DFC_SCROLL
,
298 (wndPtr
->dwStyle
& UDS_HORZ
? DFCS_SCROLLRIGHT
: DFCS_SCROLLDOWN
) |
299 (prssed
? DFCS_PUSHED
: 0) |
300 (wndPtr
->dwStyle
&WS_DISABLED
? DFCS_INACTIVE
: 0) );
303 /***********************************************************************
304 * UPDOWN_Refresh [Internal]
306 * Synchronous drawing (must NOT be used in WM_PAINT).
309 static void UPDOWN_Refresh (WND
*wndPtr
)
313 hdc
= GetDC32 (wndPtr
->hwndSelf
);
314 UPDOWN_Draw (wndPtr
, hdc
);
315 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
319 /***********************************************************************
320 * UPDOWN_Paint [Internal]
322 * Asynchronous drawing (must ONLY be used in WM_PAINT).
325 static void UPDOWN_Paint (WND
*wndPtr
)
330 hdc
= BeginPaint32 (wndPtr
->hwndSelf
, &ps
);
331 UPDOWN_Draw (wndPtr
, hdc
);
332 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
335 /***********************************************************************
337 * Tests if 'hwndBud' is a valid window handle. If not, returns FALSE.
338 * Else, sets it as a new Buddy.
339 * Then, it should subclass the buddy
340 * If window has the UDS_ARROWKEYS, it subcalsses the buddy window to
341 * process the UP/DOWN arrow keys.
342 * If window has the UDS_ALIGNLEFT or UDS_ALIGNRIGHT style
343 * the size/pos of the buddy and the control are adjusted accordingly.
345 static BOOL32
UPDOWN_SetBuddy(WND
*wndPtr
, HWND32 hwndBud
)
347 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
348 RECT32 budRect
; /* new coord for the buddy */
349 int x
; /* new x position and width for the up-down */
351 /* Is is a valid bud? */
352 if(!IsWindow32(hwndBud
))
355 if(wndPtr
->dwStyle
& UDS_ARROWKEYS
){
356 FIXME(updown
, "we need to subclass the buddy to process the arrow keys.\n");
359 /* do we need to do any adjustments? */
360 if(!(wndPtr
->dwStyle
& (UDS_ALIGNLEFT
| UDS_ALIGNRIGHT
)))
363 /* Get the rect of the buddy relative to its parent */
364 GetWindowRect32(infoPtr
->Buddy
, &budRect
);
365 MapWindowPoints32(HWND_DESKTOP
, GetParent32(infoPtr
->Buddy
),
366 (POINT32
*)(&budRect
.left
), 2);
368 /* now do the positioning */
369 if(wndPtr
->dwStyle
& UDS_ALIGNRIGHT
){
370 budRect
.right
-= DEFAULT_WIDTH
+DEFAULT_XSEP
;
371 x
= budRect
.right
+DEFAULT_XSEP
;
373 else{ /* UDS_ALIGNLEFT */
375 budRect
.left
+= DEFAULT_WIDTH
+DEFAULT_XSEP
;
378 /* first adjust the buddy to accomodate the up/down */
379 SetWindowPos32(infoPtr
->Buddy
, 0, budRect
.left
, budRect
.top
,
380 budRect
.right
- budRect
.left
, budRect
.bottom
- budRect
.top
,
381 SWP_NOACTIVATE
|SWP_NOZORDER
);
383 /* now position the up/down */
384 /* Since the UDS_ALIGN* flags were used, */
385 /* we will pick the position and size of the window. */
387 SetWindowPos32(wndPtr
->hwndSelf
,0,x
,budRect
.top
-DEFAULT_ADDTOP
,DEFAULT_WIDTH
,
388 (budRect
.bottom
-budRect
.top
)+DEFAULT_ADDTOP
+DEFAULT_ADDBOT
,
389 SWP_NOACTIVATE
|SWP_NOZORDER
);
394 /***********************************************************************
397 * This function increments/decrements the CurVal by the
398 * 'delta' amount according to the 'incr' flag
399 * It notifies the parent as required.
400 * It handles wraping and non-wraping correctly.
401 * It is assumed that delta>0
403 static void UPDOWN_DoAction(WND
*wndPtr
, int delta
, BOOL32 incr
)
405 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
406 int old_val
= infoPtr
->CurVal
;
409 TRACE(updown
, "%s by %d\n", incr
? "inc" : "dec", delta
);
411 /* check if we can do the modification first */
412 delta
*= (incr
? 1 : -1) * (infoPtr
->MaxVal
< infoPtr
->MinVal
? -1 : 1);
413 if(!UPDOWN_OffsetVal(wndPtr
, delta
))
416 /* so, if we can do the change, recompute delta and restore old value */
417 delta
= infoPtr
->CurVal
- old_val
;
418 infoPtr
->CurVal
= old_val
;
420 /* We must notify parent now to obtain permission */
421 ni
.iPos
= infoPtr
->CurVal
;
423 ni
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
424 ni
.hdr
.idFrom
= wndPtr
->wIDmenu
;
425 ni
.hdr
.code
= UDN_DELTAPOS
;
426 if(SendMessage32A(wndPtr
->parent
->hwndSelf
,
427 WM_NOTIFY
, wndPtr
->wIDmenu
, (LPARAM
)&ni
))
428 return; /* we are not allowed to change */
430 /* Now adjust value with (maybe new) delta */
431 if(!UPDOWN_OffsetVal(wndPtr
, ni
.iDelta
))
434 /* Now take care about our buddy */
435 if(!IsWindow32(infoPtr
->Buddy
))
436 return; /* Nothing else to do */
439 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
440 UPDOWN_SetBuddyInt(wndPtr
);
442 /* Also, notify it */
443 /* FIXME: do we need to send the notification only if
444 we do not have the UDS_SETBUDDYINT style set? */
446 SendMessage32A(GetParent32 (wndPtr
->hwndSelf
),
447 wndPtr
->dwStyle
& UDS_HORZ
? WM_HSCROLL
: WM_VSCROLL
,
448 MAKELONG(incr
? SB_LINEUP
: SB_LINEDOWN
, infoPtr
->CurVal
),
452 /***********************************************************************
455 * Returns TRUE if it is enabled as well as its buddy (if any)
458 static BOOL32
UPDOWN_IsEnabled(WND
*wndPtr
)
460 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
462 if(wndPtr
->dwStyle
& WS_DISABLED
)
464 return IsWindowEnabled32(infoPtr
->Buddy
);
467 /***********************************************************************
470 * Deletes any timers, releases the mouse and does redraw if necessary.
471 * If the control is not in "capture" mode, it does nothing.
472 * If the control was not in cancel mode, it returns FALSE.
473 * If the control was in cancel mode, it returns TRUE.
475 static BOOL32
UPDOWN_CancelMode(WND
*wndPtr
)
477 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
479 /* if not in 'capture' mode, do nothing */
480 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
483 KillTimer32(wndPtr
->hwndSelf
, TIMERID1
); /* kill all possible timers */
484 KillTimer32(wndPtr
->hwndSelf
, TIMERID2
);
486 if(GetCapture32() == wndPtr
->hwndSelf
) /* let the mouse go */
487 ReleaseCapture(); /* if we still have it */
489 infoPtr
->Flags
= 0; /* get rid of any flags */
490 UPDOWN_Refresh (wndPtr
); /* redraw the control just in case */
495 /***********************************************************************
496 * UPDOWN_HandleMouseEvent
498 * Handle a mouse event for the updown.
499 * 'pt' is the location of the mouse event in client or
500 * windows coordinates.
502 static void UPDOWN_HandleMouseEvent(WND
*wndPtr
, UINT32 msg
, POINT32 pt
)
504 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
510 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
511 /* If we are already in the 'clicked' mode, then nothing to do */
512 if(infoPtr
->Flags
& FLAG_CLICKED
)
515 /* If the buddy is an edit, will set focus to it */
516 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
517 SetFocus32(infoPtr
->Buddy
);
519 /* Now see which one is the 'active' arrow */
520 temp
= UPDOWN_GetArrowFromPoint(wndPtr
, &rect
, pt
);
522 /* Update the CurVal if necessary */
523 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
524 UPDOWN_GetBuddyInt(wndPtr
);
526 /* Before we proceed, see if we can spin... */
527 if(!(wndPtr
->dwStyle
& UDS_WRAP
))
528 if(( temp
&& infoPtr
->CurVal
==infoPtr
->MaxVal
) ||
529 (!temp
&& infoPtr
->CurVal
==infoPtr
->MinVal
))
532 /* Set up the correct flags */
534 infoPtr
->Flags
|= temp
? FLAG_INCR
: FLAG_DECR
;
535 infoPtr
->Flags
|= FLAG_MOUSEIN
;
537 /* repaint the control */
538 UPDOWN_Refresh (wndPtr
);
540 /* process the click */
541 UPDOWN_DoAction(wndPtr
, 1, infoPtr
->Flags
& FLAG_INCR
);
543 /* now capture all mouse messages */
544 SetCapture32(wndPtr
->hwndSelf
);
546 /* and startup the first timer */
547 SetTimer32(wndPtr
->hwndSelf
, TIMERID1
, INITIAL_DELAY
, 0);
551 /* If we are not in the 'clicked' mode, then nothing to do */
552 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
555 /* save the flags to see if any got modified */
556 temp
= infoPtr
->Flags
;
558 /* Now get the 'active' arrow rectangle */
559 if (infoPtr
->Flags
& FLAG_INCR
)
560 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
562 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
564 /* Update the flags if we are in/out */
565 if(PtInRect32(&rect
, pt
))
566 infoPtr
->Flags
|= FLAG_MOUSEIN
;
568 infoPtr
->Flags
&= ~FLAG_MOUSEIN
;
569 if(accelIndex
!= -1) /* if we have accel info */
570 accelIndex
= 0; /* reset it */
572 /* If state changed, redraw the control */
573 if(temp
!= infoPtr
->Flags
)
574 UPDOWN_Refresh (wndPtr
);
578 ERR(updown
, "Impossible case!\n");
583 /***********************************************************************
586 LRESULT WINAPI
UpDownWindowProc(HWND32 hwnd
, UINT32 message
, WPARAM32 wParam
,
589 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
590 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
596 /* get rid of border, if any */
597 wndPtr
->dwStyle
&= ~WS_BORDER
;
601 infoPtr
= (UPDOWN_INFO
*)COMCTL32_Alloc (sizeof(UPDOWN_INFO
));
602 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
604 /* initialize the info struct */
605 infoPtr
->AccelCount
=0; infoPtr
->AccelVect
=0;
606 infoPtr
->CurVal
=0; infoPtr
->MinVal
=0; infoPtr
->MaxVal
=100; /*FIXME*/
607 infoPtr
->Base
= 10; /* Default to base 10 */
608 infoPtr
->Buddy
= 0; /* No buddy window yet */
609 infoPtr
->Flags
= 0; /* And no flags */
611 /* Do we pick the buddy win ourselves? */
612 if(wndPtr
->dwStyle
& UDS_AUTOBUDDY
)
613 UPDOWN_SetBuddy(wndPtr
, GetWindow32(wndPtr
->hwndSelf
, GW_HWNDPREV
));
615 TRACE(updown
, "UpDown Ctrl creation, hwnd=%04x\n", hwnd
);
619 if(infoPtr
->AccelVect
)
620 COMCTL32_Free (infoPtr
->AccelVect
);
622 COMCTL32_Free (infoPtr
);
623 wndPtr
->wExtra
[0] = 0;
625 TRACE(updown
, "UpDown Ctrl destruction, hwnd=%04x\n", hwnd
);
629 if(wndPtr
->dwStyle
& WS_DISABLED
)
630 UPDOWN_CancelMode(wndPtr
);
631 UPDOWN_Paint(wndPtr
);
635 /* if initial timer, kill it and start the repeat timer */
636 if(wParam
== TIMERID1
){
637 KillTimer32(hwnd
, TIMERID1
);
638 /* if no accel info given, used default timer */
639 if(infoPtr
->AccelCount
==0 || infoPtr
->AccelVect
==0){
644 accelIndex
= 0; /* otherwise, use it */
645 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
647 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
650 /* now, if the mouse is above us, do the thing...*/
651 if(infoPtr
->Flags
& FLAG_MOUSEIN
){
652 temp
= accelIndex
==-1 ? 1 : infoPtr
->AccelVect
[accelIndex
].nInc
;
653 UPDOWN_DoAction(wndPtr
, temp
, infoPtr
->Flags
& FLAG_INCR
);
655 if(accelIndex
!=-1 && accelIndex
< infoPtr
->AccelCount
-1){
656 KillTimer32(hwnd
, TIMERID2
);
657 accelIndex
++; /* move to the next accel info */
658 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
659 /* make sure we have at least 1ms intervals */
660 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
666 UPDOWN_CancelMode(wndPtr
);
670 if(!UPDOWN_CancelMode(wndPtr
))
672 /*If we released the mouse and our buddy is an edit */
673 /* we must select all text in it. */
674 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
675 SendMessage32A(infoPtr
->Buddy
, EM_SETSEL32
, 0, MAKELONG(0, -1));
680 if(UPDOWN_IsEnabled(wndPtr
)){
682 CONV_POINT16TO32( (POINT16
*)&lParam
, &pt
);
683 UPDOWN_HandleMouseEvent( wndPtr
, message
, pt
);
688 if((wndPtr
->dwStyle
& UDS_ARROWKEYS
) && UPDOWN_IsEnabled(wndPtr
)){
692 UPDOWN_GetBuddyInt(wndPtr
);
693 UPDOWN_DoAction(wndPtr
, 1, wParam
==VK_UP
);
700 UPDOWN_Paint(wndPtr
);
704 if (wParam
==0 && lParam
==0) /*if both zero, */
705 return infoPtr
->AccelCount
; /*just return the accel count*/
706 if (wParam
|| lParam
){
707 UNKNOWN_PARAM(UDM_GETACCEL
, wParam
, lParam
);
710 temp
= MIN(infoPtr
->AccelCount
, wParam
);
711 memcpy((void *)lParam
, infoPtr
->AccelVect
, temp
*sizeof(UDACCEL
));
715 TRACE(updown
, "UpDown Ctrl new accel info, hwnd=%04x\n", hwnd
);
716 if(infoPtr
->AccelVect
){
717 COMCTL32_Free (infoPtr
->AccelVect
);
718 infoPtr
->AccelCount
= 0;
719 infoPtr
->AccelVect
= 0;
723 infoPtr
->AccelVect
= COMCTL32_Alloc (wParam
*sizeof(UDACCEL
));
724 if(infoPtr
->AccelVect
==0)
726 memcpy(infoPtr
->AccelVect
, (void*)lParam
, wParam
*sizeof(UDACCEL
));
730 if (wParam
|| lParam
)
731 UNKNOWN_PARAM(UDM_GETBASE
, wParam
, lParam
);
732 return infoPtr
->Base
;
735 TRACE(updown
, "UpDown Ctrl new base(%d), hwnd=%04x\n",
737 if ( !(wParam
==10 || wParam
==16) || lParam
)
738 UNKNOWN_PARAM(UDM_SETBASE
, wParam
, lParam
);
739 if (wParam
==10 || wParam
==16){
740 temp
= infoPtr
->Base
;
741 infoPtr
->Base
= wParam
;
742 return temp
; /* return the prev base */
747 if (wParam
|| lParam
)
748 UNKNOWN_PARAM(UDM_GETBUDDY
, wParam
, lParam
);
749 return infoPtr
->Buddy
;
753 UNKNOWN_PARAM(UDM_SETBUDDY
, wParam
, lParam
);
754 temp
= infoPtr
->Buddy
;
755 infoPtr
->Buddy
= wParam
;
756 UPDOWN_SetBuddy(wndPtr
, wParam
);
757 TRACE(updown
, "UpDown Ctrl new buddy(%04x), hwnd=%04x\n",
758 infoPtr
->Buddy
, hwnd
);
762 if (wParam
|| lParam
)
763 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
764 temp
= UPDOWN_GetBuddyInt(wndPtr
);
765 return MAKELONG(infoPtr
->CurVal
, temp
? 0 : 1);
768 if (wParam
|| HIWORD(lParam
))
769 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
770 temp
= SLOWORD(lParam
);
771 TRACE(updown
, "UpDown Ctrl new value(%d), hwnd=%04x\n",
773 if(!UPDOWN_InBounds(wndPtr
, temp
)){
774 if(temp
< infoPtr
->MinVal
)
775 temp
= infoPtr
->MinVal
;
776 if(temp
> infoPtr
->MaxVal
)
777 temp
= infoPtr
->MaxVal
;
779 wParam
= infoPtr
->CurVal
; /* save prev value */
780 infoPtr
->CurVal
= temp
; /* set the new value */
781 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
782 UPDOWN_SetBuddyInt(wndPtr
);
783 return wParam
; /* return prev value */
786 if (wParam
|| lParam
)
787 UNKNOWN_PARAM(UDM_GETRANGE
, wParam
, lParam
);
788 return MAKELONG(infoPtr
->MaxVal
, infoPtr
->MinVal
);
792 UNKNOWN_PARAM(UDM_SETRANGE
, wParam
, lParam
); /* we must have: */
793 infoPtr
->MaxVal
= SLOWORD(lParam
); /* UD_MINVAL <= Max <= UD_MAXVAL */
794 infoPtr
->MinVal
= SHIWORD(lParam
); /* UD_MINVAL <= Min <= UD_MAXVAL */
795 /* |Max-Min| <= UD_MAXVAL */
796 TRACE(updown
, "UpDown Ctrl new range(%d to %d), hwnd=%04x\n",
797 infoPtr
->MinVal
, infoPtr
->MaxVal
, hwnd
);
802 *(LPINT32
)wParam
= infoPtr
->MinVal
;
804 *(LPINT32
)lParam
= infoPtr
->MaxVal
;
808 infoPtr
->MinVal
= (INT32
)wParam
;
809 infoPtr
->MaxVal
= (INT32
)lParam
;
810 if (infoPtr
->MaxVal
<= infoPtr
->MinVal
)
811 infoPtr
->MaxVal
= infoPtr
->MinVal
+ 1;
812 TRACE(updown
, "UpDown Ctrl new range(%d to %d), hwnd=%04x\n",
813 infoPtr
->MinVal
, infoPtr
->MaxVal
, hwnd
);
817 if (message
>= WM_USER
)
818 ERR (updown
, "unknown msg %04x wp=%04x lp=%08lx\n",
819 message
, wParam
, lParam
);
820 return DefWindowProc32A (hwnd
, message
, wParam
, lParam
);
827 /***********************************************************************
828 * UPDOWN_Register [Internal]
830 * Registers the updown window class.
834 UPDOWN_Register(void)
836 WNDCLASS32A wndClass
;
838 if( GlobalFindAtom32A( UPDOWN_CLASS32A
) ) return;
840 ZeroMemory( &wndClass
, sizeof( WNDCLASS32A
) );
841 wndClass
.style
= CS_GLOBALCLASS
| CS_VREDRAW
;
842 wndClass
.lpfnWndProc
= (WNDPROC32
)UpDownWindowProc
;
843 wndClass
.cbClsExtra
= 0;
844 wndClass
.cbWndExtra
= sizeof(UPDOWN_INFO
*);
845 wndClass
.hCursor
= LoadCursor32A( 0, IDC_ARROW32A
);
846 wndClass
.hbrBackground
= (HBRUSH32
)(COLOR_3DFACE
+ 1);
847 wndClass
.lpszClassName
= UPDOWN_CLASS32A
;
849 RegisterClass32A( &wndClass
);
853 /***********************************************************************
854 * UPDOWN_Unregister [Internal]
856 * Unregisters the updown window class.
860 UPDOWN_Unregister (VOID
)
862 if (GlobalFindAtom32A (UPDOWN_CLASS32A
))
863 UnregisterClass32A (UPDOWN_CLASS32A
, (HINSTANCE32
)NULL
);