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 * - integers with thousand separators.
22 * Even though the above list seems rather large, the control seems to
23 * behave very well so I am confident it does work in most (all) of the
26 * I do not like the arrows yet, I'll work more on them later on.
33 #include "sysmetrics.h"
39 /* Control configuration constants */
41 #define INITIAL_DELAY 500 /* initial timer until auto-increment kicks in */
42 #define REPEAT_DELAY 50 /* delay between auto-increments */
44 #define DEFAULT_WIDTH 14 /* default width of the ctrl */
45 #define DEFAULT_XSEP 0 /* default separation between buddy and crtl */
46 #define DEFAULT_ADDTOP 0 /* amount to extend above the buddy window */
47 #define DEFAULT_ADDBOT 0 /* amount to extend below the buddy window */
52 #define FLAG_INCR 0x01
53 #define FLAG_DECR 0x02
54 #define FLAG_MOUSEIN 0x04
55 #define FLAG_CLICKED (FLAG_INCR | FLAG_DECR)
60 static int accelIndex
= -1;
62 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN(updown, \
63 "UpDown Ctrl: Unknown parameter(s) for message " #msg \
64 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
66 #define UPDOWN_GetInfoPtr(wndPtr) ((UPDOWN_INFO *)wndPtr->wExtra[0])
69 /***********************************************************************
71 * Tests if a given value 'val' is between the Min&Max limits
73 static BOOL32
UPDOWN_InBounds(WND
*wndPtr
, int val
)
75 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
77 if(infoPtr
->MaxVal
> infoPtr
->MinVal
)
78 return (infoPtr
->MinVal
<= val
) && (val
<= infoPtr
->MaxVal
);
80 return (infoPtr
->MaxVal
<= val
) && (val
<= infoPtr
->MinVal
);
83 /***********************************************************************
85 * Tests if we can change the current value by delta. If so, it changes
86 * it and returns TRUE. Else, it leaves it unchanged and returns FALSE.
88 static BOOL32
UPDOWN_OffsetVal(WND
*wndPtr
, int delta
)
90 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
92 /* check if we can do the modification first */
93 if(!UPDOWN_InBounds(wndPtr
, infoPtr
->CurVal
+delta
)){
94 if(wndPtr
->dwStyle
& UDS_WRAP
)
95 delta
+= (delta
< 0 ? -1 : 1) *
96 (infoPtr
->MaxVal
< infoPtr
->MinVal
? -1 : 1) *
97 (infoPtr
->MinVal
- infoPtr
->MaxVal
) +
103 infoPtr
->CurVal
+= delta
;
107 /***********************************************************************
108 * UPDOWN_GetArrowRect
109 * wndPtr - pointer to the up-down wnd
110 * rect - will hold the rectangle
111 * incr - TRUE get the "increment" rect (up or right)
112 * FALSE get the "decrement" rect (down or left)
115 static void UPDOWN_GetArrowRect(WND
*wndPtr
, RECT32
*rect
, BOOL32 incr
)
117 int len
; /* will hold the width or height */
119 GetClientRect32(wndPtr
->hwndSelf
, rect
);
121 if (wndPtr
->dwStyle
& UDS_HORZ
) {
122 len
= rect
->right
- rect
->left
; /* compute the width */
124 rect
->left
= len
/2+1;
129 len
= rect
->bottom
- rect
->top
; /* compute the height */
131 rect
->bottom
= len
/2;
137 /***********************************************************************
138 * UPDOWN_GetArrowFromPoint
139 * Returns the rectagle (for the up or down arrow) that contains pt.
140 * If it returns the up rect, it returns TRUE.
141 * If it returns the down rect, it returns FALSE.
143 static int UPDOWN_GetArrowFromPoint(WND
*wndPtr
, RECT32
*rect
, POINT32 pt
)
145 UPDOWN_GetArrowRect(wndPtr
, rect
, TRUE
);
146 if(PtInRect32(rect
, pt
))
149 UPDOWN_GetArrowRect(wndPtr
, rect
, FALSE
);
154 /***********************************************************************
155 * UPDOWN_GetThousandSep
156 * Returns the thousand sep. If an error occurs, it returns ','.
158 static char UPDOWN_GetThousandSep()
162 if(GetLocaleInfo32A(LOCALE_USER_DEFAULT
, LOCALE_STHOUSAND
,
163 sep
, sizeof(sep
)) != 1)
169 /***********************************************************************
171 * Tries to read the pos from the buddy window and if it succeeds,
172 * it stores it in the control's CurVal
174 * TRUE - if it read the integer from the buddy successfully
175 * FALSE - if an error occured
177 static BOOL32
UPDOWN_GetBuddyInt(WND
*wndPtr
)
179 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
180 char txt
[20], sep
, *src
, *dst
;
183 if (!IsWindow32(infoPtr
->Buddy
))
186 /*if the buddy is a list window, we must set curr index */
187 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_LISTBOX
)){
188 newVal
= SendMessage32A(infoPtr
->Buddy
, LB_GETCARETINDEX32
, 0, 0);
193 /* we have a regular window, so will get the text */
194 if (!GetWindowText32A(infoPtr
->Buddy
, txt
, sizeof(txt
)))
197 sep
= UPDOWN_GetThousandSep();
199 /* now get rid of the separators */
200 for(src
= dst
= txt
; *src
; src
++)
205 /* try to convert the number and validate it */
206 newVal
= strtol(txt
, &src
, infoPtr
->Base
);
207 if(*src
|| !UPDOWN_InBounds(wndPtr
, newVal
))
210 TRACE(updown
, "new value(%d) read from buddy (old=%d)\n",
211 newVal
, infoPtr
->CurVal
);
214 infoPtr
->CurVal
= newVal
;
219 /***********************************************************************
221 * Tries to set the pos to the buddy window based on current pos
223 * TRUE - if it set the caption of the buddy successfully
224 * FALSE - if an error occured
226 static BOOL32
UPDOWN_SetBuddyInt(WND
*wndPtr
)
228 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
232 if (!IsWindow32(infoPtr
->Buddy
))
235 TRACE(updown
, "set new value(%d) to buddy.\n",
238 /*if the buddy is a list window, we must set curr index */
239 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_LISTBOX
)){
240 SendMessage32A(infoPtr
->Buddy
, LB_SETCURSEL32
, infoPtr
->CurVal
, 0);
242 else{ /* Regular window, so set caption to the number */
243 len
= sprintf(txt1
, (infoPtr
->Base
==16) ? "%X" : "%d", infoPtr
->CurVal
);
245 sep
= UPDOWN_GetThousandSep();
247 if (!(wndPtr
->dwStyle
& UDS_NOTHOUSANDS
)) {
248 char txt2
[20], *src
= txt1
, *dst
= txt2
;
250 lstrcpyn32A (dst
, src
, len
%3);
254 for(len
=0; *src
; len
++,src
++){
259 *dst
= 0; /* null terminate it */
260 strcpy(txt1
, txt2
); /* move it to the proper place */
262 SetWindowText32A(infoPtr
->Buddy
, txt1
);
268 /***********************************************************************
269 * UPDOWN_Draw [Internal]
271 * Draw the arrows. The background need not be erased.
273 static void UPDOWN_Draw (WND
*wndPtr
, HDC32 hdc
)
275 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
279 /* Draw the incr button */
280 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
281 prssed
= (infoPtr
->Flags
& FLAG_INCR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
282 DrawFrameControl32(hdc
, &rect
, DFC_SCROLL
,
283 (wndPtr
->dwStyle
& UDS_HORZ
? DFCS_SCROLLLEFT
: DFCS_SCROLLUP
) |
284 (prssed
? DFCS_PUSHED
: 0) |
285 (wndPtr
->dwStyle
&WS_DISABLED
? DFCS_INACTIVE
: 0) );
287 /* Draw the space between the buttons */
288 rect
.top
= rect
.bottom
; rect
.bottom
++;
289 DrawEdge32(hdc
, &rect
, 0, BF_MIDDLE
);
291 /* Draw the decr button */
292 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
293 prssed
= (infoPtr
->Flags
& FLAG_DECR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
294 DrawFrameControl32(hdc
, &rect
, DFC_SCROLL
,
295 (wndPtr
->dwStyle
& UDS_HORZ
? DFCS_SCROLLRIGHT
: DFCS_SCROLLDOWN
) |
296 (prssed
? DFCS_PUSHED
: 0) |
297 (wndPtr
->dwStyle
&WS_DISABLED
? DFCS_INACTIVE
: 0) );
300 /***********************************************************************
301 * UPDOWN_Refresh [Internal]
303 * Synchronous drawing (must NOT be used in WM_PAINT).
306 static void UPDOWN_Refresh (WND
*wndPtr
)
310 hdc
= GetDC32 (wndPtr
->hwndSelf
);
311 UPDOWN_Draw (wndPtr
, hdc
);
312 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
316 /***********************************************************************
317 * UPDOWN_Paint [Internal]
319 * Asynchronous drawing (must ONLY be used in WM_PAINT).
322 static void UPDOWN_Paint (WND
*wndPtr
)
327 hdc
= BeginPaint32 (wndPtr
->hwndSelf
, &ps
);
328 UPDOWN_Draw (wndPtr
, hdc
);
329 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
332 /***********************************************************************
334 * Tests if 'hwndBud' is a valid window handle. If not, returns FALSE.
335 * Else, sets it as a new Buddy.
336 * Then, it should subclass the buddy
337 * If window has the UDS_ARROWKEYS, it subcalsses the buddy window to
338 * process the UP/DOWN arrow keys.
339 * If window has the UDS_ALIGNLEFT or UDS_ALIGNRIGHT style
340 * the size/pos of the buddy and the control are adjusted accordingly.
342 static BOOL32
UPDOWN_SetBuddy(WND
*wndPtr
, HWND32 hwndBud
)
344 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
345 RECT32 budRect
; /* new coord for the buddy */
346 int x
; /* new x position and width for the up-down */
348 /* Is is a valid bud? */
349 if(!IsWindow32(hwndBud
))
352 if(wndPtr
->dwStyle
& UDS_ARROWKEYS
){
353 FIXME(updown
, "we need to subclass the buddy to process the arrow keys.\n");
356 /* do we need to do any adjustments? */
357 if(!(wndPtr
->dwStyle
& (UDS_ALIGNLEFT
| UDS_ALIGNRIGHT
)))
360 /* Get the rect of the buddy relative to its parent */
361 GetWindowRect32(infoPtr
->Buddy
, &budRect
);
362 MapWindowPoints32(HWND_DESKTOP
, GetParent32(infoPtr
->Buddy
),
363 (POINT32
*)(&budRect
.left
), 2);
365 /* now do the positioning */
366 if(wndPtr
->dwStyle
& UDS_ALIGNRIGHT
){
367 budRect
.right
-= DEFAULT_WIDTH
+DEFAULT_XSEP
;
368 x
= budRect
.right
+DEFAULT_XSEP
;
370 else{ /* UDS_ALIGNLEFT */
372 budRect
.left
+= DEFAULT_WIDTH
+DEFAULT_XSEP
;
375 /* first adjust the buddy to accomodate the up/down */
376 SetWindowPos32(infoPtr
->Buddy
, 0, budRect
.left
, budRect
.top
,
377 budRect
.right
- budRect
.left
, budRect
.bottom
- budRect
.top
,
378 SWP_NOACTIVATE
|SWP_NOZORDER
);
380 /* now position the up/down */
381 /* Since the UDS_ALIGN* flags were used, */
382 /* we will pick the position and size of the window. */
384 SetWindowPos32(wndPtr
->hwndSelf
,0,x
,budRect
.top
-DEFAULT_ADDTOP
,DEFAULT_WIDTH
,
385 (budRect
.bottom
-budRect
.top
)+DEFAULT_ADDTOP
+DEFAULT_ADDBOT
,
386 SWP_NOACTIVATE
|SWP_NOZORDER
);
391 /***********************************************************************
394 * This function increments/decrements the CurVal by the
395 * 'delta' amount according to the 'incr' flag
396 * It notifies the parent as required.
397 * It handles wraping and non-wraping correctly.
398 * It is assumed that delta>0
400 static void UPDOWN_DoAction(WND
*wndPtr
, int delta
, BOOL32 incr
)
402 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
403 int old_val
= infoPtr
->CurVal
;
406 TRACE(updown
, "%s by %d\n", incr
? "inc" : "dec", delta
);
408 /* check if we can do the modification first */
409 delta
*= (incr
? 1 : -1) * (infoPtr
->MaxVal
< infoPtr
->MinVal
? -1 : 1);
410 if(!UPDOWN_OffsetVal(wndPtr
, delta
))
413 /* so, if we can do the change, recompute delta and restore old value */
414 delta
= infoPtr
->CurVal
- old_val
;
415 infoPtr
->CurVal
= old_val
;
417 /* We must notify parent now to obtain permission */
418 ni
.iPos
= infoPtr
->CurVal
;
420 ni
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
421 ni
.hdr
.idFrom
= wndPtr
->wIDmenu
;
422 ni
.hdr
.code
= UDN_DELTAPOS
;
423 if(SendMessage32A(wndPtr
->parent
->hwndSelf
,
424 WM_NOTIFY
, wndPtr
->wIDmenu
, (LPARAM
)&ni
))
425 return; /* we are not allowed to change */
427 /* Now adjust value with (maybe new) delta */
428 if(!UPDOWN_OffsetVal(wndPtr
, ni
.iDelta
))
431 /* Now take care about our buddy */
432 if(!IsWindow32(infoPtr
->Buddy
))
433 return; /* Nothing else to do */
436 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
437 UPDOWN_SetBuddyInt(wndPtr
);
439 /* Also, notify it */
440 /* FIXME: do we need to send the notification only if
441 we do not have the UDS_SETBUDDYINT style set? */
443 SendMessage32A(GetParent32 (wndPtr
->hwndSelf
),
444 wndPtr
->dwStyle
& UDS_HORZ
? WM_HSCROLL
: WM_VSCROLL
,
445 MAKELONG(incr
? SB_LINEUP
: SB_LINEDOWN
, infoPtr
->CurVal
),
449 /***********************************************************************
452 * Returns TRUE if it is enabled as well as its buddy (if any)
455 static BOOL32
UPDOWN_IsEnabled(WND
*wndPtr
)
457 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
459 if(wndPtr
->dwStyle
& WS_DISABLED
)
461 return IsWindowEnabled32(infoPtr
->Buddy
);
464 /***********************************************************************
467 * Deletes any timers, releases the mouse and does redraw if necessary.
468 * If the control is not in "capture" mode, it does nothing.
469 * If the control was not in cancel mode, it returns FALSE.
470 * If the control was in cancel mode, it returns TRUE.
472 static BOOL32
UPDOWN_CancelMode(WND
*wndPtr
)
474 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
476 /* if not in 'capture' mode, do nothing */
477 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
480 KillTimer32(wndPtr
->hwndSelf
, TIMERID1
); /* kill all possible timers */
481 KillTimer32(wndPtr
->hwndSelf
, TIMERID2
);
483 if(GetCapture32() == wndPtr
->hwndSelf
) /* let the mouse go */
484 ReleaseCapture(); /* if we still have it */
486 infoPtr
->Flags
= 0; /* get rid of any flags */
487 UPDOWN_Refresh (wndPtr
); /* redraw the control just in case */
492 /***********************************************************************
493 * UPDOWN_HandleMouseEvent
495 * Handle a mouse event for the updown.
496 * 'pt' is the location of the mouse event in client or
497 * windows coordinates.
499 static void UPDOWN_HandleMouseEvent(WND
*wndPtr
, UINT32 msg
, POINT32 pt
)
501 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
507 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
508 /* If we are already in the 'clicked' mode, then nothing to do */
509 if(infoPtr
->Flags
& FLAG_CLICKED
)
512 /* If the buddy is an edit, will set focus to it */
513 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
514 SetFocus32(infoPtr
->Buddy
);
516 /* Now see which one is the 'active' arrow */
517 temp
= UPDOWN_GetArrowFromPoint(wndPtr
, &rect
, pt
);
519 /* Update the CurVal if necessary */
520 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
521 UPDOWN_GetBuddyInt(wndPtr
);
523 /* Before we proceed, see if we can spin... */
524 if(!(wndPtr
->dwStyle
& UDS_WRAP
))
525 if(( temp
&& infoPtr
->CurVal
==infoPtr
->MaxVal
) ||
526 (!temp
&& infoPtr
->CurVal
==infoPtr
->MinVal
))
529 /* Set up the correct flags */
531 infoPtr
->Flags
|= temp
? FLAG_INCR
: FLAG_DECR
;
532 infoPtr
->Flags
|= FLAG_MOUSEIN
;
534 /* repaint the control */
535 UPDOWN_Refresh (wndPtr
);
537 /* process the click */
538 UPDOWN_DoAction(wndPtr
, 1, infoPtr
->Flags
& FLAG_INCR
);
540 /* now capture all mouse messages */
541 SetCapture32(wndPtr
->hwndSelf
);
543 /* and startup the first timer */
544 SetTimer32(wndPtr
->hwndSelf
, TIMERID1
, INITIAL_DELAY
, 0);
548 /* If we are not in the 'clicked' mode, then nothing to do */
549 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
552 /* save the flags to see if any got modified */
553 temp
= infoPtr
->Flags
;
555 /* Now get the 'active' arrow rectangle */
556 if (infoPtr
->Flags
& FLAG_INCR
)
557 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
559 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
561 /* Update the flags if we are in/out */
562 if(PtInRect32(&rect
, pt
))
563 infoPtr
->Flags
|= FLAG_MOUSEIN
;
565 infoPtr
->Flags
&= ~FLAG_MOUSEIN
;
566 if(accelIndex
!= -1) /* if we have accel info */
567 accelIndex
= 0; /* reset it */
569 /* If state changed, redraw the control */
570 if(temp
!= infoPtr
->Flags
)
571 UPDOWN_Refresh (wndPtr
);
575 ERR(updown
, "Impossible case!\n");
580 /***********************************************************************
583 LRESULT WINAPI
UpDownWindowProc(HWND32 hwnd
, UINT32 message
, WPARAM32 wParam
,
586 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
587 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
593 /* get rid of border, if any */
594 wndPtr
->dwStyle
&= ~WS_BORDER
;
598 infoPtr
= (UPDOWN_INFO
*)COMCTL32_Alloc (sizeof(UPDOWN_INFO
));
599 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
601 /* initialize the info struct */
602 infoPtr
->AccelCount
=0; infoPtr
->AccelVect
=0;
603 infoPtr
->CurVal
=0; infoPtr
->MinVal
=0; infoPtr
->MaxVal
=100; /*FIXME*/
604 infoPtr
->Base
= 10; /* Default to base 10 */
605 infoPtr
->Buddy
= 0; /* No buddy window yet */
606 infoPtr
->Flags
= 0; /* And no flags */
608 /* Do we pick the buddy win ourselves? */
609 if(wndPtr
->dwStyle
& UDS_AUTOBUDDY
)
610 UPDOWN_SetBuddy(wndPtr
, GetWindow32(wndPtr
->hwndSelf
, GW_HWNDPREV
));
612 TRACE(updown
, "UpDown Ctrl creation, hwnd=%04x\n", hwnd
);
616 if(infoPtr
->AccelVect
)
617 COMCTL32_Free (infoPtr
->AccelVect
);
619 COMCTL32_Free (infoPtr
);
620 wndPtr
->wExtra
[0] = 0;
622 TRACE(updown
, "UpDown Ctrl destruction, hwnd=%04x\n", hwnd
);
626 if(wndPtr
->dwStyle
& WS_DISABLED
)
627 UPDOWN_CancelMode(wndPtr
);
628 UPDOWN_Paint(wndPtr
);
632 /* if initial timer, kill it and start the repeat timer */
633 if(wParam
== TIMERID1
){
634 KillTimer32(hwnd
, TIMERID1
);
635 /* if no accel info given, used default timer */
636 if(infoPtr
->AccelCount
==0 || infoPtr
->AccelVect
==0){
641 accelIndex
= 0; /* otherwise, use it */
642 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
644 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
647 /* now, if the mouse is above us, do the thing...*/
648 if(infoPtr
->Flags
& FLAG_MOUSEIN
){
649 temp
= accelIndex
==-1 ? 1 : infoPtr
->AccelVect
[accelIndex
].nInc
;
650 UPDOWN_DoAction(wndPtr
, temp
, infoPtr
->Flags
& FLAG_INCR
);
652 if(accelIndex
!=-1 && accelIndex
< infoPtr
->AccelCount
-1){
653 KillTimer32(hwnd
, TIMERID2
);
654 accelIndex
++; /* move to the next accel info */
655 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
656 /* make sure we have at least 1ms intervals */
657 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
663 UPDOWN_CancelMode(wndPtr
);
667 if(!UPDOWN_CancelMode(wndPtr
))
669 /*If we released the mouse and our buddy is an edit */
670 /* we must select all text in it. */
671 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
672 SendMessage32A(infoPtr
->Buddy
, EM_SETSEL32
, 0, MAKELONG(0, -1));
677 if(UPDOWN_IsEnabled(wndPtr
)){
679 CONV_POINT16TO32( (POINT16
*)&lParam
, &pt
);
680 UPDOWN_HandleMouseEvent( wndPtr
, message
, pt
);
685 if((wndPtr
->dwStyle
& UDS_ARROWKEYS
) && UPDOWN_IsEnabled(wndPtr
)){
689 UPDOWN_GetBuddyInt(wndPtr
);
690 UPDOWN_DoAction(wndPtr
, 1, wParam
==VK_UP
);
697 UPDOWN_Paint(wndPtr
);
701 if (wParam
==0 && lParam
==0) /*if both zero, */
702 return infoPtr
->AccelCount
; /*just return the accel count*/
703 if (wParam
|| lParam
){
704 UNKNOWN_PARAM(UDM_GETACCEL
, wParam
, lParam
);
707 temp
= MIN(infoPtr
->AccelCount
, wParam
);
708 memcpy((void *)lParam
, infoPtr
->AccelVect
, temp
*sizeof(UDACCEL
));
712 TRACE(updown
, "UpDown Ctrl new accel info, hwnd=%04x\n", hwnd
);
713 if(infoPtr
->AccelVect
){
714 COMCTL32_Free (infoPtr
->AccelVect
);
715 infoPtr
->AccelCount
= 0;
716 infoPtr
->AccelVect
= 0;
720 infoPtr
->AccelVect
= COMCTL32_Alloc (wParam
*sizeof(UDACCEL
));
721 if(infoPtr
->AccelVect
==0)
723 memcpy(infoPtr
->AccelVect
, (void*)lParam
, wParam
*sizeof(UDACCEL
));
727 if (wParam
|| lParam
)
728 UNKNOWN_PARAM(UDM_GETBASE
, wParam
, lParam
);
729 return infoPtr
->Base
;
732 TRACE(updown
, "UpDown Ctrl new base(%d), hwnd=%04x\n",
734 if ( !(wParam
==10 || wParam
==16) || lParam
)
735 UNKNOWN_PARAM(UDM_SETBASE
, wParam
, lParam
);
736 if (wParam
==10 || wParam
==16){
737 temp
= infoPtr
->Base
;
738 infoPtr
->Base
= wParam
;
739 return temp
; /* return the prev base */
744 if (wParam
|| lParam
)
745 UNKNOWN_PARAM(UDM_GETBUDDY
, wParam
, lParam
);
746 return infoPtr
->Buddy
;
750 UNKNOWN_PARAM(UDM_SETBUDDY
, wParam
, lParam
);
751 temp
= infoPtr
->Buddy
;
752 infoPtr
->Buddy
= wParam
;
753 UPDOWN_SetBuddy(wndPtr
, wParam
);
754 TRACE(updown
, "UpDown Ctrl new buddy(%04x), hwnd=%04x\n",
755 infoPtr
->Buddy
, hwnd
);
759 if (wParam
|| lParam
)
760 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
761 temp
= UPDOWN_GetBuddyInt(wndPtr
);
762 return MAKELONG(infoPtr
->CurVal
, temp
? 0 : 1);
765 if (wParam
|| HIWORD(lParam
))
766 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
767 temp
= SLOWORD(lParam
);
768 TRACE(updown
, "UpDown Ctrl new value(%d), hwnd=%04x\n",
770 if(!UPDOWN_InBounds(wndPtr
, temp
)){
771 if(temp
< infoPtr
->MinVal
)
772 temp
= infoPtr
->MinVal
;
773 if(temp
> infoPtr
->MaxVal
)
774 temp
= infoPtr
->MaxVal
;
776 wParam
= infoPtr
->CurVal
; /* save prev value */
777 infoPtr
->CurVal
= temp
; /* set the new value */
778 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
779 UPDOWN_SetBuddyInt(wndPtr
);
780 return wParam
; /* return prev value */
783 if (wParam
|| lParam
)
784 UNKNOWN_PARAM(UDM_GETRANGE
, wParam
, lParam
);
785 return MAKELONG(infoPtr
->MaxVal
, infoPtr
->MinVal
);
789 UNKNOWN_PARAM(UDM_SETRANGE
, wParam
, lParam
); /* we must have: */
790 infoPtr
->MaxVal
= SLOWORD(lParam
); /* UD_MINVAL <= Max <= UD_MAXVAL */
791 infoPtr
->MinVal
= SHIWORD(lParam
); /* UD_MINVAL <= Min <= UD_MAXVAL */
792 /* |Max-Min| <= UD_MAXVAL */
793 TRACE(updown
, "UpDown Ctrl new range(%d to %d), hwnd=%04x\n",
794 infoPtr
->MinVal
, infoPtr
->MaxVal
, hwnd
);
799 *(LPINT32
)wParam
= infoPtr
->MinVal
;
801 *(LPINT32
)lParam
= infoPtr
->MaxVal
;
805 infoPtr
->MinVal
= (INT32
)wParam
;
806 infoPtr
->MaxVal
= (INT32
)lParam
;
807 if (infoPtr
->MaxVal
<= infoPtr
->MinVal
)
808 infoPtr
->MaxVal
= infoPtr
->MinVal
+ 1;
809 TRACE(updown
, "UpDown Ctrl new range(%d to %d), hwnd=%04x\n",
810 infoPtr
->MinVal
, infoPtr
->MaxVal
, hwnd
);
814 if (message
>= WM_USER
)
815 ERR (updown
, "unknown msg %04x wp=%04x lp=%08lx\n",
816 message
, wParam
, lParam
);
817 return DefWindowProc32A (hwnd
, message
, wParam
, lParam
);
824 /***********************************************************************
825 * UPDOWN_Register [Internal]
827 * Registers the updown window class.
831 UPDOWN_Register(void)
833 WNDCLASS32A wndClass
;
835 if( GlobalFindAtom32A( UPDOWN_CLASS32A
) ) return;
837 ZeroMemory( &wndClass
, sizeof( WNDCLASS32A
) );
838 wndClass
.style
= CS_GLOBALCLASS
| CS_VREDRAW
;
839 wndClass
.lpfnWndProc
= (WNDPROC32
)UpDownWindowProc
;
840 wndClass
.cbClsExtra
= 0;
841 wndClass
.cbWndExtra
= sizeof(UPDOWN_INFO
*);
842 wndClass
.hCursor
= LoadCursor32A( 0, IDC_ARROW32A
);
843 wndClass
.hbrBackground
= (HBRUSH32
)(COLOR_3DFACE
+ 1);
844 wndClass
.lpszClassName
= UPDOWN_CLASS32A
;
846 RegisterClass32A( &wndClass
);
850 /***********************************************************************
851 * UPDOWN_Unregister [Internal]
853 * Unregisters the updown window class.
857 UPDOWN_Unregister (VOID
)
859 if (GlobalFindAtom32A (UPDOWN_CLASS32A
))
860 UnregisterClass32A (UPDOWN_CLASS32A
, (HINSTANCE32
)NULL
);