ReactOS  0.4.14-dev-384-g5b37caa
updown.c
Go to the documentation of this file.
1 /*
2  * Updown control
3  *
4  * Copyright 1997, 2002 Dimitrie O. Paun
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winnls.h"
31 #include "commctrl.h"
32 #include "comctl32.h"
33 #include "uxtheme.h"
34 #include "vssym32.h"
35 #include "wine/heap.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38 
40 
41 typedef struct
42 {
43  HWND Self; /* Handle to this up-down control */
44  HWND Notify; /* Handle to the parent window */
45  DWORD dwStyle; /* The GWL_STYLE for this window */
46  UINT AccelCount; /* Number of elements in AccelVect */
47  UDACCEL* AccelVect; /* Vector containing AccelCount elements */
48  INT AccelIndex; /* Current accel index, -1 if not accel'ing */
49  INT Base; /* Base to display nr in the buddy window */
50  INT CurVal; /* Current up-down value */
51  INT MinVal; /* Minimum up-down value */
52  INT MaxVal; /* Maximum up-down value */
53  HWND Buddy; /* Handle to the buddy window */
54  INT BuddyType; /* Remembers the buddy type BUDDY_TYPE_* */
55  INT Flags; /* Internal Flags FLAG_* */
56  BOOL UnicodeFormat; /* Marks the use of Unicode internally */
57 } UPDOWN_INFO;
58 
59 /* Control configuration constants */
60 
61 #define INITIAL_DELAY 500 /* initial timer until auto-inc kicks in */
62 #define AUTOPRESS_DELAY 250 /* time to keep arrow pressed on KEY_DOWN */
63 #define REPEAT_DELAY 50 /* delay between auto-increments */
64 
65 #define DEFAULT_WIDTH 16 /* default width of the ctrl */
66 #define DEFAULT_XSEP 0 /* default separation between buddy and ctrl */
67 #define DEFAULT_ADDTOP 0 /* amount to extend above the buddy window */
68 #define DEFAULT_ADDBOT 0 /* amount to extend below the buddy window */
69 #define DEFAULT_BUDDYBORDER 2 /* Width/height of the buddy border */
70 #define DEFAULT_BUDDYSPACER 2 /* Spacer between the buddy and the ctrl */
71 #define DEFAULT_BUDDYBORDER_THEMED 1 /* buddy border when theming is enabled */
72 #define DEFAULT_BUDDYSPACER_THEMED 0 /* buddy spacer when theming is enabled */
73 
74 /* Work constants */
75 
76 #define FLAG_INCR 0x01
77 #define FLAG_DECR 0x02
78 #define FLAG_MOUSEIN 0x04
79 #define FLAG_PRESSED 0x08
80 #define FLAG_BUDDYINT 0x10 /* UDS_SETBUDDYINT was set on creation */
81 #define FLAG_ARROW (FLAG_INCR | FLAG_DECR)
82 
83 #define BUDDY_TYPE_UNKNOWN 0
84 #define BUDDY_TYPE_LISTBOX 1
85 #define BUDDY_TYPE_EDIT 2
86 
87 #define TIMER_AUTOREPEAT 1
88 #define TIMER_ACCEL 2
89 #define TIMER_AUTOPRESS 3
90 
91 #define UPDOWN_GetInfoPtr(hwnd) ((UPDOWN_INFO *)GetWindowLongPtrW (hwnd,0))
92 
93 /* id used for SetWindowSubclass */
94 #define BUDDY_SUBCLASSID 1
95 
96 static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, int action);
97 
98 /***********************************************************************
99  * UPDOWN_IsBuddyEdit
100  * Tests if our buddy is an edit control.
101  */
102 static inline BOOL UPDOWN_IsBuddyEdit(const UPDOWN_INFO *infoPtr)
103 {
104  return infoPtr->BuddyType == BUDDY_TYPE_EDIT;
105 }
106 
107 /***********************************************************************
108  * UPDOWN_IsBuddyListbox
109  * Tests if our buddy is a listbox control.
110  */
111 static inline BOOL UPDOWN_IsBuddyListbox(const UPDOWN_INFO *infoPtr)
112 {
113  return infoPtr->BuddyType == BUDDY_TYPE_LISTBOX;
114 }
115 
116 /***********************************************************************
117  * UPDOWN_InBounds
118  * Tests if a given value 'val' is between the Min&Max limits
119  */
120 static BOOL UPDOWN_InBounds(const UPDOWN_INFO *infoPtr, int val)
121 {
122  if(infoPtr->MaxVal > infoPtr->MinVal)
123  return (infoPtr->MinVal <= val) && (val <= infoPtr->MaxVal);
124  else
125  return (infoPtr->MaxVal <= val) && (val <= infoPtr->MinVal);
126 }
127 
128 /***********************************************************************
129  * UPDOWN_OffsetVal
130  * Change the current value by delta.
131  * It returns TRUE is the value was changed successfully, or FALSE
132  * if the value was not changed, as it would go out of bounds.
133  */
134 static BOOL UPDOWN_OffsetVal(UPDOWN_INFO *infoPtr, int delta)
135 {
136  /* check if we can do the modification first */
137  if(!UPDOWN_InBounds (infoPtr, infoPtr->CurVal+delta)) {
138  if (infoPtr->dwStyle & UDS_WRAP) {
139  delta += (delta < 0 ? -1 : 1) *
140  (infoPtr->MaxVal < infoPtr->MinVal ? -1 : 1) *
141  (infoPtr->MinVal - infoPtr->MaxVal) +
142  (delta < 0 ? 1 : -1);
143  } else if ((infoPtr->MaxVal > infoPtr->MinVal && infoPtr->CurVal+delta > infoPtr->MaxVal)
144  || (infoPtr->MaxVal < infoPtr->MinVal && infoPtr->CurVal+delta < infoPtr->MaxVal)) {
145  delta = infoPtr->MaxVal - infoPtr->CurVal;
146  } else {
147  delta = infoPtr->MinVal - infoPtr->CurVal;
148  }
149  }
150 
151  infoPtr->CurVal += delta;
152  return delta != 0;
153 }
154 
155 /***********************************************************************
156  * UPDOWN_HasBuddyBorder
157  *
158  * When we have a buddy set and that we are aligned on our buddy, we
159  * want to draw a sunken edge to make like we are part of that control.
160  */
161 static BOOL UPDOWN_HasBuddyBorder(const UPDOWN_INFO *infoPtr)
162 {
163  return ( ((infoPtr->dwStyle & (UDS_ALIGNLEFT | UDS_ALIGNRIGHT)) != 0) &&
164  UPDOWN_IsBuddyEdit(infoPtr) );
165 }
166 
167 /***********************************************************************
168  * UPDOWN_GetArrowRect
169  * wndPtr - pointer to the up-down wnd
170  * rect - will hold the rectangle
171  * arrow - FLAG_INCR to get the "increment" rect (up or right)
172  * FLAG_DECR to get the "decrement" rect (down or left)
173  * If both flags are present, the envelope is returned.
174  */
175 static void UPDOWN_GetArrowRect (const UPDOWN_INFO* infoPtr, RECT *rect, int arrow)
176 {
177  HTHEME theme = GetWindowTheme (infoPtr->Self);
179  const int spacer = theme ? DEFAULT_BUDDYSPACER_THEMED : DEFAULT_BUDDYSPACER;
180  GetClientRect (infoPtr->Self, rect);
181 
182  /*
183  * Make sure we calculate the rectangle to fit even if we draw the
184  * border.
185  */
186  if (UPDOWN_HasBuddyBorder(infoPtr)) {
187  if (infoPtr->dwStyle & UDS_ALIGNLEFT)
188  rect->left += border;
189  else
190  rect->right -= border;
191 
192  InflateRect(rect, 0, -border);
193  }
194 
195  /* now figure out if we need a space away from the buddy */
196  if (IsWindow(infoPtr->Buddy) ) {
197  if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->right -= spacer;
198  else if (infoPtr->dwStyle & UDS_ALIGNRIGHT) rect->left += spacer;
199  }
200 
201  /*
202  * We're calculating the midpoint to figure-out where the
203  * separation between the buttons will lay. We make sure that we
204  * round the uneven numbers by adding 1.
205  */
206  if (infoPtr->dwStyle & UDS_HORZ) {
207  int len = rect->right - rect->left + 1; /* compute the width */
208  if (arrow & FLAG_INCR)
209  rect->left = rect->left + len/2;
210  if (arrow & FLAG_DECR)
211  rect->right = rect->left + len/2 - (theme ? 0 : 1);
212  } else {
213  int len = rect->bottom - rect->top + 1; /* compute the height */
214  if (arrow & FLAG_INCR)
215  rect->bottom = rect->top + len/2 - (theme ? 0 : 1);
216  if (arrow & FLAG_DECR)
217  rect->top = rect->top + len/2;
218  }
219 }
220 
221 /***********************************************************************
222  * UPDOWN_GetArrowFromPoint
223  * Returns the rectagle (for the up or down arrow) that contains pt.
224  * If it returns the up rect, it returns FLAG_INCR.
225  * If it returns the down rect, it returns FLAG_DECR.
226  */
228 {
229  UPDOWN_GetArrowRect (infoPtr, rect, FLAG_INCR);
230  if(PtInRect(rect, pt)) return FLAG_INCR;
231 
232  UPDOWN_GetArrowRect (infoPtr, rect, FLAG_DECR);
233  if(PtInRect(rect, pt)) return FLAG_DECR;
234 
235  return 0;
236 }
237 
238 
239 /***********************************************************************
240  * UPDOWN_GetThousandSep
241  * Returns the thousand sep. If an error occurs, it returns ','.
242  */
244 {
245  WCHAR sep[2];
246 
248  sep[0] = ',';
249 
250  return sep[0];
251 }
252 
253 /***********************************************************************
254  * UPDOWN_GetBuddyInt
255  * Tries to read the pos from the buddy window and if it succeeds,
256  * it stores it in the control's CurVal
257  * returns:
258  * TRUE - if it read the integer from the buddy successfully
259  * FALSE - if an error occurred
260  */
262 {
263  WCHAR txt[20], sep, *src, *dst;
264  int newVal;
265 
266  if (!((infoPtr->Flags & FLAG_BUDDYINT) && IsWindow(infoPtr->Buddy)))
267  return FALSE;
268 
269  /*if the buddy is a list window, we must set curr index */
270  if (UPDOWN_IsBuddyListbox(infoPtr)) {
271  newVal = SendMessageW(infoPtr->Buddy, LB_GETCARETINDEX, 0, 0);
272  if(newVal < 0) return FALSE;
273  } else {
274  /* we have a regular window, so will get the text */
275  /* note that a zero-length string is a legitimate value for 'txt',
276  * and ought to result in a successful conversion to '0'. */
277  if (GetWindowTextW(infoPtr->Buddy, txt, ARRAY_SIZE(txt)) < 0)
278  return FALSE;
279 
280  sep = UPDOWN_GetThousandSep();
281 
282  /* now get rid of the separators */
283  for(src = dst = txt; *src; src++)
284  if(*src != sep) *dst++ = *src;
285  *dst = 0;
286 
287  /* try to convert the number and validate it */
288  newVal = strtolW(txt, &src, infoPtr->Base);
289  if(*src || !UPDOWN_InBounds (infoPtr, newVal)) return FALSE;
290  }
291 
292  TRACE("new value(%d) from buddy (old=%d)\n", newVal, infoPtr->CurVal);
293  infoPtr->CurVal = newVal;
294  return TRUE;
295 }
296 
297 
298 /***********************************************************************
299  * UPDOWN_SetBuddyInt
300  * Tries to set the pos to the buddy window based on current pos
301  * returns:
302  * TRUE - if it set the caption of the buddy successfully
303  * FALSE - if an error occurred
304  */
305 static BOOL UPDOWN_SetBuddyInt (const UPDOWN_INFO *infoPtr)
306 {
307  static const WCHAR fmt_hex[] = { '0', 'x', '%', '0', '4', 'X', 0 };
308  static const WCHAR fmt_dec_oct[] = { '%', 'd', '\0' };
309  const WCHAR *fmt;
310  WCHAR txt[20], txt_old[20] = { 0 };
311  int len;
312 
313  if (!((infoPtr->Flags & FLAG_BUDDYINT) && IsWindow(infoPtr->Buddy)))
314  return FALSE;
315 
316  TRACE("set new value(%d) to buddy.\n", infoPtr->CurVal);
317 
318  /*if the buddy is a list window, we must set curr index */
319  if (UPDOWN_IsBuddyListbox(infoPtr)) {
320  return SendMessageW(infoPtr->Buddy, LB_SETCURSEL, infoPtr->CurVal, 0) != LB_ERR;
321  }
322 
323  /* Regular window, so set caption to the number */
324  fmt = (infoPtr->Base == 16) ? fmt_hex : fmt_dec_oct;
325  len = wsprintfW(txt, fmt, infoPtr->CurVal);
326 
327 
328  /* Do thousands separation if necessary */
329  if ((infoPtr->Base == 10) && !(infoPtr->dwStyle & UDS_NOTHOUSANDS) && (len > 3)) {
330  WCHAR tmp[ARRAY_SIZE(txt)], *src = tmp, *dst = txt;
332  int start = len % 3;
333 
334  memcpy(tmp, txt, sizeof(txt));
335  if (start == 0) start = 3;
336  dst += start;
337  src += start;
338  for (len=0; *src; len++) {
339  if (len % 3 == 0) *dst++ = sep;
340  *dst++ = *src++;
341  }
342  *dst = 0;
343  }
344 
345  /* if nothing changed exit earlier */
346  GetWindowTextW(infoPtr->Buddy, txt_old, ARRAY_SIZE(txt_old));
347  if (lstrcmpiW(txt_old, txt) == 0) return FALSE;
348 
349  return SetWindowTextW(infoPtr->Buddy, txt);
350 }
351 
352 /***********************************************************************
353  * UPDOWN_DrawBuddyBackground
354  *
355  * Draw buddy background for visual integration.
356  */
358 {
359  RECT br, r;
360  HTHEME buddyTheme = GetWindowTheme (infoPtr->Buddy);
361  if (!buddyTheme) return FALSE;
362 
363  GetWindowRect (infoPtr->Buddy, &br);
364  MapWindowPoints (NULL, infoPtr->Self, (POINT*)&br, 2);
365  GetClientRect (infoPtr->Self, &r);
366 
367  if (infoPtr->dwStyle & UDS_ALIGNLEFT)
368  br.left = r.left;
369  else if (infoPtr->dwStyle & UDS_ALIGNRIGHT)
370  br.right = r.right;
371  /* FIXME: take disabled etc. into account */
372  DrawThemeBackground (buddyTheme, hdc, 0, 0, &br, NULL);
373  return TRUE;
374 }
375 
376 /***********************************************************************
377  * UPDOWN_Draw
378  *
379  * Draw the arrows. The background need not be erased.
380  */
381 static LRESULT UPDOWN_Draw (const UPDOWN_INFO *infoPtr, HDC hdc)
382 {
383  BOOL uPressed, uHot, dPressed, dHot;
384  RECT rect;
385  HTHEME theme = GetWindowTheme (infoPtr->Self);
386  int uPart = 0, uState = 0, dPart = 0, dState = 0;
387  BOOL needBuddyBg = FALSE;
388 
389  uPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR);
390  uHot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
391  dPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR);
392  dHot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN);
393  if (theme) {
394  uPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_UPHORZ : SPNP_UP;
395  uState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED
396  : (uPressed ? DNS_PRESSED : (uHot ? DNS_HOT : DNS_NORMAL));
397  dPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_DOWNHORZ : SPNP_DOWN;
398  dState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED
399  : (dPressed ? DNS_PRESSED : (dHot ? DNS_HOT : DNS_NORMAL));
400  needBuddyBg = IsWindow (infoPtr->Buddy)
401  && (IsThemeBackgroundPartiallyTransparent (theme, uPart, uState)
402  || IsThemeBackgroundPartiallyTransparent (theme, dPart, dState));
403  }
404 
405  /* Draw the common border between ourselves and our buddy */
406  if (UPDOWN_HasBuddyBorder(infoPtr) || needBuddyBg) {
407  if (!theme || !UPDOWN_DrawBuddyBackground (infoPtr, hdc)) {
408  GetClientRect(infoPtr->Self, &rect);
410  BF_BOTTOM | BF_TOP |
411  (infoPtr->dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT));
412  }
413  }
414 
415  /* Draw the incr button */
416  UPDOWN_GetArrowRect (infoPtr, &rect, FLAG_INCR);
417  if (theme) {
418  DrawThemeBackground(theme, hdc, uPart, uState, &rect, NULL);
419  } else {
422  ((infoPtr->dwStyle & UDS_HOTTRACK) && uHot ? DFCS_HOT : 0) |
423  (uPressed ? DFCS_PUSHED : 0) |
424  (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
425  }
426 
427  /* Draw the decr button */
428  UPDOWN_GetArrowRect(infoPtr, &rect, FLAG_DECR);
429  if (theme) {
430  DrawThemeBackground(theme, hdc, dPart, dState, &rect, NULL);
431  } else {
434  ((infoPtr->dwStyle & UDS_HOTTRACK) && dHot ? DFCS_HOT : 0) |
435  (dPressed ? DFCS_PUSHED : 0) |
436  (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
437  }
438 
439  return 0;
440 }
441 
442 /***********************************************************************
443  * UPDOWN_Paint
444  *
445  * Asynchronous drawing (must ONLY be used in WM_PAINT).
446  * Calls UPDOWN_Draw.
447  */
448 static LRESULT UPDOWN_Paint (const UPDOWN_INFO *infoPtr, HDC hdc)
449 {
450  PAINTSTRUCT ps;
451  if (hdc) return UPDOWN_Draw (infoPtr, hdc);
452  hdc = BeginPaint (infoPtr->Self, &ps);
453  UPDOWN_Draw (infoPtr, hdc);
454  EndPaint (infoPtr->Self, &ps);
455  return 0;
456 }
457 
458 /***********************************************************************
459  * UPDOWN_KeyPressed
460  *
461  * Handle key presses (up & down) when we have to do so
462  */
464 {
465  int arrow, accel;
466 
467  if (key == VK_UP) arrow = FLAG_INCR;
468  else if (key == VK_DOWN) arrow = FLAG_DECR;
469  else return 1;
470 
471  UPDOWN_GetBuddyInt (infoPtr);
472  infoPtr->Flags &= ~FLAG_ARROW;
473  infoPtr->Flags |= FLAG_PRESSED | arrow;
474  InvalidateRect (infoPtr->Self, NULL, FALSE);
476  accel = (infoPtr->AccelCount && infoPtr->AccelVect) ? infoPtr->AccelVect[0].nInc : 1;
477  UPDOWN_DoAction (infoPtr, accel, arrow);
478  return 0;
479 }
480 
481 static int UPDOWN_GetPos(UPDOWN_INFO *infoPtr, BOOL *err)
482 {
483  BOOL succ = UPDOWN_GetBuddyInt(infoPtr);
484  int val = infoPtr->CurVal;
485 
486  if(!UPDOWN_InBounds(infoPtr, val)) {
487  if((infoPtr->MinVal < infoPtr->MaxVal && val < infoPtr->MinVal)
488  || (infoPtr->MinVal > infoPtr->MaxVal && val > infoPtr->MinVal))
489  val = infoPtr->MinVal;
490  else
491  val = infoPtr->MaxVal;
492 
493  succ = FALSE;
494  }
495 
496  if(err) *err = !succ;
497  return val;
498 }
499 
500 static int UPDOWN_SetPos(UPDOWN_INFO *infoPtr, int pos)
501 {
502  int ret = infoPtr->CurVal;
503 
504  if(!UPDOWN_InBounds(infoPtr, pos)) {
505  if((infoPtr->MinVal < infoPtr->MaxVal && pos < infoPtr->MinVal)
506  || (infoPtr->MinVal > infoPtr->MaxVal && pos > infoPtr->MinVal))
507  pos = infoPtr->MinVal;
508  else
509  pos = infoPtr->MaxVal;
510  }
511 
512  infoPtr->CurVal = pos;
513  UPDOWN_SetBuddyInt(infoPtr);
514 
515  if(!UPDOWN_InBounds(infoPtr, ret)) {
516  if((infoPtr->MinVal < infoPtr->MaxVal && ret < infoPtr->MinVal)
517  || (infoPtr->MinVal > infoPtr->MaxVal && ret > infoPtr->MinVal))
518  ret = infoPtr->MinVal;
519  else
520  ret = infoPtr->MaxVal;
521  }
522  return ret;
523 }
524 
525 
526 /***********************************************************************
527  * UPDOWN_SetRange
528  *
529  * Handle UDM_SETRANGE, UDM_SETRANGE32
530  *
531  * FIXME: handle Max == Min properly:
532  * - arrows should be disabled (without WS_DISABLED set),
533  * visually they can't be pressed and don't respond;
534  * - all input messages should still pass in.
535  */
537 {
538  infoPtr->MaxVal = Max;
539  infoPtr->MinVal = Min;
540 
541  TRACE("UpDown Ctrl new range(%d to %d), hwnd=%p\n",
542  infoPtr->MinVal, infoPtr->MaxVal, infoPtr->Self);
543 
544  return 0;
545 }
546 
547 /***********************************************************************
548  * UPDOWN_MouseWheel
549  *
550  * Handle mouse wheel scrolling
551  */
553 {
554  int iWheelDelta = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
555 
556  if (wParam & (MK_SHIFT | MK_CONTROL))
557  return 0;
558 
559  if (iWheelDelta != 0)
560  {
561  UPDOWN_GetBuddyInt(infoPtr);
562  UPDOWN_DoAction(infoPtr, abs(iWheelDelta), iWheelDelta > 0 ? FLAG_INCR : FLAG_DECR);
563  }
564 
565  return 1;
566 }
567 
568 
569 /***********************************************************************
570  * UPDOWN_Buddy_SubclassProc used to handle messages sent to the buddy
571  * control.
572  */
573 static LRESULT CALLBACK
575  UINT_PTR uId, DWORD_PTR ref_data)
576 {
577  UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr((HWND)ref_data);
578 
579  TRACE("hwnd=%p, uMsg=%04x, wParam=%08lx, lParam=%08lx\n",
580  hwnd, uMsg, wParam, lParam);
581 
582  switch(uMsg)
583  {
584  case WM_KEYDOWN:
585  if (infoPtr)
586  {
587  UPDOWN_KeyPressed(infoPtr, (int)wParam);
588  if (wParam == VK_UP || wParam == VK_DOWN)
589  return 0;
590  }
591  break;
592 
593  case WM_MOUSEWHEEL:
594  if (infoPtr)
595  UPDOWN_MouseWheel(infoPtr, (int)wParam);
596  break;
597 
598  case WM_NCDESTROY:
600  break;
601  default:
602  break;
603  }
604 
606 }
607 
608 static void UPDOWN_ResetSubclass (UPDOWN_INFO *infoPtr)
609 {
611 }
612 
613 /***********************************************************************
614  * UPDOWN_SetBuddy
615  *
616  * Sets bud as a new Buddy.
617  * Then, it should subclass the buddy
618  * If window has the UDS_ARROWKEYS, it subclasses the buddy window to
619  * process the UP/DOWN arrow keys.
620  * If window has the UDS_ALIGNLEFT or UDS_ALIGNRIGHT style
621  * the size/pos of the buddy and the control are adjusted accordingly.
622  */
623 static HWND UPDOWN_SetBuddy (UPDOWN_INFO* infoPtr, HWND bud)
624 {
625  RECT budRect; /* new coord for the buddy */
626  int x, width; /* new x position and width for the up-down */
627  WCHAR buddyClass[40];
628  HWND old_buddy;
629 
630  TRACE("(hwnd=%p, bud=%p)\n", infoPtr->Self, bud);
631 
632  old_buddy = infoPtr->Buddy;
633 
634  UPDOWN_ResetSubclass (infoPtr);
635 
636  if (!IsWindow(bud)) bud = NULL;
637 
638  /* Store buddy window handle */
639  infoPtr->Buddy = bud;
640 
641  if(bud) {
642  /* Store buddy window class type */
643  infoPtr->BuddyType = BUDDY_TYPE_UNKNOWN;
644  if (GetClassNameW(bud, buddyClass, ARRAY_SIZE(buddyClass))) {
645  if (lstrcmpiW(buddyClass, WC_EDITW) == 0)
646  infoPtr->BuddyType = BUDDY_TYPE_EDIT;
647  else if (lstrcmpiW(buddyClass, WC_LISTBOXW) == 0)
648  infoPtr->BuddyType = BUDDY_TYPE_LISTBOX;
649  }
650 
651  if (infoPtr->dwStyle & UDS_ARROWKEYS)
653  (DWORD_PTR)infoPtr->Self);
654 
655  /* Get the rect of the buddy relative to its parent */
656  GetWindowRect(infoPtr->Buddy, &budRect);
657  MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Buddy), (POINT *)(&budRect.left), 2);
658 
659  /* now do the positioning */
660  if (infoPtr->dwStyle & UDS_ALIGNLEFT) {
661  x = budRect.left;
662  budRect.left += DEFAULT_WIDTH + DEFAULT_XSEP;
663  } else if (infoPtr->dwStyle & UDS_ALIGNRIGHT) {
664  budRect.right -= DEFAULT_WIDTH + DEFAULT_XSEP;
665  x = budRect.right+DEFAULT_XSEP;
666  } else {
667  /* nothing to do */
668  return old_buddy;
669  }
670 
671  /* first adjust the buddy to accommodate the up/down */
672  SetWindowPos(infoPtr->Buddy, 0, budRect.left, budRect.top,
673  budRect.right - budRect.left, budRect.bottom - budRect.top,
675 
676  /* now position the up/down */
677  /* Since the UDS_ALIGN* flags were used, */
678  /* we will pick the position and size of the window. */
680 
681  /*
682  * If the updown has a buddy border, it has to overlap with the buddy
683  * to look as if it is integrated with the buddy control.
684  * We nudge the control or change its size to overlap.
685  */
686  if (UPDOWN_HasBuddyBorder(infoPtr)) {
687  if(infoPtr->dwStyle & UDS_ALIGNLEFT)
689  else
691  }
692 
693  SetWindowPos(infoPtr->Self, 0, x,
694  budRect.top - DEFAULT_ADDTOP, width,
695  budRect.bottom - budRect.top + DEFAULT_ADDTOP + DEFAULT_ADDBOT,
697  } else if (!(infoPtr->dwStyle & UDS_HORZ) && old_buddy != NULL) {
698  RECT rect;
699  GetWindowRect(infoPtr->Self, &rect);
700  MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Self), (POINT *)&rect, 2);
701  SetWindowPos(infoPtr->Self, 0, rect.left, rect.top, DEFAULT_WIDTH, rect.bottom - rect.top,
703  }
704 
705  return old_buddy;
706 }
707 
708 /***********************************************************************
709  * UPDOWN_DoAction
710  *
711  * This function increments/decrements the CurVal by the
712  * 'delta' amount according to the 'action' flag which can be a
713  * combination of FLAG_INCR and FLAG_DECR
714  * It notifies the parent as required.
715  * It handles wrapping and non-wrapping correctly.
716  * It is assumed that delta>0
717  */
718 static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, int action)
719 {
720  NM_UPDOWN ni;
721 
722  TRACE("%d by %d\n", action, delta);
723 
724  /* check if we can do the modification first */
725  delta *= (action & FLAG_INCR ? 1 : -1) * (infoPtr->MaxVal < infoPtr->MinVal ? -1 : 1);
726  if ( (action & FLAG_INCR) && (action & FLAG_DECR) ) delta = 0;
727 
728  TRACE("current %d, delta: %d\n", infoPtr->CurVal, delta);
729 
730  /* We must notify parent now to obtain permission */
731  ni.iPos = infoPtr->CurVal;
732  ni.iDelta = delta;
733  ni.hdr.hwndFrom = infoPtr->Self;
734  ni.hdr.idFrom = GetWindowLongPtrW (infoPtr->Self, GWLP_ID);
735  ni.hdr.code = UDN_DELTAPOS;
736  if (!SendMessageW(infoPtr->Notify, WM_NOTIFY, ni.hdr.idFrom, (LPARAM)&ni)) {
737  /* Parent said: OK to adjust */
738 
739  /* Now adjust value with (maybe new) delta */
740  if (UPDOWN_OffsetVal (infoPtr, ni.iDelta)) {
741  TRACE("new %d, delta: %d\n", infoPtr->CurVal, ni.iDelta);
742 
743  /* Now take care about our buddy */
744  UPDOWN_SetBuddyInt (infoPtr);
745  }
746  }
747 
748  /* Also, notify it. This message is sent in any case. */
749  SendMessageW( infoPtr->Notify, (infoPtr->dwStyle & UDS_HORZ) ? WM_HSCROLL : WM_VSCROLL,
750  MAKELONG(SB_THUMBPOSITION, infoPtr->CurVal), (LPARAM)infoPtr->Self);
751 }
752 
753 /***********************************************************************
754  * UPDOWN_IsEnabled
755  *
756  * Returns TRUE if it is enabled as well as its buddy (if any)
757  * FALSE otherwise
758  */
759 static BOOL UPDOWN_IsEnabled (const UPDOWN_INFO *infoPtr)
760 {
761  if (!IsWindowEnabled(infoPtr->Self))
762  return FALSE;
763  if(infoPtr->Buddy)
764  return IsWindowEnabled(infoPtr->Buddy);
765  return TRUE;
766 }
767 
768 /***********************************************************************
769  * UPDOWN_CancelMode
770  *
771  * Deletes any timers, releases the mouse and does redraw if necessary.
772  * If the control is not in "capture" mode, it does nothing.
773  * If the control was not in cancel mode, it returns FALSE.
774  * If the control was in cancel mode, it returns TRUE.
775  */
777 {
778  if (!(infoPtr->Flags & FLAG_PRESSED)) return FALSE;
779 
780  KillTimer (infoPtr->Self, TIMER_AUTOREPEAT);
781  KillTimer (infoPtr->Self, TIMER_ACCEL);
782  KillTimer (infoPtr->Self, TIMER_AUTOPRESS);
783 
784  if (GetCapture() == infoPtr->Self)
785  ReleaseCapture();
786 
787  infoPtr->Flags &= ~FLAG_PRESSED;
788  InvalidateRect (infoPtr->Self, NULL, FALSE);
789 
790  return TRUE;
791 }
792 
793 /***********************************************************************
794  * UPDOWN_HandleMouseEvent
795  *
796  * Handle a mouse event for the updown.
797  * 'pt' is the location of the mouse event in client or
798  * windows coordinates.
799  */
801 {
802  POINT pt = { x, y };
803  RECT rect;
804  int temp, arrow;
805  TRACKMOUSEEVENT tme;
806 
807  TRACE("msg %04x point %s\n", msg, wine_dbgstr_point(&pt));
808 
809  switch(msg)
810  {
811  case WM_LBUTTONDOWN: /* Initialise mouse tracking */
812 
813  /* If the buddy is an edit, will set focus to it */
814  if (UPDOWN_IsBuddyEdit(infoPtr)) SetFocus(infoPtr->Buddy);
815 
816  /* Now see which one is the 'active' arrow */
817  arrow = UPDOWN_GetArrowFromPoint (infoPtr, &rect, pt);
818 
819  /* Update the flags if we are in/out */
820  infoPtr->Flags &= ~(FLAG_MOUSEIN | FLAG_ARROW);
821  if (arrow)
822  infoPtr->Flags |= FLAG_MOUSEIN | arrow;
823  else
824  if (infoPtr->AccelIndex != -1) infoPtr->AccelIndex = 0;
825 
826  if (infoPtr->Flags & FLAG_ARROW) {
827 
828  /* Update the CurVal if necessary */
829  UPDOWN_GetBuddyInt (infoPtr);
830 
831  /* Set up the correct flags */
832  infoPtr->Flags |= FLAG_PRESSED;
833 
834  /* repaint the control */
835  InvalidateRect (infoPtr->Self, NULL, FALSE);
836 
837  /* process the click */
838  temp = (infoPtr->AccelCount && infoPtr->AccelVect) ? infoPtr->AccelVect[0].nInc : 1;
839  UPDOWN_DoAction (infoPtr, temp, infoPtr->Flags & FLAG_ARROW);
840 
841  /* now capture all mouse messages */
842  SetCapture (infoPtr->Self);
843 
844  /* and startup the first timer */
846  }
847  break;
848 
849  case WM_MOUSEMOVE:
850  /* save the flags to see if any got modified */
851  temp = infoPtr->Flags;
852 
853  /* Now see which one is the 'active' arrow */
854  arrow = UPDOWN_GetArrowFromPoint (infoPtr, &rect, pt);
855 
856  /* Update the flags if we are in/out */
857  infoPtr->Flags &= ~(FLAG_MOUSEIN | FLAG_ARROW);
858  if(arrow) {
859  infoPtr->Flags |= FLAG_MOUSEIN | arrow;
860  } else {
861  if(infoPtr->AccelIndex != -1) infoPtr->AccelIndex = 0;
862  }
863 
864  /* If state changed, redraw the control */
865  if(temp != infoPtr->Flags)
866  InvalidateRect (infoPtr->Self, NULL, FALSE);
867 
868  /* Set up tracking so the mousein flags can be reset when the
869  * mouse leaves the control */
870  tme.cbSize = sizeof( tme );
871  tme.dwFlags = TME_LEAVE;
872  tme.hwndTrack = infoPtr->Self;
873  TrackMouseEvent (&tme);
874 
875  break;
876  case WM_MOUSELEAVE:
877  infoPtr->Flags &= ~(FLAG_MOUSEIN | FLAG_ARROW);
878  InvalidateRect (infoPtr->Self, NULL, FALSE);
879  break;
880 
881  default:
882  ERR("Impossible case (msg=%x)!\n", msg);
883  }
884 
885 }
886 
887 /***********************************************************************
888  * UpDownWndProc
889  */
891 {
892  UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr (hwnd);
893  static const WCHAR themeClass[] = {'S','p','i','n',0};
894  HTHEME theme;
895 
896  TRACE("hwnd=%p msg=%04x wparam=%08lx lparam=%08lx\n", hwnd, message, wParam, lParam);
897 
898  if (!infoPtr && (message != WM_CREATE))
900 
901  switch(message)
902  {
903  case WM_CREATE:
904  {
906 
907  infoPtr = heap_alloc_zero(sizeof(*infoPtr));
908  SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
909 
910  /* initialize the info struct */
911  infoPtr->Self = hwnd;
912  infoPtr->Notify = pcs->hwndParent;
913  infoPtr->dwStyle = pcs->style;
914  infoPtr->AccelCount = 0;
915  infoPtr->AccelVect = 0;
916  infoPtr->AccelIndex = -1;
917  infoPtr->CurVal = 0;
918  infoPtr->MinVal = 100;
919  infoPtr->MaxVal = 0;
920  infoPtr->Base = 10; /* Default to base 10 */
921  infoPtr->Buddy = 0; /* No buddy window yet */
922  infoPtr->Flags = (infoPtr->dwStyle & UDS_SETBUDDYINT) ? FLAG_BUDDYINT : 0;
923 
924  SetWindowLongW (hwnd, GWL_STYLE, infoPtr->dwStyle & ~WS_BORDER);
925  if (!(infoPtr->dwStyle & UDS_HORZ))
926  SetWindowPos (hwnd, NULL, 0, 0, DEFAULT_WIDTH, pcs->cy,
928 
929  /* Do we pick the buddy win ourselves? */
930  if (infoPtr->dwStyle & UDS_AUTOBUDDY)
932 
934 
935  TRACE("UpDown Ctrl creation, hwnd=%p\n", hwnd);
936  }
937  break;
938 
939  case WM_DESTROY:
940  heap_free (infoPtr->AccelVect);
941  UPDOWN_ResetSubclass (infoPtr);
942  heap_free (infoPtr);
943  SetWindowLongPtrW (hwnd, 0, 0);
944  theme = GetWindowTheme (hwnd);
945  CloseThemeData (theme);
946  TRACE("UpDown Ctrl destruction, hwnd=%p\n", hwnd);
947  break;
948 
949  case WM_ENABLE:
950  if (wParam) {
951  infoPtr->dwStyle &= ~WS_DISABLED;
952  } else {
953  infoPtr->dwStyle |= WS_DISABLED;
954  UPDOWN_CancelMode (infoPtr);
955  }
956  InvalidateRect (infoPtr->Self, NULL, FALSE);
957  break;
958 
959  case WM_STYLECHANGED:
960  if (wParam == GWL_STYLE) {
961  infoPtr->dwStyle = ((LPSTYLESTRUCT)lParam)->styleNew;
962  InvalidateRect (infoPtr->Self, NULL, FALSE);
963  }
964  break;
965 
966  case WM_THEMECHANGED:
967  theme = GetWindowTheme (hwnd);
968  CloseThemeData (theme);
971  break;
972 
973  case WM_TIMER:
974  /* is this the auto-press timer? */
975  if(wParam == TIMER_AUTOPRESS) {
977  infoPtr->Flags &= ~(FLAG_PRESSED | FLAG_ARROW);
978  InvalidateRect(infoPtr->Self, NULL, FALSE);
979  }
980 
981  /* if initial timer, kill it and start the repeat timer */
982  if(wParam == TIMER_AUTOREPEAT) {
983  INT delay;
984 
986  /* if no accel info given, used default timer */
987  if(infoPtr->AccelCount==0 || infoPtr->AccelVect==0) {
988  infoPtr->AccelIndex = -1;
990  } else {
991  infoPtr->AccelIndex = 0; /* otherwise, use it */
992  delay = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1;
993  }
995  }
996 
997  /* now, if the mouse is above us, do the thing...*/
998  if(infoPtr->Flags & FLAG_MOUSEIN) {
999  int temp;
1000 
1001  temp = infoPtr->AccelIndex == -1 ? 1 : infoPtr->AccelVect[infoPtr->AccelIndex].nInc;
1002  UPDOWN_DoAction(infoPtr, temp, infoPtr->Flags & FLAG_ARROW);
1003 
1004  if(infoPtr->AccelIndex != -1 && infoPtr->AccelIndex < infoPtr->AccelCount-1) {
1006  infoPtr->AccelIndex++; /* move to the next accel info */
1007  temp = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1;
1008  /* make sure we have at least 1ms intervals */
1009  SetTimer(hwnd, TIMER_ACCEL, temp, 0);
1010  }
1011  }
1012  break;
1013 
1014  case WM_CANCELMODE:
1015  return UPDOWN_CancelMode (infoPtr);
1016 
1017  case WM_LBUTTONUP:
1018  if (GetCapture() != infoPtr->Self) break;
1019 
1020  if ( (infoPtr->Flags & FLAG_MOUSEIN) &&
1021  (infoPtr->Flags & FLAG_ARROW) ) {
1022 
1023  SendMessageW( infoPtr->Notify,
1024  (infoPtr->dwStyle & UDS_HORZ) ? WM_HSCROLL : WM_VSCROLL,
1025  MAKELONG(SB_ENDSCROLL, infoPtr->CurVal),
1026  (LPARAM)hwnd);
1027  if (UPDOWN_IsBuddyEdit(infoPtr))
1028  SendMessageW(infoPtr->Buddy, EM_SETSEL, 0, MAKELONG(0, -1));
1029  }
1030  UPDOWN_CancelMode(infoPtr);
1031  break;
1032 
1033  case WM_LBUTTONDOWN:
1034  case WM_MOUSEMOVE:
1035  case WM_MOUSELEAVE:
1036  if(UPDOWN_IsEnabled(infoPtr))
1038  break;
1039 
1040  case WM_MOUSEWHEEL:
1041  UPDOWN_MouseWheel(infoPtr, wParam);
1042  break;
1043 
1044  case WM_KEYDOWN:
1045  if((infoPtr->dwStyle & UDS_ARROWKEYS) && UPDOWN_IsEnabled(infoPtr))
1046  return UPDOWN_KeyPressed(infoPtr, (int)wParam);
1047  break;
1048 
1049  case WM_PRINTCLIENT:
1050  case WM_PAINT:
1051  return UPDOWN_Paint (infoPtr, (HDC)wParam);
1052 
1053  case UDM_GETACCEL:
1054  if (wParam==0 && lParam==0) return infoPtr->AccelCount;
1055  if (wParam && lParam) {
1056  int temp = min(infoPtr->AccelCount, wParam);
1057  memcpy((void *)lParam, infoPtr->AccelVect, temp*sizeof(UDACCEL));
1058  return temp;
1059  }
1060  return 0;
1061 
1062  case UDM_SETACCEL:
1063  {
1064  TRACE("UDM_SETACCEL\n");
1065 
1066  if(infoPtr->AccelVect) {
1067  heap_free (infoPtr->AccelVect);
1068  infoPtr->AccelCount = 0;
1069  infoPtr->AccelVect = 0;
1070  }
1071  if(wParam==0) return TRUE;
1072  infoPtr->AccelVect = heap_alloc(wParam*sizeof(UDACCEL));
1073  if(!infoPtr->AccelVect) return FALSE;
1074  memcpy(infoPtr->AccelVect, (void*)lParam, wParam*sizeof(UDACCEL));
1075  infoPtr->AccelCount = wParam;
1076 
1077  if (TRACE_ON(updown))
1078  {
1079  UINT i;
1080 
1081  for (i = 0; i < wParam; i++)
1082  TRACE("%u: nSec %u nInc %u\n", i,
1083  infoPtr->AccelVect[i].nSec, infoPtr->AccelVect[i].nInc);
1084  }
1085 
1086  return TRUE;
1087  }
1088  case UDM_GETBASE:
1089  return infoPtr->Base;
1090 
1091  case UDM_SETBASE:
1092  TRACE("UpDown Ctrl new base(%ld), hwnd=%p\n", wParam, hwnd);
1093  if (wParam==10 || wParam==16) {
1094  WPARAM old_base = infoPtr->Base;
1095  infoPtr->Base = wParam;
1096 
1097  if (old_base != infoPtr->Base)
1098  UPDOWN_SetBuddyInt(infoPtr);
1099 
1100  return old_base;
1101  }
1102  break;
1103 
1104  case UDM_GETBUDDY:
1105  return (LRESULT)infoPtr->Buddy;
1106 
1107  case UDM_SETBUDDY:
1108  return (LRESULT)UPDOWN_SetBuddy (infoPtr, (HWND)wParam);
1109 
1110  case UDM_GETPOS:
1111  {
1112  BOOL err;
1113  int pos;
1114 
1115  pos = UPDOWN_GetPos(infoPtr, &err);
1116  return MAKELONG(pos, err);
1117  }
1118  case UDM_SETPOS:
1119  {
1120  return UPDOWN_SetPos(infoPtr, (short)LOWORD(lParam));
1121  }
1122  case UDM_GETRANGE:
1123  return MAKELONG(infoPtr->MaxVal, infoPtr->MinVal);
1124 
1125  case UDM_SETRANGE:
1126  /* we must have:
1127  UD_MINVAL <= Max <= UD_MAXVAL
1128  UD_MINVAL <= Min <= UD_MAXVAL
1129  |Max-Min| <= UD_MAXVAL */
1130  UPDOWN_SetRange(infoPtr, (short)lParam, (short)HIWORD(lParam));
1131  break;
1132 
1133  case UDM_GETRANGE32:
1134  if (wParam) *(LPINT)wParam = infoPtr->MinVal;
1135  if (lParam) *(LPINT)lParam = infoPtr->MaxVal;
1136  break;
1137 
1138  case UDM_SETRANGE32:
1139  UPDOWN_SetRange(infoPtr, (INT)lParam, (INT)wParam);
1140  break;
1141 
1142  case UDM_GETPOS32:
1143  {
1144  return UPDOWN_GetPos(infoPtr, (BOOL*)lParam);
1145  }
1146  case UDM_SETPOS32:
1147  {
1148  return UPDOWN_SetPos(infoPtr, (int)lParam);
1149  }
1150  case UDM_GETUNICODEFORMAT:
1151  /* we lie a bit here, we're always using Unicode internally */
1152  return infoPtr->UnicodeFormat;
1153 
1154  case UDM_SETUNICODEFORMAT:
1155  {
1156  /* do we really need to honour this flag? */
1157  int temp = infoPtr->UnicodeFormat;
1158  infoPtr->UnicodeFormat = (BOOL)wParam;
1159  return temp;
1160  }
1161  default:
1163  ERR("unknown msg %04x wp=%04lx lp=%08lx\n", message, wParam, lParam);
1164  return DefWindowProcW (hwnd, message, wParam, lParam);
1165  }
1166 
1167  return 0;
1168 }
1169 
1170 /***********************************************************************
1171  * UPDOWN_Register [Internal]
1172  *
1173  * Registers the updown window class.
1174  */
1176 {
1177  WNDCLASSW wndClass;
1178 
1179  ZeroMemory( &wndClass, sizeof( WNDCLASSW ) );
1180  wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
1181  wndClass.lpfnWndProc = UpDownWindowProc;
1182  wndClass.cbClsExtra = 0;
1183  wndClass.cbWndExtra = sizeof(UPDOWN_INFO*);
1184  wndClass.hCursor = LoadCursorW( 0, (LPWSTR)IDC_ARROW );
1185  wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1186  wndClass.lpszClassName = UPDOWN_CLASSW;
1187 
1188  RegisterClassW( &wndClass );
1189 }
1190 
1191 
1192 /***********************************************************************
1193  * UPDOWN_Unregister [Internal]
1194  *
1195  * Unregisters the updown window class.
1196  */
1198 {
1200 }
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define LB_SETCURSEL
Definition: winuser.h:2045
#define WS_DISABLED
Definition: pedump.c:621
static LRESULT UPDOWN_Paint(const UPDOWN_INFO *infoPtr, HDC hdc)
Definition: updown.c:448
#define abs(i)
Definition: fconv.c:206
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
GLint GLint GLsizei width
Definition: gl.h:1546
#define DEFAULT_BUDDYSPACER
Definition: updown.c:70
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
Definition: tftpd.h:59
static int UPDOWN_GetPos(UPDOWN_INFO *infoPtr, BOOL *err)
Definition: updown.c:481
#define TRUE
Definition: types.h:120
#define WC_EDITW
Definition: commctrl.h:4683
#define UDM_GETPOS
Definition: commctrl.h:2140
void UPDOWN_Unregister(void)
Definition: updown.c:1197
#define UDS_ALIGNLEFT
Definition: commctrl.h:2130
#define UDM_GETPOS32
Definition: commctrl.h:2152
#define MK_SHIFT
Definition: winuser.h:2344
#define TIMER_AUTOREPEAT
Definition: updown.c:87
#define DEFAULT_BUDDYBORDER
Definition: updown.c:69
static LRESULT UPDOWN_Draw(const UPDOWN_INFO *infoPtr, HDC hdc)
Definition: updown.c:381
UINT style
Definition: winuser.h:3150
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
#define WM_LBUTTONDOWN
Definition: winuser.h:1758
INT CurVal
Definition: updown.c:50
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
BOOL WINAPI IsWindow(_In_opt_ HWND)
static BOOL UPDOWN_OffsetVal(UPDOWN_INFO *infoPtr, int delta)
Definition: updown.c:134
#define pt(x, y)
Definition: drawing.c:79
#define DEFAULT_BUDDYSPACER_THEMED
Definition: updown.c:72
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static BOOL UPDOWN_InBounds(const UPDOWN_INFO *infoPtr, int val)
Definition: updown.c:120
#define WM_MOUSEWHEEL
Definition: treelist.c:96
static struct netconfig_info ni
Definition: getnetconfig.c:158
#define LOCALE_USER_DEFAULT
#define DEFAULT_WIDTH
Definition: updown.c:65
INT MaxVal
Definition: updown.c:52
#define strtolW(s, e, b)
Definition: unicode.h:33
static HDC
Definition: imagelist.c:92
#define DFCS_INACTIVE
Definition: winuser.h:502
#define CALLBACK
Definition: compat.h:27
const char * fmt
Definition: wsprintf.c:30
#define BF_BOTTOM
Definition: winuser.h:457
LONG top
Definition: windef.h:292
static INT UPDOWN_GetArrowFromPoint(const UPDOWN_INFO *infoPtr, RECT *rect, POINT pt)
Definition: updown.c:227
static HTHEME(WINAPI *pOpenThemeDataEx)(HWND
#define UDM_SETACCEL
Definition: commctrl.h:2143
#define ZeroMemory
Definition: winbase.h:1642
#define CS_HREDRAW
Definition: winuser.h:648
#define DEFAULT_XSEP
Definition: updown.c:66
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
int cbClsExtra
Definition: winuser.h:3152
HWND WINAPI SetFocus(_In_opt_ HWND)
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
BOOL WINAPI DrawFrameControl(_In_ HDC, _Inout_ LPRECT, _In_ UINT, _In_ UINT)
UINT_PTR WPARAM
Definition: windef.h:207
#define VK_DOWN
Definition: winuser.h:2202
INT AccelIndex
Definition: updown.c:48
#define GetWindowLongPtrW
Definition: winuser.h:4730
LONG left
Definition: windef.h:291
#define SWP_NOZORDER
Definition: winuser.h:1232
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define UDM_GETRANGE32
Definition: commctrl.h:2148
LONG right
Definition: windef.h:293
HRESULT WINAPI DrawThemeBackground(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect)
Definition: draw.c:128
static const WCHAR themeClass[]
Definition: header.c:115
int32_t INT
Definition: typedefs.h:56
DWORD dwStyle
Definition: updown.c:45
& rect
Definition: startmenu.cpp:1413
WPARAM wParam
Definition: combotst.c:138
#define UDS_WRAP
Definition: commctrl.h:2127
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
#define WM_ENABLE
Definition: winuser.h:1597
#define TIMER_AUTOPRESS
Definition: updown.c:89
#define WM_PRINTCLIENT
Definition: richedit.h:70
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define UPDOWN_GetInfoPtr(hwnd)
Definition: updown.c:91
BOOL WINAPI TrackMouseEvent(_Inout_ LPTRACKMOUSEEVENT)
#define BUDDY_TYPE_UNKNOWN
Definition: updown.c:83
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
static BOOL UPDOWN_IsEnabled(const UPDOWN_INFO *infoPtr)
Definition: updown.c:759
int WINAPI GetClassNameW(_In_ HWND hWnd, _Out_writes_to_(nMaxCount, return) LPWSTR lpClassName, _In_ int nMaxCount)
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: lang.c:1098
BOOL WINAPI IsThemeBackgroundPartiallyTransparent(HTHEME hTheme, int iPartId, int iStateId)
Definition: draw.c:1883
#define BUDDY_TYPE_LISTBOX
Definition: updown.c:84
#define WHEEL_DELTA
Definition: treelist.c:99
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
static int UPDOWN_SetPos(UPDOWN_INFO *infoPtr, int pos)
Definition: updown.c:500
#define DFCS_PUSHED
Definition: winuser.h:503
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define LOCALE_STHOUSAND
Definition: winnls.h:43
#define BUDDY_TYPE_EDIT
Definition: updown.c:85
#define UDM_GETBASE
Definition: commctrl.h:2146
#define VK_UP
Definition: winuser.h:2200
#define LB_ERR
Definition: winuser.h:2407
unsigned int BOOL
Definition: ntddk_ex.h:94
#define FLAG_PRESSED
Definition: updown.c:79
#define UDS_NOTHOUSANDS
Definition: commctrl.h:2134
static BOOL UPDOWN_IsBuddyEdit(const UPDOWN_INFO *infoPtr)
Definition: updown.c:102
LONG WINAPI SetWindowLongW(_In_ HWND, _In_ int, _In_ LONG)
short SHORT
Definition: pedump.c:59
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
BOOL WINAPI DrawEdge(_In_ HDC, _Inout_ LPRECT, _In_ UINT, _In_ UINT)
#define Max(a, b)
Definition: cdprocs.h:70
WNDPROC lpfnWndProc
Definition: winuser.h:3151
HWND WINAPI GetCapture(void)
Definition: message.c:2879
#define WM_MOUSELEAVE
Definition: commctrl.h:4971
void UPDOWN_Register(void)
Definition: updown.c:1175
#define MAKELONG(a, b)
Definition: typedefs.h:248
#define UDS_ARROWKEYS
Definition: commctrl.h:2132
HWND Self
Definition: updown.c:43
smooth NULL
Definition: ftsmooth.c:416
#define SB_THUMBPOSITION
Definition: winuser.h:572
#define WM_KEYDOWN
Definition: winuser.h:1697
LPCWSTR lpszClassName
Definition: winuser.h:3159
LONG_PTR LPARAM
Definition: windef.h:208
BOOL WINAPI IsWindowEnabled(_In_ HWND)
#define UDM_SETRANGE
Definition: commctrl.h:2137
static void UPDOWN_ResetSubclass(UPDOWN_INFO *infoPtr)
Definition: updown.c:608
LRESULT WINAPI DefSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: commctrl.c:1496
#define UDM_SETRANGE32
Definition: commctrl.h:2147
#define SB_ENDSCROLL
Definition: winuser.h:574
WINE_DEFAULT_DEBUG_CHANNEL(updown)
UINT AccelCount
Definition: updown.c:46
#define DFCS_SCROLLDOWN
Definition: winuser.h:490
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
#define WM_DESTROY
Definition: winuser.h:1591
#define REPEAT_DELAY
Definition: updown.c:63
GLuint GLfloat * val
Definition: glext.h:7180
BOOL WINAPI SetWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uIDSubclass, DWORD_PTR dwRef)
Definition: commctrl.c:1261
#define CS_VREDRAW
Definition: winuser.h:653
struct tagSTYLESTRUCT * LPSTYLESTRUCT
const char * wine_dbgstr_point(const POINT *guid)
#define TRACE(s)
Definition: solgame.cpp:4
#define FLAG_MOUSEIN
Definition: updown.c:78
int cbWndExtra
Definition: winuser.h:3153
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define BF_RIGHT
Definition: winuser.h:456
#define SWP_NOACTIVATE
Definition: winuser.h:1227
UINT nSec
Definition: commctrl.h:2120
#define WM_TIMER
Definition: winuser.h:1724
GLint GLint GLsizei GLsizei GLsizei GLint border
Definition: gl.h:1546
#define CS_GLOBALCLASS
Definition: winuser.h:647
#define WM_NCDESTROY
Definition: winuser.h:1666
#define WINAPI
Definition: msvc.h:8
#define UDM_SETPOS32
Definition: commctrl.h:2151
#define EM_SETSEL
Definition: winuser.h:2000
static BOOL UPDOWN_SetBuddyInt(const UPDOWN_INFO *infoPtr)
Definition: updown.c:305
BOOL WINAPI InvalidateRect(_In_opt_ HWND, _In_opt_ LPCRECT, _In_ BOOL)
#define WC_LISTBOXW
Definition: commctrl.h:4707
unsigned long DWORD
Definition: ntddk_ex.h:95
#define DFCS_SCROLLRIGHT
Definition: winuser.h:492
static void UPDOWN_GetArrowRect(const UPDOWN_INFO *infoPtr, RECT *rect, int arrow)
Definition: updown.c:175
#define FLAG_DECR
Definition: updown.c:77
#define DFCS_SCROLLUP
Definition: winuser.h:489
static BOOL UPDOWN_DrawBuddyBackground(const UPDOWN_INFO *infoPtr, HDC hdc)
Definition: updown.c:357
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2074
#define Min(a, b)
Definition: cdprocs.h:66
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
HTHEME WINAPI OpenThemeData(HWND hwnd, LPCWSTR classlist)
Definition: system.c:835
#define WM_PAINT
Definition: winuser.h:1602
#define BUDDY_SUBCLASSID
Definition: updown.c:94
HTHEME WINAPI GetWindowTheme(HWND hwnd)
Definition: system.c:851
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
int ret
HWND WINAPI GetWindow(_In_ HWND, _In_ UINT)
#define UDN_DELTAPOS
Definition: commctrl.h:2165
void delay(unsigned msec)
Definition: i386rtl.c:32
HDC hdc
Definition: main.c:9
#define COLOR_BTNFACE
Definition: winuser.h:918
BOOL UnicodeFormat
Definition: updown.c:56
static LRESULT UPDOWN_MouseWheel(UPDOWN_INFO *infoPtr, WPARAM wParam)
Definition: updown.c:552
#define WM_CANCELMODE
Definition: winuser.h:1617
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define SWP_FRAMECHANGED
Definition: winuser.h:1225
UINT nInc
Definition: commctrl.h:2121
static LRESULT UPDOWN_SetRange(UPDOWN_INFO *infoPtr, INT Max, INT Min)
Definition: updown.c:536
#define UDS_HORZ
Definition: commctrl.h:2133
#define DEFAULT_ADDBOT
Definition: updown.c:68
#define WM_APP
Definition: eventvwr.h:70
GLenum src
Definition: glext.h:6340
#define err(...)
#define NM_UPDOWN
Definition: commctrl.h:2156
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define WM_USER
Definition: winuser.h:1877
HCURSOR hCursor
Definition: winuser.h:3156
#define ERR(fmt,...)
Definition: debug.h:109
#define GWL_STYLE
Definition: winuser.h:846
#define UDS_AUTOBUDDY
Definition: commctrl.h:2131
#define FLAG_ARROW
Definition: updown.c:81
#define UDM_SETBUDDY
Definition: commctrl.h:2141
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
HWND WINAPI GetParent(_In_ HWND)
HWND WINAPI SetCapture(_In_ HWND hWnd)
#define UDM_GETACCEL
Definition: commctrl.h:2144
#define WS_BORDER
Definition: pedump.c:625
#define INITIAL_DELAY
Definition: updown.c:61
static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition: updown.c:890
const WCHAR * action
Definition: action.c:7783
static BOOL(WINAPI *pSetWindowSubclass)(HWND
BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
Definition: commctrl.c:1390
int WINAPI GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount)
Definition: window.c:1408
static calc_node_t temp
Definition: rpn_ieee.c:38
GLuint start
Definition: gl.h:1545
#define ARRAY_SIZE(a)
Definition: main.h:24
#define UDS_ALIGNRIGHT
Definition: commctrl.h:2129
HBRUSH hbrBackground
Definition: winuser.h:3157
#define BF_TOP
Definition: winuser.h:455
#define TME_LEAVE
Definition: commctrl.h:4977
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_LBUTTONUP
Definition: winuser.h:1759
#define LB_GETCARETINDEX
Definition: winuser.h:2019
GLenum GLenum dst
Definition: glext.h:6340
static BOOL UPDOWN_HasBuddyBorder(const UPDOWN_INFO *infoPtr)
Definition: updown.c:161
static WCHAR UPDOWN_GetThousandSep(void)
Definition: updown.c:243
#define DEFAULT_BUDDYBORDER_THEMED
Definition: updown.c:71
#define UDM_SETPOS
Definition: commctrl.h:2139
#define HWND_DESKTOP
Definition: winuser.h:1195
#define min(a, b)
Definition: monoChain.cc:55
#define UDM_GETRANGE
Definition: commctrl.h:2138
unsigned int UINT
Definition: ndis.h:50
#define WM_MOUSEMOVE
Definition: winuser.h:1757
#define WM_HSCROLL
Definition: winuser.h:1725
#define UDM_GETBUDDY
Definition: commctrl.h:2142
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
#define MK_CONTROL
Definition: winuser.h:2345
#define DFC_SCROLL
Definition: winuser.h:475
INT MinVal
Definition: updown.c:51
HWND Buddy
Definition: updown.c:53
INT Base
Definition: updown.c:49
static HWND UPDOWN_SetBuddy(UPDOWN_INFO *infoPtr, HWND bud)
Definition: updown.c:623
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
#define msg(x)
Definition: auth_time.c:54
#define IDC_ARROW
Definition: winuser.h:682
static BOOL UPDOWN_CancelMode(UPDOWN_INFO *infoPtr)
Definition: updown.c:776
BOOL WINAPI ReleaseCapture(void)
Definition: message.c:2888
INT BuddyType
Definition: updown.c:54
#define WM_CREATE
Definition: winuser.h:1590
static LRESULT CALLBACK UPDOWN_Buddy_SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uId, DWORD_PTR ref_data)
Definition: updown.c:574
UDACCEL * AccelVect
Definition: updown.c:47
static BOOL UPDOWN_IsBuddyListbox(const UPDOWN_INFO *infoPtr)
Definition: updown.c:111
#define UDS_SETBUDDYINT
Definition: commctrl.h:2128
#define HIWORD(l)
Definition: typedefs.h:246
LONG bottom
Definition: windef.h:294
#define FLAG_BUDDYINT
Definition: updown.c:80
BOOL COMCTL32_IsReflectedMessage(UINT uMsg) DECLSPEC_HIDDEN
Definition: commctrl.c:1748
#define SWP_NOMOVE
Definition: winuser.h:1229
#define FLAG_INCR
Definition: updown.c:76
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
#define EDGE_SUNKEN
Definition: winuser.h:451
BOOL WINAPI SetWindowPos(_In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
static BOOL UPDOWN_GetBuddyInt(UPDOWN_INFO *infoPtr)
Definition: updown.c:261
HWND Notify
Definition: updown.c:44
#define SetWindowLongPtrW
Definition: winuser.h:5247
#define UDS_HOTTRACK
Definition: commctrl.h:2135
#define AUTOPRESS_DELAY
Definition: updown.c:62
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define DFCS_SCROLLLEFT
Definition: winuser.h:491
LONG_PTR LRESULT
Definition: windef.h:209
#define UPDOWN_CLASSW
Definition: commctrl.h:2115
static INT
Definition: updown.c:65
#define TRACE_ON(x)
Definition: compat.h:65
#define DEFAULT_ADDTOP
Definition: updown.c:67
#define UDM_GETUNICODEFORMAT
Definition: commctrl.h:2150
LPARAM lParam
Definition: combotst.c:139
#define LOWORD(l)
Definition: pedump.c:82
#define GW_HWNDPREV
Definition: winuser.h:757
Definition: dsound.c:943
#define UDM_SETBASE
Definition: commctrl.h:2145
#define GWLP_ID
Definition: winuser.h:854
HRESULT WINAPI CloseThemeData(HTHEME hTheme)
Definition: system.c:950
#define WM_NOTIFY
Definition: richedit.h:61
#define WM_VSCROLL
Definition: winuser.h:1726
#define BF_LEFT
Definition: winuser.h:454
#define TIMER_ACCEL
Definition: updown.c:88
Definition: path.c:42
static LRESULT UPDOWN_KeyPressed(UPDOWN_INFO *infoPtr, int key)
Definition: updown.c:463
static void UPDOWN_DoAction(UPDOWN_INFO *infoPtr, int delta, int action)
Definition: updown.c:718
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
static void UPDOWN_HandleMouseEvent(UPDOWN_INFO *infoPtr, UINT msg, INT x, INT y)
Definition: updown.c:800
INT Flags
Definition: updown.c:55
#define SWP_NOOWNERZORDER
Definition: winuser.h:1234
int * LPINT
Definition: windef.h:178
#define UDM_SETUNICODEFORMAT
Definition: commctrl.h:2149