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.
34 #include "sysmetrics.h"
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 if (!(wndPtr
->dwStyle
& UDS_NOTHOUSANDS
)) {
250 char txt2
[20], *src
= txt1
, *dst
= txt2
;
252 strncpy(dst
, src
, len
%3);
256 for(len
=0; *src
; len
++,src
++){
261 *dst
= 0; /* null terminate it */
262 strcpy(txt1
, txt2
); /* move it to the proper place */
264 SetWindowText32A(infoPtr
->Buddy
, txt1
);
270 /***********************************************************************
271 * UPDOWN_Draw [Internal]
273 * Draw the arrows. The background need not be erased.
275 static void UPDOWN_Draw (WND
*wndPtr
, HDC32 hdc
)
277 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
281 /* Draw the incr button */
282 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
283 prssed
= (infoPtr
->Flags
& FLAG_INCR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
284 DrawFrameControl32(hdc
, &rect
, DFC_SCROLL
,
285 (wndPtr
->dwStyle
& UDS_HORZ
? DFCS_SCROLLLEFT
: DFCS_SCROLLUP
) |
286 (prssed
? DFCS_PUSHED
: 0) |
287 (wndPtr
->dwStyle
&WS_DISABLED
? DFCS_INACTIVE
: 0) );
289 /* Draw the space between the buttons */
290 rect
.top
= rect
.bottom
; rect
.bottom
++;
291 DrawEdge32(hdc
, &rect
, 0, BF_MIDDLE
);
293 /* Draw the decr button */
294 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
295 prssed
= (infoPtr
->Flags
& FLAG_DECR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
296 DrawFrameControl32(hdc
, &rect
, DFC_SCROLL
,
297 (wndPtr
->dwStyle
& UDS_HORZ
? DFCS_SCROLLRIGHT
: DFCS_SCROLLDOWN
) |
298 (prssed
? DFCS_PUSHED
: 0) |
299 (wndPtr
->dwStyle
&WS_DISABLED
? DFCS_INACTIVE
: 0) );
302 /***********************************************************************
303 * UPDOWN_Refresh [Internal]
305 * Synchronous drawing (must NOT be used in WM_PAINT).
308 static void UPDOWN_Refresh (WND
*wndPtr
)
312 hdc
= GetDC32 (wndPtr
->hwndSelf
);
313 UPDOWN_Draw (wndPtr
, hdc
);
314 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
318 /***********************************************************************
319 * UPDOWN_Paint [Internal]
321 * Asynchronous drawing (must ONLY be used in WM_PAINT).
324 static void UPDOWN_Paint (WND
*wndPtr
)
329 hdc
= BeginPaint32 (wndPtr
->hwndSelf
, &ps
);
330 UPDOWN_Draw (wndPtr
, hdc
);
331 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
334 /***********************************************************************
336 * Tests if 'hwndBud' is a valid window handle. If not, returns FALSE.
337 * Else, sets it as a new Buddy.
338 * Then, it should subclass the buddy
339 * If window has the UDS_ARROWKEYS, it subcalsses the buddy window to
340 * process the UP/DOWN arrow keys.
341 * If window has the UDS_ALIGNLEFT or UDS_ALIGNRIGHT style
342 * the size/pos of the buddy and the control are adjusted accordingly.
344 static BOOL32
UPDOWN_SetBuddy(WND
*wndPtr
, HWND32 hwndBud
)
346 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
347 RECT32 budRect
; /* new coord for the buddy */
348 int x
; /* new x position and width for the up-down */
350 /* Is is a valid bud? */
351 if(!IsWindow32(hwndBud
))
354 if(wndPtr
->dwStyle
& UDS_ARROWKEYS
){
355 FIXME(updown
, "we need to subclass the buddy to process the arrow keys.\n");
358 /* do we need to do any adjustments? */
359 if(!(wndPtr
->dwStyle
& (UDS_ALIGNLEFT
| UDS_ALIGNRIGHT
)))
362 /* Get the rect of the buddy relative to its parent */
363 GetWindowRect32(infoPtr
->Buddy
, &budRect
);
364 MapWindowPoints32(HWND_DESKTOP
, GetParent32(infoPtr
->Buddy
),
365 (POINT32
*)(&budRect
.left
), 2);
367 /* now do the positioning */
368 if(wndPtr
->dwStyle
& UDS_ALIGNRIGHT
){
369 budRect
.right
-= DEFAULT_WIDTH
+DEFAULT_XSEP
;
370 x
= budRect
.right
+DEFAULT_XSEP
;
372 else{ /* UDS_ALIGNLEFT */
374 budRect
.left
+= DEFAULT_WIDTH
+DEFAULT_XSEP
;
377 /* first adjust the buddy to accomodate the up/down */
378 SetWindowPos32(infoPtr
->Buddy
, 0, budRect
.left
, budRect
.top
,
379 budRect
.right
- budRect
.left
, budRect
.bottom
- budRect
.top
,
380 SWP_NOACTIVATE
|SWP_NOZORDER
);
382 /* now position the up/down */
383 /* Since the UDS_ALIGN* flags were used, */
384 /* we will pick the position and size of the window. */
386 SetWindowPos32(wndPtr
->hwndSelf
,0,x
,budRect
.top
-DEFAULT_ADDTOP
,DEFAULT_WIDTH
,
387 (budRect
.bottom
-budRect
.top
)+DEFAULT_ADDTOP
+DEFAULT_ADDBOT
,
388 SWP_NOACTIVATE
|SWP_NOZORDER
);
393 /***********************************************************************
396 * This function increments/decrements the CurVal by the
397 * 'delta' amount according to the 'incr' flag
398 * It notifies the parent as required.
399 * It handles wraping and non-wraping correctly.
400 * It is assumed that delta>0
402 static void UPDOWN_DoAction(WND
*wndPtr
, int delta
, BOOL32 incr
)
404 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
405 int old_val
= infoPtr
->CurVal
;
408 TRACE(updown
, "%s by %d\n", incr
? "inc" : "dec", delta
);
410 /* check if we can do the modification first */
411 delta
*= (incr
? 1 : -1) * (infoPtr
->MaxVal
< infoPtr
->MinVal
? -1 : 1);
412 if(!UPDOWN_OffsetVal(wndPtr
, delta
))
415 /* so, if we can do the change, recompute delta and restore old value */
416 delta
= infoPtr
->CurVal
- old_val
;
417 infoPtr
->CurVal
= old_val
;
419 /* We must notify parent now to obtain permission */
420 ni
.iPos
= infoPtr
->CurVal
;
422 ni
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
423 ni
.hdr
.idFrom
= wndPtr
->wIDmenu
;
424 ni
.hdr
.code
= UDN_DELTAPOS
;
425 if(SendMessage32A(wndPtr
->parent
->hwndSelf
,
426 WM_NOTIFY
, wndPtr
->wIDmenu
, (LPARAM
)&ni
))
427 return; /* we are not allowed to change */
429 /* Now adjust value with (maybe new) delta */
430 if(!UPDOWN_OffsetVal(wndPtr
, ni
.iDelta
))
433 /* Now take care about our buddy */
434 if(!IsWindow32(infoPtr
->Buddy
))
435 return; /* Nothing else to do */
438 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
439 UPDOWN_SetBuddyInt(wndPtr
);
441 /* Also, notify it */
442 /* FIXME: do we need to send the notification only if
443 we do not have the UDS_SETBUDDYINT style set? */
445 SendMessage32A(GetParent32 (wndPtr
->hwndSelf
),
446 wndPtr
->dwStyle
& UDS_HORZ
? WM_HSCROLL
: WM_VSCROLL
,
447 MAKELONG(incr
? SB_LINEUP
: SB_LINEDOWN
, infoPtr
->CurVal
),
451 /***********************************************************************
454 * Returns TRUE if it is enabled as well as its buddy (if any)
457 static BOOL32
UPDOWN_IsEnabled(WND
*wndPtr
)
459 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
461 if(wndPtr
->dwStyle
& WS_DISABLED
)
463 return IsWindowEnabled32(infoPtr
->Buddy
);
466 /***********************************************************************
469 * Deletes any timers, releases the mouse and does redraw if necessary.
470 * If the control is not in "capture" mode, it does nothing.
471 * If the control was not in cancel mode, it returns FALSE.
472 * If the control was in cancel mode, it returns TRUE.
474 static BOOL32
UPDOWN_CancelMode(WND
*wndPtr
)
476 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
478 /* if not in 'capture' mode, do nothing */
479 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
482 KillTimer32(wndPtr
->hwndSelf
, TIMERID1
); /* kill all possible timers */
483 KillTimer32(wndPtr
->hwndSelf
, TIMERID2
);
485 if(GetCapture32() == wndPtr
->hwndSelf
) /* let the mouse go */
486 ReleaseCapture(); /* if we still have it */
488 infoPtr
->Flags
= 0; /* get rid of any flags */
489 UPDOWN_Refresh (wndPtr
); /* redraw the control just in case */
494 /***********************************************************************
495 * UPDOWN_HandleMouseEvent
497 * Handle a mouse event for the updown.
498 * 'pt' is the location of the mouse event in client or
499 * windows coordinates.
501 static void UPDOWN_HandleMouseEvent(WND
*wndPtr
, UINT32 msg
, POINT32 pt
)
503 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
509 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
510 /* If we are already in the 'clicked' mode, then nothing to do */
511 if(infoPtr
->Flags
& FLAG_CLICKED
)
514 /* If the buddy is an edit, will set focus to it */
515 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
516 SetFocus32(infoPtr
->Buddy
);
518 /* Now see which one is the 'active' arrow */
519 temp
= UPDOWN_GetArrowFromPoint(wndPtr
, &rect
, pt
);
521 /* Update the CurVal if necessary */
522 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
523 UPDOWN_GetBuddyInt(wndPtr
);
525 /* Before we proceed, see if we can spin... */
526 if(!(wndPtr
->dwStyle
& UDS_WRAP
))
527 if(( temp
&& infoPtr
->CurVal
==infoPtr
->MaxVal
) ||
528 (!temp
&& infoPtr
->CurVal
==infoPtr
->MinVal
))
531 /* Set up the correct flags */
533 infoPtr
->Flags
|= temp
? FLAG_INCR
: FLAG_DECR
;
534 infoPtr
->Flags
|= FLAG_MOUSEIN
;
536 /* repaint the control */
537 UPDOWN_Refresh (wndPtr
);
539 /* process the click */
540 UPDOWN_DoAction(wndPtr
, 1, infoPtr
->Flags
& FLAG_INCR
);
542 /* now capture all mouse messages */
543 SetCapture32(wndPtr
->hwndSelf
);
545 /* and startup the first timer */
546 SetTimer32(wndPtr
->hwndSelf
, TIMERID1
, INITIAL_DELAY
, 0);
550 /* If we are not in the 'clicked' mode, then nothing to do */
551 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
554 /* save the flags to see if any got modified */
555 temp
= infoPtr
->Flags
;
557 /* Now get the 'active' arrow rectangle */
558 if (infoPtr
->Flags
& FLAG_INCR
)
559 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
561 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
563 /* Update the flags if we are in/out */
564 if(PtInRect32(&rect
, pt
))
565 infoPtr
->Flags
|= FLAG_MOUSEIN
;
567 infoPtr
->Flags
&= ~FLAG_MOUSEIN
;
568 if(accelIndex
!= -1) /* if we have accel info */
569 accelIndex
= 0; /* reset it */
571 /* If state changed, redraw the control */
572 if(temp
!= infoPtr
->Flags
)
573 UPDOWN_Refresh (wndPtr
);
577 ERR(updown
, "Impossible case!\n");
582 /***********************************************************************
585 LRESULT WINAPI
UpDownWindowProc(HWND32 hwnd
, UINT32 message
, WPARAM32 wParam
,
588 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
589 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
595 /* get rid of border, if any */
596 wndPtr
->dwStyle
&= ~WS_BORDER
;
601 (UPDOWN_INFO
*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
602 sizeof(UPDOWN_INFO
));
603 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
605 /* initialize the info struct */
606 infoPtr
->AccelCount
=0; infoPtr
->AccelVect
=0;
607 infoPtr
->CurVal
=0; infoPtr
->MinVal
=0; infoPtr
->MaxVal
=100; /*FIXME*/
608 infoPtr
->Base
= 10; /* Default to base 10 */
609 infoPtr
->Buddy
= 0; /* No buddy window yet */
610 infoPtr
->Flags
= 0; /* And no flags */
612 /* Do we pick the buddy win ourselves? */
613 if(wndPtr
->dwStyle
& UDS_AUTOBUDDY
)
614 UPDOWN_SetBuddy(wndPtr
, GetWindow32(wndPtr
->hwndSelf
, GW_HWNDPREV
));
616 TRACE(updown
, "UpDown Ctrl creation, hwnd=%04x\n", hwnd
);
620 if(infoPtr
->AccelVect
)
621 free(infoPtr
->AccelVect
);
623 HeapFree (GetProcessHeap (), 0, infoPtr
);
624 wndPtr
->wExtra
[0] = 0;
626 TRACE(updown
, "UpDown Ctrl destruction, hwnd=%04x\n", hwnd
);
630 if(wndPtr
->dwStyle
& WS_DISABLED
)
631 UPDOWN_CancelMode(wndPtr
);
632 UPDOWN_Paint(wndPtr
);
636 /* if initial timer, kill it and start the repeat timer */
637 if(wParam
== TIMERID1
){
638 KillTimer32(hwnd
, TIMERID1
);
639 /* if no accel info given, used default timer */
640 if(infoPtr
->AccelCount
==0 || infoPtr
->AccelVect
==0){
645 accelIndex
= 0; /* otherwise, use it */
646 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
648 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
651 /* now, if the mouse is above us, do the thing...*/
652 if(infoPtr
->Flags
& FLAG_MOUSEIN
){
653 temp
= accelIndex
==-1 ? 1 : infoPtr
->AccelVect
[accelIndex
].nInc
;
654 UPDOWN_DoAction(wndPtr
, temp
, infoPtr
->Flags
& FLAG_INCR
);
656 if(accelIndex
!=-1 && accelIndex
< infoPtr
->AccelCount
-1){
657 KillTimer32(hwnd
, TIMERID2
);
658 accelIndex
++; /* move to the next accel info */
659 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
660 /* make sure we have at least 1ms intervals */
661 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
667 UPDOWN_CancelMode(wndPtr
);
671 if(!UPDOWN_CancelMode(wndPtr
))
673 /*If we released the mouse and our buddy is an edit */
674 /* we must select all text in it. */
675 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
676 SendMessage32A(infoPtr
->Buddy
, EM_SETSEL32
, 0, MAKELONG(0, -1));
681 if(UPDOWN_IsEnabled(wndPtr
)){
683 CONV_POINT16TO32( (POINT16
*)&lParam
, &pt
);
684 UPDOWN_HandleMouseEvent( wndPtr
, message
, pt
);
689 if((wndPtr
->dwStyle
& UDS_ARROWKEYS
) && UPDOWN_IsEnabled(wndPtr
)){
693 UPDOWN_GetBuddyInt(wndPtr
);
694 UPDOWN_DoAction(wndPtr
, 1, wParam
==VK_UP
);
701 UPDOWN_Paint(wndPtr
);
705 if (wParam
==0 && lParam
==0) /*if both zero, */
706 return infoPtr
->AccelCount
; /*just return the accel count*/
707 if (wParam
|| lParam
){
708 UNKNOWN_PARAM(UDM_GETACCEL
, wParam
, lParam
);
711 temp
= MIN(infoPtr
->AccelCount
, wParam
);
712 memcpy((void *)lParam
, infoPtr
->AccelVect
, temp
*sizeof(UDACCEL
));
716 TRACE(updown
, "UpDown Ctrl new accel info, hwnd=%04x\n", hwnd
);
717 if(infoPtr
->AccelVect
){
718 free(infoPtr
->AccelVect
);
719 infoPtr
->AccelCount
= 0;
720 infoPtr
->AccelVect
= 0;
724 infoPtr
->AccelVect
= malloc(wParam
*sizeof(UDACCEL
));
725 if(infoPtr
->AccelVect
==0)
727 memcpy(infoPtr
->AccelVect
, (void*)lParam
, wParam
*sizeof(UDACCEL
));
731 if (wParam
|| lParam
)
732 UNKNOWN_PARAM(UDM_GETBASE
, wParam
, lParam
);
733 return infoPtr
->Base
;
736 TRACE(updown
, "UpDown Ctrl new base(%d), hwnd=%04x\n",
738 if ( !(wParam
==10 || wParam
==16) || lParam
)
739 UNKNOWN_PARAM(UDM_SETBASE
, wParam
, lParam
);
740 if (wParam
==10 || wParam
==16){
741 temp
= infoPtr
->Base
;
742 infoPtr
->Base
= wParam
;
743 return temp
; /* return the prev base */
748 if (wParam
|| lParam
)
749 UNKNOWN_PARAM(UDM_GETBUDDY
, wParam
, lParam
);
750 return infoPtr
->Buddy
;
754 UNKNOWN_PARAM(UDM_SETBUDDY
, wParam
, lParam
);
755 temp
= infoPtr
->Buddy
;
756 infoPtr
->Buddy
= wParam
;
757 UPDOWN_SetBuddy(wndPtr
, wParam
);
758 TRACE(updown
, "UpDown Ctrl new buddy(%04x), hwnd=%04x\n",
759 infoPtr
->Buddy
, hwnd
);
763 if (wParam
|| lParam
)
764 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
765 temp
= UPDOWN_GetBuddyInt(wndPtr
);
766 return MAKELONG(infoPtr
->CurVal
, temp
? 0 : 1);
769 if (wParam
|| HIWORD(lParam
))
770 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
771 temp
= SLOWORD(lParam
);
772 TRACE(updown
, "UpDown Ctrl new value(%d), hwnd=%04x\n",
774 if(!UPDOWN_InBounds(wndPtr
, temp
)){
775 if(temp
< infoPtr
->MinVal
)
776 temp
= infoPtr
->MinVal
;
777 if(temp
> infoPtr
->MaxVal
)
778 temp
= infoPtr
->MaxVal
;
780 wParam
= infoPtr
->CurVal
; /* save prev value */
781 infoPtr
->CurVal
= temp
; /* set the new value */
782 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
783 UPDOWN_SetBuddyInt(wndPtr
);
784 return wParam
; /* return prev value */
787 if (wParam
|| lParam
)
788 UNKNOWN_PARAM(UDM_GETRANGE
, wParam
, lParam
);
789 return MAKELONG(infoPtr
->MaxVal
, infoPtr
->MinVal
);
793 UNKNOWN_PARAM(UDM_SETRANGE
, wParam
, lParam
); /* we must have: */
794 infoPtr
->MaxVal
= SLOWORD(lParam
); /* UD_MINVAL <= Max <= UD_MAXVAL */
795 infoPtr
->MinVal
= SHIWORD(lParam
); /* UD_MINVAL <= Min <= UD_MAXVAL */
796 /* |Max-Min| <= UD_MAXVAL */
797 TRACE(updown
, "UpDown Ctrl new range(%d to %d), hwnd=%04x\n",
798 infoPtr
->MinVal
, infoPtr
->MaxVal
, hwnd
);
803 *(LPINT32
)wParam
= infoPtr
->MinVal
;
805 *(LPINT32
)lParam
= infoPtr
->MaxVal
;
809 infoPtr
->MinVal
= (INT32
)wParam
;
810 infoPtr
->MaxVal
= (INT32
)lParam
;
811 if (infoPtr
->MaxVal
<= infoPtr
->MinVal
)
812 infoPtr
->MaxVal
= infoPtr
->MinVal
+ 1;
813 TRACE(updown
, "UpDown Ctrl new range(%d to %d), hwnd=%04x\n",
814 infoPtr
->MinVal
, infoPtr
->MaxVal
, hwnd
);
818 if (message
>= WM_USER
)
819 WARN(updown
, "unknown msg %04x wp=%04x lp=%08lx\n",
820 message
, wParam
, lParam
);
821 return DefWindowProc32A( hwnd
, message
, wParam
, lParam
);
827 /***********************************************************************
828 * UPDOWN_Register [Internal]
830 * Registers the updown window class.
832 void UPDOWN_Register(void)
834 WNDCLASS32A wndClass
;
836 if( GlobalFindAtom32A( UPDOWN_CLASS32A
) ) return;
838 ZeroMemory( &wndClass
, sizeof( WNDCLASS32A
) );
839 wndClass
.style
= CS_GLOBALCLASS
| CS_VREDRAW
;
840 wndClass
.lpfnWndProc
= (WNDPROC32
)UpDownWindowProc
;
841 wndClass
.cbClsExtra
= 0;
842 wndClass
.cbWndExtra
= sizeof(UPDOWN_INFO
*);
843 wndClass
.hCursor
= LoadCursor32A( 0, IDC_ARROW32A
);
844 wndClass
.hbrBackground
= (HBRUSH32
)(COLOR_3DFACE
+ 1);
845 wndClass
.lpszClassName
= UPDOWN_CLASS32A
;
847 RegisterClass32A( &wndClass
);