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"
38 /* Control configuration constants */
40 #define INITIAL_DELAY 500 /* initial timer until auto-increment kicks in */
41 #define REPEAT_DELAY 50 /* delay between auto-increments */
43 #define DEFAULT_WIDTH 14 /* default width of the ctrl */
44 #define DEFAULT_XSEP 0 /* default separation between buddy and crtl */
45 #define DEFAULT_ADDTOP 0 /* amount to extend above the buddy window */
46 #define DEFAULT_ADDBOT 0 /* amount to extend below the buddy window */
51 #define FLAG_INCR 0x01
52 #define FLAG_DECR 0x02
53 #define FLAG_MOUSEIN 0x04
54 #define FLAG_CLICKED (FLAG_INCR | FLAG_DECR)
59 static int accelIndex
= -1;
61 #define UNKNOWN_PARAM(msg, wParam, lParam) WARN(updown, \
62 "UpDown Ctrl: Unknown parameter(s) for message " #msg \
63 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
65 #define UPDOWN_GetInfoPtr(wndPtr) ((UPDOWN_INFO *)wndPtr->wExtra[0])
68 /***********************************************************************
70 * Tests if a given value 'val' is between the Min&Max limits
72 static BOOL32
UPDOWN_InBounds(WND
*wndPtr
, int val
)
74 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
76 if(infoPtr
->MaxVal
> infoPtr
->MinVal
)
77 return (infoPtr
->MinVal
<= val
) && (val
<= infoPtr
->MaxVal
);
79 return (infoPtr
->MaxVal
<= val
) && (val
<= infoPtr
->MinVal
);
82 /***********************************************************************
84 * Tests if we can change the current value by delta. If so, it changes
85 * it and returns TRUE. Else, it leaves it unchanged and returns FALSE.
87 static BOOL32
UPDOWN_OffsetVal(WND
*wndPtr
, int delta
)
89 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
91 /* check if we can do the modification first */
92 if(!UPDOWN_InBounds(wndPtr
, infoPtr
->CurVal
+delta
)){
93 if(wndPtr
->dwStyle
& UDS_WRAP
)
94 delta
+= (delta
< 0 ? -1 : 1) *
95 (infoPtr
->MaxVal
< infoPtr
->MinVal
? -1 : 1) *
96 (infoPtr
->MinVal
- infoPtr
->MaxVal
) +
102 infoPtr
->CurVal
+= delta
;
106 /***********************************************************************
107 * UPDOWN_GetArrowRect
108 * wndPtr - pointer to the up-down wnd
109 * rect - will hold the rectangle
110 * incr - TRUE get the "increment" rect (up or right)
111 * FALSE get the "decrement" rect (down or left)
114 static void UPDOWN_GetArrowRect(WND
*wndPtr
, RECT32
*rect
, BOOL32 incr
)
116 int len
; /* will hold the width or height */
118 GetClientRect32(wndPtr
->hwndSelf
, rect
);
120 if (wndPtr
->dwStyle
& UDS_HORZ
) {
121 len
= rect
->right
- rect
->left
; /* compute the width */
123 rect
->left
= len
/2+1;
128 len
= rect
->bottom
- rect
->top
; /* compute the height */
130 rect
->bottom
= len
/2;
136 /***********************************************************************
137 * UPDOWN_GetArrowFromPoint
138 * Returns the rectagle (for the up or down arrow) that contains pt.
139 * If it returns the up rect, it returns TRUE.
140 * If it returns the down rect, it returns FALSE.
142 static int UPDOWN_GetArrowFromPoint(WND
*wndPtr
, RECT32
*rect
, POINT32 pt
)
144 UPDOWN_GetArrowRect(wndPtr
, rect
, TRUE
);
145 if(PtInRect32(rect
, pt
))
148 UPDOWN_GetArrowRect(wndPtr
, rect
, FALSE
);
153 /***********************************************************************
154 * UPDOWN_GetThousandSep
155 * Returns the thousand sep. If an error occurs, it returns ','.
157 static char UPDOWN_GetThousandSep()
161 if(GetLocaleInfo32A(LOCALE_USER_DEFAULT
, LOCALE_STHOUSAND
,
162 sep
, sizeof(sep
)) != 1)
168 /***********************************************************************
170 * Tries to read the pos from the buddy window and if it succeeds,
171 * it stores it in the control's CurVal
173 * TRUE - if it read the integer from the buddy successfully
174 * FALSE - if an error occured
176 static BOOL32
UPDOWN_GetBuddyInt(WND
*wndPtr
)
178 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
179 char txt
[20], sep
, *src
, *dst
;
182 if (!IsWindow32(infoPtr
->Buddy
))
185 /*if the buddy is a list window, we must set curr index */
186 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_LISTBOX
)){
187 newVal
= SendMessage32A(infoPtr
->Buddy
, LB_GETCARETINDEX32
, 0, 0);
192 /* we have a regular window, so will get the text */
193 if (!GetWindowText32A(infoPtr
->Buddy
, txt
, sizeof(txt
)))
196 sep
= UPDOWN_GetThousandSep();
198 /* now get rid of the separators */
199 for(src
= dst
= txt
; *src
; src
++)
204 /* try to convert the number and validate it */
205 newVal
= strtol(txt
, &src
, infoPtr
->Base
);
206 if(*src
|| !UPDOWN_InBounds(wndPtr
, newVal
))
209 TRACE(updown
, "new value(%d) read from buddy (old=%d)\n",
210 newVal
, infoPtr
->CurVal
);
213 infoPtr
->CurVal
= newVal
;
218 /***********************************************************************
220 * Tries to set the pos to the buddy window based on current pos
222 * TRUE - if it set the caption of the buddy successfully
223 * FALSE - if an error occured
225 static BOOL32
UPDOWN_SetBuddyInt(WND
*wndPtr
)
227 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
231 if (!IsWindow32(infoPtr
->Buddy
))
234 TRACE(updown
, "set new value(%d) to buddy.\n",
237 /*if the buddy is a list window, we must set curr index */
238 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_LISTBOX
)){
239 SendMessage32A(infoPtr
->Buddy
, LB_SETCURSEL32
, infoPtr
->CurVal
, 0);
241 else{ /* Regular window, so set caption to the number */
242 len
= sprintf(txt1
, (infoPtr
->Base
==16) ? "%X" : "%d", infoPtr
->CurVal
);
244 sep
= UPDOWN_GetThousandSep();
246 if (!(wndPtr
->dwStyle
& UDS_NOTHOUSANDS
)) {
247 char txt2
[20], *src
= txt1
, *dst
= txt2
;
249 lstrcpyn32A (dst
, src
, len
%3);
253 for(len
=0; *src
; len
++,src
++){
258 *dst
= 0; /* null terminate it */
259 strcpy(txt1
, txt2
); /* move it to the proper place */
261 SetWindowText32A(infoPtr
->Buddy
, txt1
);
267 /***********************************************************************
268 * UPDOWN_Draw [Internal]
270 * Draw the arrows. The background need not be erased.
272 static void UPDOWN_Draw (WND
*wndPtr
, HDC32 hdc
)
274 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
278 /* Draw the incr button */
279 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
280 prssed
= (infoPtr
->Flags
& FLAG_INCR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
281 DrawFrameControl32(hdc
, &rect
, DFC_SCROLL
,
282 (wndPtr
->dwStyle
& UDS_HORZ
? DFCS_SCROLLLEFT
: DFCS_SCROLLUP
) |
283 (prssed
? DFCS_PUSHED
: 0) |
284 (wndPtr
->dwStyle
&WS_DISABLED
? DFCS_INACTIVE
: 0) );
286 /* Draw the space between the buttons */
287 rect
.top
= rect
.bottom
; rect
.bottom
++;
288 DrawEdge32(hdc
, &rect
, 0, BF_MIDDLE
);
290 /* Draw the decr button */
291 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
292 prssed
= (infoPtr
->Flags
& FLAG_DECR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
293 DrawFrameControl32(hdc
, &rect
, DFC_SCROLL
,
294 (wndPtr
->dwStyle
& UDS_HORZ
? DFCS_SCROLLRIGHT
: DFCS_SCROLLDOWN
) |
295 (prssed
? DFCS_PUSHED
: 0) |
296 (wndPtr
->dwStyle
&WS_DISABLED
? DFCS_INACTIVE
: 0) );
299 /***********************************************************************
300 * UPDOWN_Refresh [Internal]
302 * Synchronous drawing (must NOT be used in WM_PAINT).
305 static void UPDOWN_Refresh (WND
*wndPtr
)
309 hdc
= GetDC32 (wndPtr
->hwndSelf
);
310 UPDOWN_Draw (wndPtr
, hdc
);
311 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
315 /***********************************************************************
316 * UPDOWN_Paint [Internal]
318 * Asynchronous drawing (must ONLY be used in WM_PAINT).
321 static void UPDOWN_Paint (WND
*wndPtr
)
326 hdc
= BeginPaint32 (wndPtr
->hwndSelf
, &ps
);
327 UPDOWN_Draw (wndPtr
, hdc
);
328 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
331 /***********************************************************************
333 * Tests if 'hwndBud' is a valid window handle. If not, returns FALSE.
334 * Else, sets it as a new Buddy.
335 * Then, it should subclass the buddy
336 * If window has the UDS_ARROWKEYS, it subcalsses the buddy window to
337 * process the UP/DOWN arrow keys.
338 * If window has the UDS_ALIGNLEFT or UDS_ALIGNRIGHT style
339 * the size/pos of the buddy and the control are adjusted accordingly.
341 static BOOL32
UPDOWN_SetBuddy(WND
*wndPtr
, HWND32 hwndBud
)
343 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
344 RECT32 budRect
; /* new coord for the buddy */
345 int x
; /* new x position and width for the up-down */
347 /* Is is a valid bud? */
348 if(!IsWindow32(hwndBud
))
351 if(wndPtr
->dwStyle
& UDS_ARROWKEYS
){
352 FIXME(updown
, "we need to subclass the buddy to process the arrow keys.\n");
355 /* do we need to do any adjustments? */
356 if(!(wndPtr
->dwStyle
& (UDS_ALIGNLEFT
| UDS_ALIGNRIGHT
)))
359 /* Get the rect of the buddy relative to its parent */
360 GetWindowRect32(infoPtr
->Buddy
, &budRect
);
361 MapWindowPoints32(HWND_DESKTOP
, GetParent32(infoPtr
->Buddy
),
362 (POINT32
*)(&budRect
.left
), 2);
364 /* now do the positioning */
365 if(wndPtr
->dwStyle
& UDS_ALIGNRIGHT
){
366 budRect
.right
-= DEFAULT_WIDTH
+DEFAULT_XSEP
;
367 x
= budRect
.right
+DEFAULT_XSEP
;
369 else{ /* UDS_ALIGNLEFT */
371 budRect
.left
+= DEFAULT_WIDTH
+DEFAULT_XSEP
;
374 /* first adjust the buddy to accomodate the up/down */
375 SetWindowPos32(infoPtr
->Buddy
, 0, budRect
.left
, budRect
.top
,
376 budRect
.right
- budRect
.left
, budRect
.bottom
- budRect
.top
,
377 SWP_NOACTIVATE
|SWP_NOZORDER
);
379 /* now position the up/down */
380 /* Since the UDS_ALIGN* flags were used, */
381 /* we will pick the position and size of the window. */
383 SetWindowPos32(wndPtr
->hwndSelf
,0,x
,budRect
.top
-DEFAULT_ADDTOP
,DEFAULT_WIDTH
,
384 (budRect
.bottom
-budRect
.top
)+DEFAULT_ADDTOP
+DEFAULT_ADDBOT
,
385 SWP_NOACTIVATE
|SWP_NOZORDER
);
390 /***********************************************************************
393 * This function increments/decrements the CurVal by the
394 * 'delta' amount according to the 'incr' flag
395 * It notifies the parent as required.
396 * It handles wraping and non-wraping correctly.
397 * It is assumed that delta>0
399 static void UPDOWN_DoAction(WND
*wndPtr
, int delta
, BOOL32 incr
)
401 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
402 int old_val
= infoPtr
->CurVal
;
405 TRACE(updown
, "%s by %d\n", incr
? "inc" : "dec", delta
);
407 /* check if we can do the modification first */
408 delta
*= (incr
? 1 : -1) * (infoPtr
->MaxVal
< infoPtr
->MinVal
? -1 : 1);
409 if(!UPDOWN_OffsetVal(wndPtr
, delta
))
412 /* so, if we can do the change, recompute delta and restore old value */
413 delta
= infoPtr
->CurVal
- old_val
;
414 infoPtr
->CurVal
= old_val
;
416 /* We must notify parent now to obtain permission */
417 ni
.iPos
= infoPtr
->CurVal
;
419 ni
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
420 ni
.hdr
.idFrom
= wndPtr
->wIDmenu
;
421 ni
.hdr
.code
= UDN_DELTAPOS
;
422 if(SendMessage32A(wndPtr
->parent
->hwndSelf
,
423 WM_NOTIFY
, wndPtr
->wIDmenu
, (LPARAM
)&ni
))
424 return; /* we are not allowed to change */
426 /* Now adjust value with (maybe new) delta */
427 if(!UPDOWN_OffsetVal(wndPtr
, ni
.iDelta
))
430 /* Now take care about our buddy */
431 if(!IsWindow32(infoPtr
->Buddy
))
432 return; /* Nothing else to do */
435 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
436 UPDOWN_SetBuddyInt(wndPtr
);
438 /* Also, notify it */
439 /* FIXME: do we need to send the notification only if
440 we do not have the UDS_SETBUDDYINT style set? */
442 SendMessage32A(GetParent32 (wndPtr
->hwndSelf
),
443 wndPtr
->dwStyle
& UDS_HORZ
? WM_HSCROLL
: WM_VSCROLL
,
444 MAKELONG(incr
? SB_LINEUP
: SB_LINEDOWN
, infoPtr
->CurVal
),
448 /***********************************************************************
451 * Returns TRUE if it is enabled as well as its buddy (if any)
454 static BOOL32
UPDOWN_IsEnabled(WND
*wndPtr
)
456 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
458 if(wndPtr
->dwStyle
& WS_DISABLED
)
460 return IsWindowEnabled32(infoPtr
->Buddy
);
463 /***********************************************************************
466 * Deletes any timers, releases the mouse and does redraw if necessary.
467 * If the control is not in "capture" mode, it does nothing.
468 * If the control was not in cancel mode, it returns FALSE.
469 * If the control was in cancel mode, it returns TRUE.
471 static BOOL32
UPDOWN_CancelMode(WND
*wndPtr
)
473 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
475 /* if not in 'capture' mode, do nothing */
476 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
479 KillTimer32(wndPtr
->hwndSelf
, TIMERID1
); /* kill all possible timers */
480 KillTimer32(wndPtr
->hwndSelf
, TIMERID2
);
482 if(GetCapture32() == wndPtr
->hwndSelf
) /* let the mouse go */
483 ReleaseCapture(); /* if we still have it */
485 infoPtr
->Flags
= 0; /* get rid of any flags */
486 UPDOWN_Refresh (wndPtr
); /* redraw the control just in case */
491 /***********************************************************************
492 * UPDOWN_HandleMouseEvent
494 * Handle a mouse event for the updown.
495 * 'pt' is the location of the mouse event in client or
496 * windows coordinates.
498 static void UPDOWN_HandleMouseEvent(WND
*wndPtr
, UINT32 msg
, POINT32 pt
)
500 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
506 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
507 /* If we are already in the 'clicked' mode, then nothing to do */
508 if(infoPtr
->Flags
& FLAG_CLICKED
)
511 /* If the buddy is an edit, will set focus to it */
512 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
513 SetFocus32(infoPtr
->Buddy
);
515 /* Now see which one is the 'active' arrow */
516 temp
= UPDOWN_GetArrowFromPoint(wndPtr
, &rect
, pt
);
518 /* Update the CurVal if necessary */
519 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
520 UPDOWN_GetBuddyInt(wndPtr
);
522 /* Before we proceed, see if we can spin... */
523 if(!(wndPtr
->dwStyle
& UDS_WRAP
))
524 if(( temp
&& infoPtr
->CurVal
==infoPtr
->MaxVal
) ||
525 (!temp
&& infoPtr
->CurVal
==infoPtr
->MinVal
))
528 /* Set up the correct flags */
530 infoPtr
->Flags
|= temp
? FLAG_INCR
: FLAG_DECR
;
531 infoPtr
->Flags
|= FLAG_MOUSEIN
;
533 /* repaint the control */
534 UPDOWN_Refresh (wndPtr
);
536 /* process the click */
537 UPDOWN_DoAction(wndPtr
, 1, infoPtr
->Flags
& FLAG_INCR
);
539 /* now capture all mouse messages */
540 SetCapture32(wndPtr
->hwndSelf
);
542 /* and startup the first timer */
543 SetTimer32(wndPtr
->hwndSelf
, TIMERID1
, INITIAL_DELAY
, 0);
547 /* If we are not in the 'clicked' mode, then nothing to do */
548 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
551 /* save the flags to see if any got modified */
552 temp
= infoPtr
->Flags
;
554 /* Now get the 'active' arrow rectangle */
555 if (infoPtr
->Flags
& FLAG_INCR
)
556 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
558 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
560 /* Update the flags if we are in/out */
561 if(PtInRect32(&rect
, pt
))
562 infoPtr
->Flags
|= FLAG_MOUSEIN
;
564 infoPtr
->Flags
&= ~FLAG_MOUSEIN
;
565 if(accelIndex
!= -1) /* if we have accel info */
566 accelIndex
= 0; /* reset it */
568 /* If state changed, redraw the control */
569 if(temp
!= infoPtr
->Flags
)
570 UPDOWN_Refresh (wndPtr
);
574 ERR(updown
, "Impossible case!\n");
579 /***********************************************************************
582 LRESULT WINAPI
UpDownWindowProc(HWND32 hwnd
, UINT32 message
, WPARAM32 wParam
,
585 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
586 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
592 /* get rid of border, if any */
593 wndPtr
->dwStyle
&= ~WS_BORDER
;
597 infoPtr
= (UPDOWN_INFO
*)COMCTL32_Alloc (sizeof(UPDOWN_INFO
));
598 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
600 /* initialize the info struct */
601 infoPtr
->AccelCount
=0; infoPtr
->AccelVect
=0;
602 infoPtr
->CurVal
=0; infoPtr
->MinVal
=0; infoPtr
->MaxVal
=100; /*FIXME*/
603 infoPtr
->Base
= 10; /* Default to base 10 */
604 infoPtr
->Buddy
= 0; /* No buddy window yet */
605 infoPtr
->Flags
= 0; /* And no flags */
607 /* Do we pick the buddy win ourselves? */
608 if(wndPtr
->dwStyle
& UDS_AUTOBUDDY
)
609 UPDOWN_SetBuddy(wndPtr
, GetWindow32(wndPtr
->hwndSelf
, GW_HWNDPREV
));
611 TRACE(updown
, "UpDown Ctrl creation, hwnd=%04x\n", hwnd
);
615 if(infoPtr
->AccelVect
)
616 COMCTL32_Free (infoPtr
->AccelVect
);
618 COMCTL32_Free (infoPtr
);
619 wndPtr
->wExtra
[0] = 0;
621 TRACE(updown
, "UpDown Ctrl destruction, hwnd=%04x\n", hwnd
);
625 if(wndPtr
->dwStyle
& WS_DISABLED
)
626 UPDOWN_CancelMode(wndPtr
);
627 UPDOWN_Paint(wndPtr
);
631 /* if initial timer, kill it and start the repeat timer */
632 if(wParam
== TIMERID1
){
633 KillTimer32(hwnd
, TIMERID1
);
634 /* if no accel info given, used default timer */
635 if(infoPtr
->AccelCount
==0 || infoPtr
->AccelVect
==0){
640 accelIndex
= 0; /* otherwise, use it */
641 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
643 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
646 /* now, if the mouse is above us, do the thing...*/
647 if(infoPtr
->Flags
& FLAG_MOUSEIN
){
648 temp
= accelIndex
==-1 ? 1 : infoPtr
->AccelVect
[accelIndex
].nInc
;
649 UPDOWN_DoAction(wndPtr
, temp
, infoPtr
->Flags
& FLAG_INCR
);
651 if(accelIndex
!=-1 && accelIndex
< infoPtr
->AccelCount
-1){
652 KillTimer32(hwnd
, TIMERID2
);
653 accelIndex
++; /* move to the next accel info */
654 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
655 /* make sure we have at least 1ms intervals */
656 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
662 UPDOWN_CancelMode(wndPtr
);
666 if(!UPDOWN_CancelMode(wndPtr
))
668 /*If we released the mouse and our buddy is an edit */
669 /* we must select all text in it. */
670 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
671 SendMessage32A(infoPtr
->Buddy
, EM_SETSEL32
, 0, MAKELONG(0, -1));
676 if(UPDOWN_IsEnabled(wndPtr
)){
678 CONV_POINT16TO32( (POINT16
*)&lParam
, &pt
);
679 UPDOWN_HandleMouseEvent( wndPtr
, message
, pt
);
684 if((wndPtr
->dwStyle
& UDS_ARROWKEYS
) && UPDOWN_IsEnabled(wndPtr
)){
688 UPDOWN_GetBuddyInt(wndPtr
);
689 UPDOWN_DoAction(wndPtr
, 1, wParam
==VK_UP
);
696 UPDOWN_Paint(wndPtr
);
700 if (wParam
==0 && lParam
==0) /*if both zero, */
701 return infoPtr
->AccelCount
; /*just return the accel count*/
702 if (wParam
|| lParam
){
703 UNKNOWN_PARAM(UDM_GETACCEL
, wParam
, lParam
);
706 temp
= MIN(infoPtr
->AccelCount
, wParam
);
707 memcpy((void *)lParam
, infoPtr
->AccelVect
, temp
*sizeof(UDACCEL
));
711 TRACE(updown
, "UpDown Ctrl new accel info, hwnd=%04x\n", hwnd
);
712 if(infoPtr
->AccelVect
){
713 COMCTL32_Free (infoPtr
->AccelVect
);
714 infoPtr
->AccelCount
= 0;
715 infoPtr
->AccelVect
= 0;
719 infoPtr
->AccelVect
= COMCTL32_Alloc (wParam
*sizeof(UDACCEL
));
720 if(infoPtr
->AccelVect
==0)
722 memcpy(infoPtr
->AccelVect
, (void*)lParam
, wParam
*sizeof(UDACCEL
));
726 if (wParam
|| lParam
)
727 UNKNOWN_PARAM(UDM_GETBASE
, wParam
, lParam
);
728 return infoPtr
->Base
;
731 TRACE(updown
, "UpDown Ctrl new base(%d), hwnd=%04x\n",
733 if ( !(wParam
==10 || wParam
==16) || lParam
)
734 UNKNOWN_PARAM(UDM_SETBASE
, wParam
, lParam
);
735 if (wParam
==10 || wParam
==16){
736 temp
= infoPtr
->Base
;
737 infoPtr
->Base
= wParam
;
738 return temp
; /* return the prev base */
743 if (wParam
|| lParam
)
744 UNKNOWN_PARAM(UDM_GETBUDDY
, wParam
, lParam
);
745 return infoPtr
->Buddy
;
749 UNKNOWN_PARAM(UDM_SETBUDDY
, wParam
, lParam
);
750 temp
= infoPtr
->Buddy
;
751 infoPtr
->Buddy
= wParam
;
752 UPDOWN_SetBuddy(wndPtr
, wParam
);
753 TRACE(updown
, "UpDown Ctrl new buddy(%04x), hwnd=%04x\n",
754 infoPtr
->Buddy
, hwnd
);
758 if (wParam
|| lParam
)
759 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
760 temp
= UPDOWN_GetBuddyInt(wndPtr
);
761 return MAKELONG(infoPtr
->CurVal
, temp
? 0 : 1);
764 if (wParam
|| HIWORD(lParam
))
765 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
766 temp
= SLOWORD(lParam
);
767 TRACE(updown
, "UpDown Ctrl new value(%d), hwnd=%04x\n",
769 if(!UPDOWN_InBounds(wndPtr
, temp
)){
770 if(temp
< infoPtr
->MinVal
)
771 temp
= infoPtr
->MinVal
;
772 if(temp
> infoPtr
->MaxVal
)
773 temp
= infoPtr
->MaxVal
;
775 wParam
= infoPtr
->CurVal
; /* save prev value */
776 infoPtr
->CurVal
= temp
; /* set the new value */
777 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
778 UPDOWN_SetBuddyInt(wndPtr
);
779 return wParam
; /* return prev value */
782 if (wParam
|| lParam
)
783 UNKNOWN_PARAM(UDM_GETRANGE
, wParam
, lParam
);
784 return MAKELONG(infoPtr
->MaxVal
, infoPtr
->MinVal
);
788 UNKNOWN_PARAM(UDM_SETRANGE
, wParam
, lParam
); /* we must have: */
789 infoPtr
->MaxVal
= SLOWORD(lParam
); /* UD_MINVAL <= Max <= UD_MAXVAL */
790 infoPtr
->MinVal
= SHIWORD(lParam
); /* UD_MINVAL <= Min <= UD_MAXVAL */
791 /* |Max-Min| <= UD_MAXVAL */
792 TRACE(updown
, "UpDown Ctrl new range(%d to %d), hwnd=%04x\n",
793 infoPtr
->MinVal
, infoPtr
->MaxVal
, hwnd
);
798 *(LPINT32
)wParam
= infoPtr
->MinVal
;
800 *(LPINT32
)lParam
= infoPtr
->MaxVal
;
804 infoPtr
->MinVal
= (INT32
)wParam
;
805 infoPtr
->MaxVal
= (INT32
)lParam
;
806 if (infoPtr
->MaxVal
<= infoPtr
->MinVal
)
807 infoPtr
->MaxVal
= infoPtr
->MinVal
+ 1;
808 TRACE(updown
, "UpDown Ctrl new range(%d to %d), hwnd=%04x\n",
809 infoPtr
->MinVal
, infoPtr
->MaxVal
, hwnd
);
813 if (message
>= WM_USER
)
814 ERR (updown
, "unknown msg %04x wp=%04x lp=%08lx\n",
815 message
, wParam
, lParam
);
816 return DefWindowProc32A (hwnd
, message
, wParam
, lParam
);
823 /***********************************************************************
824 * UPDOWN_Register [Internal]
826 * Registers the updown window class.
830 UPDOWN_Register(void)
832 WNDCLASS32A wndClass
;
834 if( GlobalFindAtom32A( UPDOWN_CLASS32A
) ) return;
836 ZeroMemory( &wndClass
, sizeof( WNDCLASS32A
) );
837 wndClass
.style
= CS_GLOBALCLASS
| CS_VREDRAW
;
838 wndClass
.lpfnWndProc
= (WNDPROC32
)UpDownWindowProc
;
839 wndClass
.cbClsExtra
= 0;
840 wndClass
.cbWndExtra
= sizeof(UPDOWN_INFO
*);
841 wndClass
.hCursor
= LoadCursor32A( 0, IDC_ARROW32A
);
842 wndClass
.hbrBackground
= (HBRUSH32
)(COLOR_3DFACE
+ 1);
843 wndClass
.lpszClassName
= UPDOWN_CLASS32A
;
845 RegisterClass32A( &wndClass
);
849 /***********************************************************************
850 * UPDOWN_Unregister [Internal]
852 * Unregisters the updown window class.
856 UPDOWN_Unregister (VOID
)
858 if (GlobalFindAtom32A (UPDOWN_CLASS32A
))
859 UnregisterClass32A (UPDOWN_CLASS32A
, (HINSTANCE32
)NULL
);