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.
13 * Not much. The following have not been tested at all:
15 * - listbox as buddy window
18 * - UDS_ALIGNLEFT, ~UDS_WRAP
19 * - integers with thousand separators.
20 * Even though the above list seems rather large, the control seems to
21 * behave very well so I am confident it does work in most (all) of the
24 * I do not like the arrows yet, I'll work more on them later on.
34 #include "sysmetrics.h"
40 /*#define DEBUG_UPDOWN*/
43 /* Control configuration constants */
45 #define INITIAL_DELAY 500 /* initial timer until auto-increment kicks in */
46 #define REPEAT_DELAY 50 /* delay between auto-increments */
48 #define DEFAULT_WIDTH 14 /* default width of the ctrl */
49 #define DEFAULT_XSEP 0 /* default separation between buddy and crtl */
50 #define DEFAULT_ADDTOP 0 /* amount to extend above the buddy window */
51 #define DEFAULT_ADDBOT 0 /* amount to extend below the buddy window */
56 #define FLAG_INCR 0x01
57 #define FLAG_DECR 0x02
58 #define FLAG_MOUSEIN 0x04
59 #define FLAG_CLICKED (FLAG_INCR | FLAG_DECR)
64 static int accelIndex
= -1;
66 #define UNKNOWN_PARAM(msg, wParam, lParam) dprintf_updown(stddeb, \
67 "UpDown Ctrl: Unknown parameter(s) for message " #msg \
68 "(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
70 #define UPDOWN_GetInfoPtr(wndPtr) ((UPDOWN_INFO *)wndPtr->wExtra)
72 /***********************************************************************
74 * Tests if a given value 'val' is between the Min&Max limits
76 static BOOL32
UPDOWN_InBounds(WND
*wndPtr
, int val
)
78 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
80 if(infoPtr
->MaxVal
> infoPtr
->MinVal
)
81 return (infoPtr
->MinVal
<= val
) && (val
<= infoPtr
->MaxVal
);
83 return (infoPtr
->MaxVal
<= val
) && (val
<= infoPtr
->MinVal
);
86 /***********************************************************************
88 * Tests if we can change the current value by delta. If so, it changes
89 * it and returns TRUE. Else, it leaves it unchanged and returns FALSE.
91 static BOOL32
UPDOWN_OffsetVal(WND
*wndPtr
, int delta
)
93 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
95 /* check if we can do the modification first */
96 if(!UPDOWN_InBounds(wndPtr
, infoPtr
->CurVal
+delta
)){
97 if(wndPtr
->dwStyle
& UDS_WRAP
)
98 delta
+= (delta
< 0 ? -1 : 1) *
99 (infoPtr
->MaxVal
< infoPtr
->MinVal
? -1 : 1) *
100 (infoPtr
->MinVal
- infoPtr
->MaxVal
) +
101 (delta
< 0 ? 1 : -1);
106 infoPtr
->CurVal
+= delta
;
110 /***********************************************************************
111 * UPDOWN_GetArrawRect
112 * wndPtr - pointer to the up-down wnd
113 * rect - will hold the rectangle
114 * incr - TRUE get the "increment" rect (up or right)
115 * FALSE get the "decrement" rect (down or left)
118 static void UPDOWN_GetArrowRect(WND
*wndPtr
, RECT32
*rect
, BOOL32 incr
)
120 int len
; /* will hold the width or height */
122 GetClientRect32(wndPtr
->hwndSelf
, rect
);
124 if (wndPtr
->dwStyle
& UDS_HORZ
) {
125 len
= rect
->right
- rect
->left
; /* compute the width */
127 rect
->left
= len
/2+1;
132 len
= rect
->bottom
- rect
->top
; /* compute the height */
134 rect
->bottom
= len
/2;
140 /***********************************************************************
141 * UPDOWN_GetArrowFromPoint
142 * Returns the rectagle (for the up or down arrow) that contains pt.
143 * If it returns the up rect, it returns TRUE.
144 * If it returns the down rect, it returns FALSE.
146 static int UPDOWN_GetArrowFromPoint(WND
*wndPtr
, RECT32
*rect
, POINT32 pt
)
148 UPDOWN_GetArrowRect(wndPtr
, rect
, TRUE
);
149 if(PtInRect32(rect
, pt
))
152 UPDOWN_GetArrowRect(wndPtr
, rect
, FALSE
);
157 /***********************************************************************
158 * UPDOWN_GetThousandSep
159 * Returns the thousand sep. If an error occurs, it returns ','.
161 static char UPDOWN_GetThousandSep()
165 if(GetLocaleInfo32A(LOCALE_USER_DEFAULT
, LOCALE_STHOUSAND
,
166 sep
, sizeof(sep
)) != 1)
172 /***********************************************************************
174 * Tries to read the pos from the buddy window and if it succeeds,
175 * it stores it in the control's CurVal
177 * TRUE - if it read the integer from the buddy successfully
178 * FALSE - if an error occured
180 static BOOL32
UPDOWN_GetBuddyInt(WND
*wndPtr
)
182 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
183 char txt
[20], sep
, *src
, *dst
;
186 if (!IsWindow32(infoPtr
->Buddy
))
189 /*if the buddy is a list window, we must set curr index */
190 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_LISTBOX
)){
191 newVal
= SendMessage32A(infoPtr
->Buddy
, LB_GETCARETINDEX32
, 0, 0);
196 /* we have a regural window, so will get the text */
197 if (!GetWindowText32A(infoPtr
->Buddy
, txt
, sizeof(txt
)))
200 sep
= UPDOWN_GetThousandSep();
202 /* now get rid of the separators */
203 for(src
= dst
= txt
; *src
; src
++)
208 /* try to convert the number and validate it */
209 newVal
= strtol(txt
, &src
, infoPtr
->Base
);
210 if(*src
|| !UPDOWN_InBounds(wndPtr
, newVal
))
213 dprintf_updown(stddeb
, "UpDown Ctrl: new value(%d) read from buddy "
214 "(old=%d)\n", newVal
, infoPtr
->CurVal
);
217 infoPtr
->CurVal
= newVal
;
222 /***********************************************************************
224 * Tries to set the pos to the buddy window based on current pos
226 * TRUE - if it set the caption of the buddy successfully
227 * FALSE - if an error occured
229 static BOOL32
UPDOWN_SetBuddyInt(WND
*wndPtr
)
231 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
235 if (!IsWindow32(infoPtr
->Buddy
))
238 dprintf_updown(stddeb
, "UpDown Ctrl: set new value(%d) to buddy.\n",
241 /*if the buddy is a list window, we must set curr index */
242 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_LISTBOX
)){
243 SendMessage32A(infoPtr
->Buddy
, LB_SETCURSEL32
, infoPtr
->CurVal
, 0);
245 else{ /* Regural window, so set caption to the number */
246 len
= sprintf(txt1
, (infoPtr
->Base
==16) ? "%X" : "%d", infoPtr
->CurVal
);
248 sep
= UPDOWN_GetThousandSep();
250 if (!(wndPtr
->dwStyle
& UDS_NOTHOUSANDS
)) {
251 char txt2
[20], *src
= txt1
, *dst
= txt2
;
253 strncpy(dst
, src
, len
%3);
257 for(len
=0; *src
; len
++,src
++){
262 *dst
= 0; /* null terminate it */
263 strcpy(txt1
, txt2
); /* move it to the proper place */
265 SetWindowText32A(infoPtr
->Buddy
, txt1
);
271 /***********************************************************************
273 * Draw the arrows for the up-down control. The arrows are drawn with the
274 * current pen and filled with the current brush.
276 * hdc - the DC to draw on
277 * rect - rectangle holding the arrow
278 * incr - TRUE if we draw the "increment" arrow
279 * FALSE if we draw the "decrement" arrow
280 * pressed - TRUE if the arrow is pressed (clicked)
281 * FALSE if the arrow is not pressed (clicked)
282 * horz - TRUE if the arrow is horizontal
283 * FLASE if the arrow is vertical
285 static void UPDOWN_DrawArrow(HDC32 hdc
, RECT32
*rect
, BOOL32 incr
,
286 BOOL32 pressed
, BOOL32 horz
)
288 const int rw
= rect
->right
- rect
->left
;
289 const int rh
= rect
->bottom
- rect
->top
;
290 int offset
= pressed
? 1 : 0;
293 /* compute max extents of the triangle */
294 if(horz
){ /* horizontal arrows */
301 /* compute the position of the tip */
302 y
= (rect
->top
+rect
->bottom
+1)/2 + offset
;
304 x
= (rect
->left
+rect
->right
+1)/2 + (2*th
)/3 + offset
;
306 x
= (rect
->left
+rect
->right
)/2 + th
/3 + offset
;
308 for(len
=1; th
>0; th
--, len
+=2){
309 MoveToEx32(hdc
, x
, y
, 0);
310 LineTo32(hdc
, x
, y
+len
);
316 else{ /* vertical arrows */
323 /* compute the position of the tip */
324 x
= (rect
->left
+rect
->right
+1)/2 + offset
;
326 y
= (rect
->top
+rect
->bottom
+1)/2 - th
/3 + offset
;
328 y
= (rect
->top
+rect
->bottom
)/2 + (2*th
)/3 + offset
;
330 for(len
=1; th
>0; th
--, len
+=2){
331 MoveToEx32(hdc
, x
, y
, 0);
332 LineTo32(hdc
, x
+len
, y
);
342 /***********************************************************************
344 * Draw the arrows. The background need not be erased.
346 static void UPDOWN_Paint(WND
*wndPtr
)
348 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
355 hdc
= BeginPaint32( wndPtr
->hwndSelf
, &ps
);
357 /* First select the proper brush */
358 oldBrush
= wndPtr
->dwStyle
& WS_DISABLED
? GRAY_BRUSH
: BLACK_BRUSH
;
359 oldBrush
= SelectObject32(hdc
, GetStockObject32(oldBrush
));
361 /* Draw the incr button */
362 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
363 prssed
= (infoPtr
->Flags
& FLAG_INCR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
364 DrawEdge32(hdc
, &rect
, prssed
?EDGE_SUNKEN
:EDGE_RAISED
, BF_RECT
|BF_MIDDLE
);
365 UPDOWN_DrawArrow(hdc
, &rect
, TRUE
, prssed
, wndPtr
->dwStyle
& UDS_HORZ
);
367 /* Draw the space between the buttons */
368 rect
.top
= rect
.bottom
; rect
.bottom
++;
369 DrawEdge32(hdc
, &rect
, 0, BF_MIDDLE
);
371 /* Draw the decr button */
372 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
373 prssed
= (infoPtr
->Flags
& FLAG_DECR
) && (infoPtr
->Flags
& FLAG_MOUSEIN
);
374 DrawEdge32(hdc
, &rect
, prssed
? EDGE_SUNKEN
: EDGE_RAISED
,
375 BF_RECT
| BF_SOFT
| BF_MIDDLE
);
376 UPDOWN_DrawArrow(hdc
, &rect
, FALSE
, prssed
, wndPtr
->dwStyle
& UDS_HORZ
);
379 SelectObject32(hdc
, oldBrush
);
380 EndPaint32( wndPtr
->hwndSelf
, &ps
);
383 /***********************************************************************
385 * Tests if 'hwndBud' is a valid window handle. If not, returns FALSE.
386 * Else, sets it as a new Buddy.
387 * Then, it should subclass the buddy
388 * If window has the UDS_ARROWKEYS, it subcalsses the buddy window to
389 * process the UP/DOWN arrow keys.
390 * If window has the UDS_ALIGNLEFT or UDS_ALIGNRIGHT style
391 * the size/pos of the buddy and the control are adjusted accordingly.
393 static BOOL32
UPDOWN_SetBuddy(WND
*wndPtr
, HWND32 hwndBud
)
395 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
396 RECT32 budRect
; /* new coord for the buddy */
397 int x
; /* new x position and width for the up-down */
399 /* Is is a valid bud? */
400 if(!IsWindow32(hwndBud
))
403 if(wndPtr
->dwStyle
& UDS_ARROWKEYS
){
404 /* FIXME: we need to subclass the buddy to process the arrow keys. */
405 fprintf(stderr
, "UpDown Ctrl: we should subclass the buddy window!\n");
408 /* do we need to do any adjustments? */
409 if(!(wndPtr
->dwStyle
& (UDS_ALIGNLEFT
| UDS_ALIGNRIGHT
)))
412 /* Get the rect of the buddy relative to its parent */
413 GetWindowRect32(infoPtr
->Buddy
, &budRect
);
414 MapWindowPoints32(HWND_DESKTOP
, GetParent32(infoPtr
->Buddy
),
415 (POINT32
*)(&budRect
.left
), 2);
417 /* now do the positioning */
418 if(wndPtr
->dwStyle
& UDS_ALIGNRIGHT
){
419 budRect
.right
-= DEFAULT_WIDTH
+DEFAULT_XSEP
;
420 x
= budRect
.right
+DEFAULT_XSEP
;
422 else{ /* UDS_ALIGNLEFT */
424 budRect
.left
+= DEFAULT_WIDTH
+DEFAULT_XSEP
;
427 /* first adjust the buddy to accomodate the up/down */
428 SetWindowPos32(infoPtr
->Buddy
, 0, budRect
.left
, budRect
.top
,
429 budRect
.right
- budRect
.left
, budRect
.bottom
- budRect
.top
,
430 SWP_NOACTIVATE
|SWP_NOZORDER
);
432 /* now position the up/down */
433 /* Since the UDS_ALIGN* flags were used, */
434 /* we will pick the position and size of the window. */
435 SetWindowPos32(wndPtr
->hwndSelf
,0,x
,budRect
.top
-DEFAULT_ADDTOP
,DEFAULT_WIDTH
,
436 (budRect
.bottom
-budRect
.top
)+DEFAULT_ADDTOP
+DEFAULT_ADDBOT
,
437 SWP_NOACTIVATE
|SWP_NOZORDER
);
442 /***********************************************************************
445 * This function increments/decrements the CurVal by the
446 * 'delta' amount according to the 'incr' flag
447 * It notifies the parent as required.
448 * It handles wraping and non-wraping correctly.
449 * It is assumed that delta>0
451 static void UPDOWN_DoAction(WND
*wndPtr
, int delta
, BOOL32 incr
)
453 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
454 int old_val
= infoPtr
->CurVal
;
457 dprintf_updown(stddeb
, "UpDown Ctrl action: %s by %d\n",
458 incr
? "inc" : "dec", delta
);
460 /* check if we can do the modification first */
461 delta
*= (incr
? 1 : -1) * (infoPtr
->MaxVal
< infoPtr
->MinVal
? -1 : 1);
462 if(!UPDOWN_OffsetVal(wndPtr
, delta
))
465 /* so, if we can do the change, recompute delta and restore old value */
466 delta
= infoPtr
->CurVal
- old_val
;
467 infoPtr
->CurVal
= old_val
;
469 /* We must notify parent now to obtain permission */
470 ni
.iPos
= infoPtr
->CurVal
;
472 ni
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
473 ni
.hdr
.idFrom
= wndPtr
->wIDmenu
;
474 ni
.hdr
.code
= UDN_DELTAPOS
;
475 if(SendMessage32A(wndPtr
->parent
->hwndSelf
,
476 WM_NOTIFY
, wndPtr
->wIDmenu
, (LPARAM
)&ni
))
477 return; /* we are not allowed to change */
479 /* Now adjust value with (maybe new) delta */
480 if(!UPDOWN_OffsetVal(wndPtr
, ni
.iDelta
))
483 /* Now take care about our buddy */
484 if(!IsWindow32(infoPtr
->Buddy
))
485 return; /* Nothing else to do */
488 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
489 UPDOWN_SetBuddyInt(wndPtr
);
491 /* Also, notify it */
492 /* FIXME: do we need to send the notification only if
493 we do not have the UDS_SETBUDDYINT style set? */
494 SendMessage32A(infoPtr
->Buddy
,
495 wndPtr
->dwStyle
& UDS_HORZ
? WM_HSCROLL
: WM_VSCROLL
,
496 MAKELONG(incr
? SB_LINEUP
: SB_LINEDOWN
, infoPtr
->CurVal
),
500 /***********************************************************************
503 * Returns TRUE if it is enabled as well as its buddy (if any)
506 static BOOL32
UPDOWN_IsEnabled(WND
*wndPtr
)
508 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
510 if(wndPtr
->dwStyle
& WS_DISABLED
)
512 return IsWindowEnabled32(infoPtr
->Buddy
);
515 /***********************************************************************
518 * Deletes any timers, releases the mouse and does redraw if necessary.
519 * If the control is not in "capture" mode, it does nothing.
520 * If the control was not in cancel mode, it returns FALSE.
521 * If the control was in cancel mode, it returns TRUE.
523 static BOOL32
UPDOWN_CancelMode(WND
*wndPtr
)
525 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
527 /* if not in 'capture' mode, do nothing */
528 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
531 KillTimer32(wndPtr
->hwndSelf
, TIMERID1
); /* kill all possible timers */
532 KillTimer32(wndPtr
->hwndSelf
, TIMERID2
);
534 if(GetCapture32() == wndPtr
->hwndSelf
) /* let the mouse go */
535 ReleaseCapture(); /* if we still have it */
537 infoPtr
->Flags
= 0; /* get rid of any flags */
538 UPDOWN_Paint(wndPtr
); /* redraw the control just in case */
543 /***********************************************************************
544 * UPDOWN_HandleMouseEvent
546 * Handle a mouse event for the updown.
547 * 'pt' is the location of the mouse event in client or
548 * windows coordinates.
550 static void UPDOWN_HandleMouseEvent(WND
*wndPtr
, UINT32 msg
, POINT32 pt
)
552 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
558 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
559 /* If we are already in the 'clicked' mode, then nothing to do */
560 if(infoPtr
->Flags
& FLAG_CLICKED
)
563 /* If the buddy is an edit, will set focus to it */
564 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
565 SetFocus32(infoPtr
->Buddy
);
567 /* Now see which one is the 'active' arrow */
568 temp
= UPDOWN_GetArrowFromPoint(wndPtr
, &rect
, pt
);
570 /* Update the CurVal if necessary */
571 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
572 UPDOWN_GetBuddyInt(wndPtr
);
574 /* Before we proceed, see if we can spin... */
575 if(!(wndPtr
->dwStyle
& UDS_WRAP
))
576 if(( temp
&& infoPtr
->CurVal
==infoPtr
->MaxVal
) ||
577 (!temp
&& infoPtr
->CurVal
==infoPtr
->MinVal
))
580 /* Set up the correct flags */
582 infoPtr
->Flags
|= temp
? FLAG_INCR
: FLAG_DECR
;
583 infoPtr
->Flags
|= FLAG_MOUSEIN
;
585 /* repaint the control */
586 UPDOWN_Paint(wndPtr
);
588 /* process the click */
589 UPDOWN_DoAction(wndPtr
, 1, infoPtr
->Flags
& FLAG_INCR
);
591 /* now capture all mouse messages */
592 SetCapture32(wndPtr
->hwndSelf
);
594 /* and startup the first timer */
595 SetTimer32(wndPtr
->hwndSelf
, TIMERID1
, INITIAL_DELAY
, 0);
599 /* If we are not in the 'clicked' mode, then nothing to do */
600 if(!(infoPtr
->Flags
& FLAG_CLICKED
))
603 /* save the flags to see if any got modified */
604 temp
= infoPtr
->Flags
;
606 /* Now get the 'active' arrow rectangle */
607 if (infoPtr
->Flags
& FLAG_INCR
)
608 UPDOWN_GetArrowRect(wndPtr
, &rect
, TRUE
);
610 UPDOWN_GetArrowRect(wndPtr
, &rect
, FALSE
);
612 /* Update the flags if we are in/out */
613 if(PtInRect32(&rect
, pt
))
614 infoPtr
->Flags
|= FLAG_MOUSEIN
;
616 infoPtr
->Flags
&= ~FLAG_MOUSEIN
;
617 if(accelIndex
!= -1) /* if we have accel info */
618 accelIndex
= 0; /* reset it */
620 /* If state changed, redraw the control */
621 if(temp
!= infoPtr
->Flags
)
622 UPDOWN_Paint(wndPtr
);
626 fprintf(stderr
, "UpDown: Impossible case in proc "
627 "UPDOWN_HandleMouseEvent");
632 /***********************************************************************
635 LRESULT WINAPI
UpDownWindowProc(HWND32 hwnd
, UINT32 message
, WPARAM32 wParam
,
638 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
639 UPDOWN_INFO
*infoPtr
= UPDOWN_GetInfoPtr(wndPtr
);
645 /* get rid of border, if any */
646 wndPtr
->dwStyle
&= ~WS_BORDER
;
648 /* initialize the info struct */
649 infoPtr
->AccelCount
=0; infoPtr
->AccelVect
=0;
650 infoPtr
->CurVal
=0; infoPtr
->MinVal
=0; infoPtr
->MaxVal
=100; /*FIXME*/
651 infoPtr
->Base
= 10; /* Default to base 10 */
652 infoPtr
->Buddy
= 0; /* No buddy window yet */
653 infoPtr
->Flags
= 0; /* And no flags */
655 /* Do we pick the buddy win ourselves? */
656 if(wndPtr
->dwStyle
& UDS_AUTOBUDDY
)
657 UPDOWN_SetBuddy(wndPtr
, GetWindow32(wndPtr
->hwndSelf
, GW_HWNDPREV
));
659 dprintf_updown(stddeb
, "UpDown Ctrl creation, hwnd=%04x\n", hwnd
);
663 if(infoPtr
->AccelVect
)
664 free(infoPtr
->AccelVect
);
665 dprintf_updown(stddeb
, "UpDown Ctrl destruction, hwnd=%04x\n", hwnd
);
669 if(wndPtr
->dwStyle
& WS_DISABLED
)
670 UPDOWN_CancelMode(wndPtr
);
671 UPDOWN_Paint(wndPtr
);
675 /* if initial timer, kill it and start the repeat timer */
676 if(wParam
== TIMERID1
){
677 KillTimer32(hwnd
, TIMERID1
);
678 /* if no accel info given, used default timer */
679 if(infoPtr
->AccelCount
==0 || infoPtr
->AccelVect
==0){
684 accelIndex
= 0; /* otherwise, use it */
685 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
687 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
690 /* now, if the mouse is above us, do the thing...*/
691 if(infoPtr
->Flags
& FLAG_MOUSEIN
){
692 temp
= accelIndex
==-1 ? 1 : infoPtr
->AccelVect
[accelIndex
].nInc
;
693 UPDOWN_DoAction(wndPtr
, temp
, infoPtr
->Flags
& FLAG_INCR
);
695 if(accelIndex
!=-1 && accelIndex
< infoPtr
->AccelCount
-1){
696 KillTimer32(hwnd
, TIMERID2
);
697 accelIndex
++; /* move to the next accel info */
698 temp
= infoPtr
->AccelVect
[accelIndex
].nSec
* 1000 + 1;
699 /* make sure we have at least 1ms intervals */
700 SetTimer32(hwnd
, TIMERID2
, temp
, 0);
706 UPDOWN_CancelMode(wndPtr
);
710 if(!UPDOWN_CancelMode(wndPtr
))
712 /*If we released the mouse and our buddy is an edit */
713 /* we must select all text in it. */
714 if(WIDGETS_IsControl32(WIN_FindWndPtr(infoPtr
->Buddy
), BIC32_EDIT
))
715 SendMessage32A(infoPtr
->Buddy
, EM_SETSEL32
, 0, MAKELONG(0, -1));
720 if(UPDOWN_IsEnabled(wndPtr
)){
722 CONV_POINT16TO32( (POINT16
*)&lParam
, &pt
);
723 UPDOWN_HandleMouseEvent( wndPtr
, message
, pt
);
728 if((wndPtr
->dwStyle
& UDS_ARROWKEYS
) && UPDOWN_IsEnabled(wndPtr
)){
732 UPDOWN_GetBuddyInt(wndPtr
);
733 UPDOWN_DoAction(wndPtr
, 1, wParam
==VK_UP
);
740 UPDOWN_Paint(wndPtr
);
744 if (wParam
==0 && lParam
==0) /*if both zero, */
745 return infoPtr
->AccelCount
; /*just return the accel count*/
746 if (wParam
|| lParam
){
747 UNKNOWN_PARAM(UDM_GETACCEL
, wParam
, lParam
);
750 temp
= MIN(infoPtr
->AccelCount
, wParam
);
751 memcpy((void *)lParam
, infoPtr
->AccelVect
, temp
*sizeof(UDACCEL
));
755 dprintf_updown(stddeb
, "UpDown Ctrl new accel info, hwnd=%04x\n", hwnd
);
756 if(infoPtr
->AccelVect
){
757 free(infoPtr
->AccelVect
);
758 infoPtr
->AccelCount
= 0;
759 infoPtr
->AccelVect
= 0;
763 infoPtr
->AccelVect
= malloc(wParam
*sizeof(UDACCEL
));
764 if(infoPtr
->AccelVect
==0)
766 memcpy(infoPtr
->AccelVect
, (void*)lParam
, wParam
*sizeof(UDACCEL
));
770 if (wParam
|| lParam
)
771 UNKNOWN_PARAM(UDM_GETBASE
, wParam
, lParam
);
772 return infoPtr
->Base
;
775 dprintf_updown(stddeb
, "UpDown Ctrl new base(%d), hwnd=%04x\n",
777 if ( !(wParam
==10 || wParam
==16) || lParam
)
778 UNKNOWN_PARAM(UDM_SETBASE
, wParam
, lParam
);
779 if (wParam
==10 || wParam
==16){
780 temp
= infoPtr
->Base
;
781 infoPtr
->Base
= wParam
;
782 return temp
; /* return the prev base */
787 if (wParam
|| lParam
)
788 UNKNOWN_PARAM(UDM_GETBUDDY
, wParam
, lParam
);
789 return infoPtr
->Buddy
;
793 UNKNOWN_PARAM(UDM_SETBUDDY
, wParam
, lParam
);
794 temp
= infoPtr
->Buddy
;
795 infoPtr
->Buddy
= wParam
;
796 UPDOWN_SetBuddy(wndPtr
, wParam
);
797 dprintf_updown(stddeb
, "UpDown Ctrl new buddy(%04x), hwnd=%04x\n",
798 infoPtr
->Buddy
, hwnd
);
802 if (wParam
|| lParam
)
803 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
804 temp
= UPDOWN_GetBuddyInt(wndPtr
);
805 return MAKELONG(infoPtr
->CurVal
, temp
? 0 : 1);
808 if (wParam
|| HIWORD(lParam
))
809 UNKNOWN_PARAM(UDM_GETPOS
, wParam
, lParam
);
810 temp
= SLOWORD(lParam
);
811 dprintf_updown(stddeb
, "UpDown Ctrl new value(%d), hwnd=%04x\n",
813 if(!UPDOWN_InBounds(wndPtr
, temp
)){
814 if(temp
< infoPtr
->MinVal
)
815 temp
= infoPtr
->MinVal
;
816 if(temp
> infoPtr
->MaxVal
)
817 temp
= infoPtr
->MaxVal
;
819 wParam
= infoPtr
->CurVal
; /* save prev value */
820 infoPtr
->CurVal
= temp
; /* set the new value */
821 if(wndPtr
->dwStyle
& UDS_SETBUDDYINT
)
822 UPDOWN_SetBuddyInt(wndPtr
);
823 return wParam
; /* return prev value */
826 if (wParam
|| lParam
)
827 UNKNOWN_PARAM(UDM_GETRANGE
, wParam
, lParam
);
828 return MAKELONG(infoPtr
->MaxVal
, infoPtr
->MinVal
);
832 UNKNOWN_PARAM(UDM_SETRANGE
, wParam
, lParam
); /* we must have: */
833 infoPtr
->MaxVal
= SLOWORD(lParam
); /* UD_MINVAL <= Max <= UD_MAXVAL */
834 infoPtr
->MinVal
= SHIWORD(lParam
); /* UD_MINVAL <= Min <= UD_MAXVAL */
835 /* |Max-Min| <= UD_MAXVAL */
836 dprintf_updown(stddeb
, "UpDown Ctrl new range(%d to %d), hwnd=%04x\n",
837 infoPtr
->MinVal
, infoPtr
->MaxVal
, hwnd
);
841 if (message
>= WM_USER
)
842 fprintf( stderr
, "UpDown Ctrl: unknown msg %04x wp=%04x lp=%08lx\n",
843 message
, wParam
, lParam
);
844 return DefWindowProc32A( hwnd
, message
, wParam
, lParam
);
850 /***********************************************************************
851 * CreateUpDownControl (COMCTL32.14)
853 HWND32 WINAPI
CreateUpDownControl( DWORD style
, INT32 x
, INT32 y
,
854 INT32 cx
, INT32 cy
, HWND32 parent
,
855 INT32 id
, HINSTANCE32 inst
, HWND32 buddy
,
856 INT32 maxVal
, INT32 minVal
, INT32 curVal
)
858 HWND32 hUD
= CreateWindow32A(UPDOWN_CLASS32A
, 0, style
, x
, y
, cx
, cy
,
859 parent
, id
, inst
, 0);
861 SendMessage32A(hUD
, UDM_SETBUDDY
, buddy
, 0);
862 SendMessage32A(hUD
, UDM_SETRANGE
, 0, MAKELONG(maxVal
, minVal
));
863 SendMessage32A(hUD
, UDM_SETPOS
, 0, MAKELONG(curVal
, 0));