ReactOS  0.4.14-dev-49-gfb4591c
updown.c
Go to the documentation of this file.
1 /* Unit tests for the up-down control
2  *
3  * Copyright 2005 C. Scott Ananian
4  * Copyright (C) 2007 James Hawkins
5  * Copyright (C) 2007 Leslie Choong
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 /* TO TEST:
23  * - send click messages to the up-down control, check the current position
24  * - up-down control automatically positions itself next to its buddy window
25  * - up-down control sets the caption of the buddy window
26  * - test CreateUpDownControl API
27  * - check UDS_AUTOBUDDY style, up-down control selects previous window in z-order
28  * - check UDM_SETBUDDY message
29  * - check UDM_GETBUDDY message
30  * - up-down control and buddy control must have the same parent
31  * - up-down control notifies its parent window when its position changes with UDN_DELTAPOS + WM_VSCROLL or WM_HSCROLL
32  * - check UDS_ALIGN[LEFT,RIGHT]...check that width of buddy window is decreased
33  * - check that UDS_SETBUDDYINT sets the caption of the buddy window when it is changed
34  * - check that the thousands operator is set for large numbers
35  * - check that the thousands operator is not set with UDS_NOTHOUSANDS
36  * - check UDS_ARROWKEYS, control subclasses the buddy window so that it processes the keys when it has focus
37  * - check UDS_HORZ
38  * - check changing past min/max values
39  * - check UDS_WRAP wraps values past min/max, incrementing past upper value wraps position to lower value
40  * - can change control's position, min/max pos, radix
41  * - check UDM_GETPOS, for up-down control with a buddy window, position is the caption of the buddy window, so change the
42  * caption of the buddy window then call UDM_GETPOS
43  * - check UDM_SETRANGE, max can be less than min, so clicking the up arrow decreases the current position
44  * - more stuff to test
45  */
46 
47 #include <windows.h>
48 #include <commctrl.h>
49 #include <stdio.h>
50 
51 #include "wine/test.h"
52 #include "msg.h"
53 
54 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
55 
56 #define NUM_MSG_SEQUENCES 3
57 #define PARENT_SEQ_INDEX 0
58 #define EDIT_SEQ_INDEX 1
59 #define UPDOWN_SEQ_INDEX 2
60 
61 #define UPDOWN_ID 0
62 #define BUDDY_ID 1
63 
65 
66 static HWND (WINAPI *pCreateUpDownControl)(DWORD, INT, INT, INT, INT,
67  HWND, INT, HINSTANCE, HWND, INT, INT, INT);
68 static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
69 
71 
72 static const struct message add_updown_with_edit_seq[] = {
76  { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED /*, MAKELONG(91, 75) exact size depends on font */ },
77  { 0 }
78 };
79 
80 static const struct message add_updown_to_parent_seq[] = {
81  { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
82  { WM_QUERYUISTATE, sent|optional },
84  { 0 }
85 };
86 
87 static const struct message get_edit_text_seq[] = {
88  { WM_GETTEXT, sent },
89  { 0 }
90 };
91 
92 static const struct message test_updown_pos_seq[] = {
93  { UDM_SETRANGE, sent|lparam, 0, MAKELONG(100,0) },
94  { UDM_GETRANGE, sent},
95  { UDM_SETPOS, sent|lparam, 0, 5},
96  { UDM_GETPOS, sent},
97  { UDM_SETPOS, sent|lparam, 0, 0},
98  { UDM_GETPOS, sent},
99  { UDM_SETPOS, sent|lparam, 0, MAKELONG(-1,0)},
100  { UDM_GETPOS, sent},
101  { UDM_SETPOS, sent|lparam, 0, 100},
102  { UDM_GETPOS, sent},
103  { UDM_SETPOS, sent|lparam, 0, 101},
104  { UDM_GETPOS, sent},
105  { 0 }
106 };
107 
108 static const struct message test_updown_pos32_seq[] = {
109  { UDM_SETRANGE32, sent|lparam, 0, 1000 },
110  { UDM_GETRANGE32, sent}, /* Cannot check wparam and lparam as they are ptrs */
111  { UDM_SETPOS32, sent|lparam, 0, 500 },
112  { UDM_GETPOS32, sent},
113  { UDM_SETPOS32, sent|lparam, 0, 0 },
114  { UDM_GETPOS32, sent},
115  { UDM_SETPOS32, sent|lparam, 0, -1 },
116  { UDM_GETPOS32, sent},
117  { UDM_SETPOS32, sent|lparam, 0, 1000 },
118  { UDM_GETPOS32, sent},
119  { UDM_SETPOS32, sent|lparam, 0, 1001 },
120  { UDM_GETPOS32, sent},
121  { 0 }
122 };
123 
124 static const struct message test_updown_buddy_seq[] = {
125  { UDM_GETBUDDY, sent },
126  { UDM_SETBUDDY, sent },
127  { WM_STYLECHANGING, sent|defwinproc },
128  { WM_STYLECHANGED, sent|defwinproc },
129  { WM_STYLECHANGING, sent|defwinproc },
130  { WM_STYLECHANGED, sent|defwinproc },
134  { WM_MOVE, sent|defwinproc },
135  { UDM_GETBUDDY, sent },
136  { 0 }
137 };
138 
139 static const struct message test_updown_base_seq[] = {
140  { UDM_SETBASE, sent|wparam, 10 },
141  { UDM_GETBASE, sent },
142  { UDM_SETBASE, sent|wparam, 80 },
143  { UDM_GETBASE, sent },
144  { UDM_SETBASE, sent|wparam, 16 },
145  { UDM_GETBASE, sent },
146  { UDM_SETBASE, sent|wparam, 80 },
147  { UDM_GETBASE, sent },
148  { UDM_SETBASE, sent|wparam, 10 },
149  { UDM_GETBASE, sent },
150  { 0 }
151 };
152 
153 static const struct message test_updown_unicode_seq[] = {
160  { 0 }
161 };
162 
163 static const struct message test_updown_pos_nochange_seq[] = {
164  { WM_GETTEXT, sent|id, 0, 0, BUDDY_ID },
165  { 0 }
166 };
167 
169 {
170  static LONG defwndproc_counter = 0;
171  struct message msg = { 0 };
172  LRESULT ret;
173 
174  /* log system messages, except for painting */
175  if (message < WM_USER &&
176  message != WM_PAINT &&
177  message != WM_ERASEBKGND &&
178  message != WM_NCPAINT &&
179  message != WM_NCHITTEST &&
180  message != WM_GETTEXT &&
181  message != WM_GETICON &&
183  {
184  msg.message = message;
185  msg.flags = sent|wparam|lparam;
186  if (defwndproc_counter) msg.flags |= defwinproc;
187  msg.wParam = wParam;
188  msg.lParam = lParam;
190  }
191 
192  defwndproc_counter++;
194  defwndproc_counter--;
195 
196  return ret;
197 }
198 
200 {
201  WNDCLASSA cls;
202 
203  cls.style = 0;
205  cls.cbClsExtra = 0;
206  cls.cbWndExtra = 0;
208  cls.hIcon = 0;
209  cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
211  cls.lpszMenuName = NULL;
212  cls.lpszClassName = "Up-Down test parent class";
213  return RegisterClassA(&cls);
214 }
215 
217 {
219  return NULL;
220 
221  return CreateWindowExA(0, "Up-Down test parent class",
222  "Up-Down test parent window",
225  0, 0, 100, 100,
227 }
228 
230 {
232  static LONG defwndproc_counter = 0;
233  struct message msg = { 0 };
234  LRESULT ret;
235 
236  msg.message = message;
237  msg.flags = sent|wparam|lparam;
238  if (defwndproc_counter) msg.flags |= defwinproc;
239  msg.wParam = wParam;
240  msg.lParam = lParam;
241  msg.id = BUDDY_ID;
243 
244  defwndproc_counter++;
245  ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
246  defwndproc_counter--;
247  return ret;
248 }
249 
251 {
252  WNDPROC oldproc;
253  HWND hwnd;
254  RECT rect;
255 
258  0, 0, rect.right, rect.bottom,
260  if (!hwnd) return NULL;
261 
265 
266  return hwnd;
267 }
268 
270 {
272  static LONG defwndproc_counter = 0;
273  struct message msg = { 0 };
274  LRESULT ret;
275 
276  msg.message = message;
277  msg.flags = sent|wparam|lparam;
278  if (defwndproc_counter) msg.flags |= defwinproc;
279  msg.wParam = wParam;
280  msg.lParam = lParam;
281  msg.id = UPDOWN_ID;
283 
284  defwndproc_counter++;
285  ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
286  defwndproc_counter--;
287 
288  return ret;
289 }
290 
292 {
293  WNDPROC oldproc;
294  HWND updown;
295  RECT rect;
296 
299  0, 0, rect.right, rect.bottom,
301  ok(updown != NULL, "Failed to create UpDown control.\n");
302  if (!updown) return NULL;
303 
304  SendMessageA(updown, UDM_SETBUDDY, (WPARAM)buddy, 0);
305  SendMessageA(updown, UDM_SETRANGE, 0, MAKELONG(100, 0));
306  SendMessageA(updown, UDM_SETPOS, 0, MAKELONG(50, 0));
307 
308  oldproc = (WNDPROC)SetWindowLongPtrA(updown, GWLP_WNDPROC,
310  SetWindowLongPtrA(updown, GWLP_USERDATA, (LONG_PTR)oldproc);
311 
312  return updown;
313 }
314 
315 static void test_updown_pos(void)
316 {
317  HWND updown;
318  int r;
319 
321 
323 
324  /* Set Range from 0 to 100 */
325  SendMessageA(updown, UDM_SETRANGE, 0 , MAKELONG(100,0) );
326  r = SendMessageA(updown, UDM_GETRANGE, 0,0);
327  expect(100,LOWORD(r));
328  expect(0,HIWORD(r));
329 
330  /* Set the position to 5, return is not checked as it was set before func call */
331  SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(5,0) );
332  /* Since UDM_SETBUDDYINT was not set at creation HIWORD(r) will always be 1 as a return from UDM_GETPOS */
333  /* Get the position, which should be 5 */
334  r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
335  expect(5,LOWORD(r));
336  expect(1,HIWORD(r));
337 
338  /* Set the position to 0, return should be 5 */
339  r = SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(0,0) );
340  expect(5,r);
341  /* Get the position, which should be 0 */
342  r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
343  expect(0,LOWORD(r));
344  expect(1,HIWORD(r));
345 
346  /* Set the position to -1, return should be 0 */
347  r = SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(-1,0) );
348  expect(0,r);
349  /* Get the position, which should be 0 */
350  r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
351  expect(0,LOWORD(r));
352  expect(1,HIWORD(r));
353 
354  /* Set the position to 100, return should be 0 */
355  r = SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(100,0) );
356  expect(0,r);
357  /* Get the position, which should be 100 */
358  r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
359  expect(100,LOWORD(r));
360  expect(1,HIWORD(r));
361 
362  /* Set the position to 101, return should be 100 */
363  r = SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(101,0) );
364  expect(100,r);
365  /* Get the position, which should be 100 */
366  r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
367  expect(100,LOWORD(r));
368  expect(1,HIWORD(r));
369 
371 
372  DestroyWindow(updown);
373 
374  /* there's no attempt to update buddy Edit if text didn't change */
375  SetWindowTextA(g_edit, "50");
377 
378  /* test sequence only on 5.8x versions */
379  r = SendMessageA(updown, UDM_GETPOS32, 0, 0);
380  if (r)
381  {
382  UDACCEL accel;
383 
385 
386  r = SendMessageA(updown, UDM_SETPOS, 0, 50);
387  expect(50,r);
388 
390  "test updown pos, no change", FALSE);
391 
392  SendMessageA(updown, UDM_SETRANGE, 0, MAKELONG(1, 40));
393  r = SendMessageA(updown, UDM_GETRANGE, 0, 0);
394  expect(1, LOWORD(r));
395  expect(40, HIWORD(r));
396 
397  accel.nSec = 0;
398  accel.nInc = 5;
399  r = SendMessageA(updown, UDM_SETACCEL, 1, (LPARAM)&accel);
400  expect(TRUE, r);
401 
402  r = SendMessageA(updown, UDM_GETPOS, 0, 0);
403  expect(40, LOWORD(r));
404  expect(1, HIWORD(r));
405 
406  r = SendMessageA(updown, UDM_SETPOS, 0, MAKELONG(0, 0));
407  expect(40, LOWORD(r));
408  expect(0, HIWORD(r));
409 
410  r = SendMessageA(updown, UDM_GETPOS, 0, 0);
411  expect(1, LOWORD(r));
412  expect(0, HIWORD(r));
413 
414  r = SendMessageA(updown, UDM_SETPOS, 0, MAKELONG(2, 0));
415  expect(1, LOWORD(r));
416  expect(0, HIWORD(r));
417 
419  expect(0, r);
420  r = SendMessageA(updown, UDM_GETPOS, 0, 0);
421  expect(1, LOWORD(r));
422  expect(0, HIWORD(r));
423 
424  r = SendMessageA(updown, UDM_SETPOS, 0, MAKELONG(50, 0));
425  expect(1, LOWORD(r));
426  expect(0, HIWORD(r));
427 
428  r = SendMessageA(updown, UDM_GETPOS, 0, 0);
429  expect(40, LOWORD(r));
430  expect(0, HIWORD(r));
431  }
432 
433  DestroyWindow(updown);
434 }
435 
436 static void test_updown_pos32(void)
437 {
438  HWND updown;
439  int r;
440  int low, high;
441 
443 
445 
446  /* Set the position to 0 to 1000 */
447  SendMessageA(updown, UDM_SETRANGE32, 0 , 1000 );
448 
449  low = high = -1;
450  r = SendMessageA(updown, UDM_GETRANGE32, (WPARAM) &low , (LPARAM) &high );
451  expect(0,r);
452  if (low == -1)
453  {
454  win_skip("UDM_SETRANGE32/UDM_GETRANGE32 not available\n");
455  DestroyWindow(updown);
456  return;
457  }
458 
459  expect(0,low);
460  expect(1000,high);
461 
462  /* Set position to 500 */
463  r = SendMessageA(updown, UDM_SETPOS32, 0 , 500 );
464  if (!r)
465  {
466  win_skip("UDM_SETPOS32 and UDM_GETPOS32 need 5.80\n");
467  DestroyWindow(updown);
468  return;
469  }
470  expect(50,r);
471 
472  /* Since UDM_SETBUDDYINT was not set at creation bRet will always be true as a return from UDM_GETPOS32 */
473 
474  r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
475  expect(500,r);
476  expect(1,high);
477 
478  /* Set position to 0, return should be 500 */
479  r = SendMessageA(updown, UDM_SETPOS32, 0 , 0 );
480  expect(500,r);
481  r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
482  expect(0,r);
483  expect(1,high);
484 
485  /* Set position to -1 which should become 0, return should be 0 */
486  r = SendMessageA(updown, UDM_SETPOS32, 0 , -1 );
487  expect(0,r);
488  r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
489  expect(0,r);
490  expect(1,high);
491 
492  /* Set position to 1000, return should be 0 */
493  r = SendMessageA(updown, UDM_SETPOS32, 0 , 1000 );
494  expect(0,r);
495  r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
496  expect(1000,r);
497  expect(1,high);
498 
499  /* Set position to 1001 which should become 1000, return should be 1000 */
500  r = SendMessageA(updown, UDM_SETPOS32, 0 , 1001 );
501  expect(1000,r);
502  r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
503  expect(1000,r);
504  expect(1,high);
505 
507 
508  DestroyWindow(updown);
509 
510  /* there's no attempt to update buddy Edit if text didn't change */
511  SetWindowTextA(g_edit, "50");
513 
515 
516  r = SendMessageA(updown, UDM_SETPOS32, 0, 50);
517  expect(50,r);
519  "test updown pos, no change", FALSE);
520 
521  DestroyWindow(updown);
522 }
523 
524 static void test_updown_buddy(void)
525 {
526  HWND updown, buddyReturn, buddy;
527  RECT rect, rect2;
528  WNDPROC proc;
529  DWORD style;
530 
532 
534 
535  buddyReturn = (HWND)SendMessageA(updown, UDM_GETBUDDY, 0 , 0 );
536  ok(buddyReturn == g_edit, "Expected edit handle\n");
537 
538  buddyReturn = (HWND)SendMessageA(updown, UDM_SETBUDDY, (WPARAM) g_edit, 0);
539  ok(buddyReturn == g_edit, "Expected edit handle\n");
540 
541  buddyReturn = (HWND)SendMessageA(updown, UDM_GETBUDDY, 0 , 0 );
542  ok(buddyReturn == g_edit, "Expected edit handle\n");
543 
545  ok_sequence(sequences, EDIT_SEQ_INDEX, add_updown_with_edit_seq, "test updown buddy_edit", FALSE);
546 
547  DestroyWindow(updown);
548 
549  buddy = create_edit_control();
551 
552  updown= create_updown_control(UDS_ALIGNRIGHT, buddy);
553  ok(proc == (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "No subclassing expected\n");
554 
555  style = GetWindowLongA(updown, GWL_STYLE);
557  style = GetWindowLongA(updown, GWL_STYLE);
558  ok(style & UDS_ARROWKEYS, "Expected UDS_ARROWKEYS\n");
559  /* no subclass if UDS_ARROWKEYS set after creation */
560  ok(proc == (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "No subclassing expected\n");
561 
562  DestroyWindow(updown);
563 
565  ok(proc != (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "Subclassing expected\n");
566 
567  if (pSetWindowSubclass)
568  {
569  /* updown uses subclass helpers for buddy on >5.8x systems */
570  ok(GetPropA(buddy, "CC32SubclassInfo") != NULL, "Expected CC32SubclassInfo property\n");
571  }
572 
573  DestroyWindow(updown);
574  DestroyWindow(buddy);
575 
576  /* Create with buddy and UDS_HORZ, reset buddy. */
578 
579  buddyReturn = (HWND)SendMessageA(updown, UDM_GETBUDDY, 0, 0);
580  ok(buddyReturn == g_edit, "Unexpected buddy window.\n");
581 
582  GetClientRect(updown, &rect);
583 
584  buddyReturn = (HWND)SendMessageA(updown, UDM_SETBUDDY, 0, 0);
585  ok(buddyReturn == g_edit, "Unexpected buddy window.\n");
586 
587  GetClientRect(updown, &rect2);
588  ok(EqualRect(&rect, &rect2), "Unexpected window rect.\n");
589 
590  /* Remove UDS_HORZ, reset buddy again. */
591  style = GetWindowLongA(updown, GWL_STYLE);
592  SetWindowLongA(updown, GWL_STYLE, style & ~UDS_HORZ);
593  style = GetWindowLongA(updown, GWL_STYLE);
594  ok(!(style & UDS_HORZ), "Unexpected style.\n");
595 
596  buddyReturn = (HWND)SendMessageA(updown, UDM_SETBUDDY, 0, 0);
597  ok(buddyReturn == NULL, "Unexpected buddy window.\n");
598 
599  GetClientRect(updown, &rect2);
600  ok(EqualRect(&rect, &rect2), "Unexpected window rect.\n");
601 
602  DestroyWindow(updown);
603 
604  /* Without UDS_HORZ. */
605  updown = create_updown_control(0, g_edit);
606 
607  buddyReturn = (HWND)SendMessageA(updown, UDM_GETBUDDY, 0, 0);
608  ok(buddyReturn == g_edit, "Unexpected buddy window.\n");
609 
610  GetClientRect(updown, &rect);
611 
612  buddyReturn = (HWND)SendMessageA(updown, UDM_SETBUDDY, 0, 0);
613  ok(buddyReturn == g_edit, "Unexpected buddy window.\n");
614 
615  GetClientRect(updown, &rect2);
616  ok(EqualRect(&rect, &rect2), "Unexpected window rect.\n");
617 
618  DestroyWindow(updown);
619 
620  /* Create without buddy. */
623  0, 0, rect.right, rect.bottom, parent_wnd, (HMENU)1, GetModuleHandleA(NULL), NULL);
624  ok(updown != NULL, "Failed to create UpDown control.\n");
625 
626  GetClientRect(updown, &rect);
627  buddyReturn = (HWND)SendMessageA(updown, UDM_SETBUDDY, 0, 0);
628  ok(buddyReturn == NULL, "Unexpected buddy window.\n");
629  GetClientRect(updown, &rect2);
630 
631  ok(EqualRect(&rect, &rect2), "Unexpected window rect.\n");
632 
633  style = GetWindowLongA(updown, GWL_STYLE);
634  SetWindowLongA(updown, GWL_STYLE, style & ~UDS_HORZ);
635 
636  GetClientRect(updown, &rect2);
637  ok(EqualRect(&rect, &rect2), "Unexpected window rect.\n");
638 
639  buddyReturn = (HWND)SendMessageA(updown, UDM_SETBUDDY, (WPARAM)g_edit, 0);
640  ok(buddyReturn == NULL, "Unexpected buddy window.\n");
641  GetClientRect(updown, &rect);
642 
643  buddyReturn = (HWND)SendMessageA(updown, UDM_SETBUDDY, 0, 0);
644  ok(buddyReturn == g_edit, "Unexpected buddy window.\n");
645  GetClientRect(updown, &rect2);
646 todo_wine
647  ok(EqualRect(&rect, &rect2), "Unexpected window rect.\n");
648 
649  DestroyWindow(updown);
650 }
651 
652 static void test_updown_base(void)
653 {
654  HWND updown;
655  int r;
656  CHAR text[10];
657 
659 
661 
662  SendMessageA(updown, UDM_SETBASE, 10 , 0);
663  r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
664  expect(10,r);
665 
666  /* Set base to an invalid value, should return 0 and stay at 10 */
667  r = SendMessageA(updown, UDM_SETBASE, 80 , 0);
668  expect(0,r);
669  r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
670  expect(10,r);
671 
672  /* Set base to 16 now, should get 16 as the return */
673  r = SendMessageA(updown, UDM_SETBASE, 16 , 0);
674  expect(10,r);
675  r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
676  expect(16,r);
677 
678  /* Set base to an invalid value, should return 0 and stay at 16 */
679  r = SendMessageA(updown, UDM_SETBASE, 80 , 0);
680  expect(0,r);
681  r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
682  expect(16,r);
683 
684  /* Set base back to 10, return should be 16 */
685  r = SendMessageA(updown, UDM_SETBASE, 10 , 0);
686  expect(16,r);
687  r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
688  expect(10,r);
689 
691 
692  DestroyWindow(updown);
693 
694  /* switch base with buddy attached */
696 
697  r = SendMessageA(updown, UDM_SETPOS, 0, 10);
698  expect(50, r);
699 
701  ok(lstrcmpA(text, "10") == 0, "Expected '10', got '%s'\n", text);
702 
703  r = SendMessageA(updown, UDM_SETBASE, 16, 0);
704  expect(10, r);
705 
707  /* FIXME: currently hex output isn't properly formatted, but for this
708  test only change from initial text matters */
709  ok(lstrcmpA(text, "10") != 0, "Expected '0x000A', got '%s'\n", text);
710 
711  DestroyWindow(updown);
712 }
713 
714 static void test_updown_unicode(void)
715 {
716  HWND updown;
717  int r;
718 
720 
722 
723  /* Set it to ANSI, don't check return as we don't know previous state */
724  SendMessageA(updown, UDM_SETUNICODEFORMAT, 0 , 0);
725  r = SendMessageA(updown, UDM_GETUNICODEFORMAT, 0 , 0);
726  expect(0,r);
727 
728  /* Now set it to Unicode format */
729  r = SendMessageA(updown, UDM_SETUNICODEFORMAT, 1 , 0);
730  expect(0,r);
731  r = SendMessageA(updown, UDM_GETUNICODEFORMAT, 0 , 0);
732  if (!r)
733  {
734  win_skip("UDM_SETUNICODEFORMAT not available\n");
735  DestroyWindow(updown);
736  return;
737  }
738  expect(1,r);
739 
740  /* And now set it back to ANSI */
741  r = SendMessageA(updown, UDM_SETUNICODEFORMAT, 0 , 0);
742  expect(1,r);
743  r = SendMessageA(updown, UDM_GETUNICODEFORMAT, 0 , 0);
744  expect(0,r);
745 
747 
748  DestroyWindow(updown);
749 }
750 
751 static void test_updown_create(void)
752 {
753  CHAR text[MAX_PATH];
754  HWND updown;
755  RECT r;
756 
758 
760  ok(updown != NULL, "Failed to create updown control\n");
761  ok_sequence(sequences, PARENT_SEQ_INDEX, add_updown_to_parent_seq, "add updown control to parent", TRUE);
762  ok_sequence(sequences, EDIT_SEQ_INDEX, add_updown_with_edit_seq, "add updown control with edit", FALSE);
763 
765 
767  ok(lstrlenA(text) == 0, "Expected empty string\n");
769 
770  DestroyWindow(updown);
771 
772  /* create with zero width */
773  updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
775  ok(updown != NULL, "Failed to create updown control\n");
776  r.right = 0;
777  GetClientRect(updown, &r);
778  ok(r.right > 0, "Expected default width, got %d\n", r.right);
779  DestroyWindow(updown);
780  /* create with really small width */
781  updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 2, 0,
783  ok(updown != NULL, "Failed to create updown control\n");
784  r.right = 0;
785  GetClientRect(updown, &r);
786  ok(r.right != 2 && r.right > 0, "Expected default width, got %d\n", r.right);
787  DestroyWindow(updown);
788  /* create with width greater than default */
789  updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 100, 0,
791  ok(updown != NULL, "Failed to create updown control\n");
792  r.right = 0;
793  GetClientRect(updown, &r);
794  ok(r.right < 100 && r.right > 0, "Expected default width, got %d\n", r.right);
795  DestroyWindow(updown);
796  /* create with zero height, UDS_HORZ */
797  updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
799  ok(updown != NULL, "Failed to create updown control\n");
800  r.bottom = 0;
801  GetClientRect(updown, &r);
802  ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
803  DestroyWindow(updown);
804  /* create with really small height, UDS_HORZ */
805  updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 2,
807  ok(updown != NULL, "Failed to create updown control\n");
808  r.bottom = 0;
809  GetClientRect(updown, &r);
810  ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
811  DestroyWindow(updown);
812  /* create with height greater than default, UDS_HORZ */
813  updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 100,
815  ok(updown != NULL, "Failed to create updown control\n");
816  r.bottom = 0;
817  GetClientRect(updown, &r);
818  ok(r.bottom < 100 && r.bottom > 0, "Expected default height, got %d\n", r.bottom);
819  DestroyWindow(updown);
820 }
821 
822 static void test_UDS_SETBUDDYINT(void)
823 {
824  HWND updown;
825  DWORD style, ret;
826  CHAR text[10];
827 
828  /* cleanup buddy */
829  text[0] = '\0';
831 
832  /* creating without UDS_SETBUDDYINT */
834  /* try to set UDS_SETBUDDYINT after creation */
835  style = GetWindowLongA(updown, GWL_STYLE);
837  style = GetWindowLongA(updown, GWL_STYLE);
838  ok(style & UDS_SETBUDDYINT, "Expected UDS_SETBUDDY to be set\n");
839  SendMessageA(updown, UDM_SETPOS, 0, 20);
841  ok(lstrlenA(text) == 0, "Expected empty string\n");
842  DestroyWindow(updown);
843 
844  /* creating with UDS_SETBUDDYINT */
847  /* 50 is initial value here */
848  ok(lstrcmpA(text, "50") == 0, "Expected '50', got '%s'\n", text);
849  /* now remove style flag */
850  style = GetWindowLongA(updown, GWL_STYLE);
852  SendMessageA(updown, UDM_SETPOS, 0, 20);
854  ok(lstrcmpA(text, "20") == 0, "Expected '20', got '%s'\n", text);
855  /* set edit text directly, check position */
856  strcpy(text, "10");
858  ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
859  expect(10, ret);
860  strcpy(text, "11");
862  ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
863  expect(11, LOWORD(ret));
864  expect(0, HIWORD(ret));
865  /* set to invalid value */
866  strcpy(text, "21st");
868  ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
869  expect(11, LOWORD(ret));
870  expect(TRUE, HIWORD(ret));
871  /* set style back */
872  style = GetWindowLongA(updown, GWL_STYLE);
874  SendMessageA(updown, UDM_SETPOS, 0, 30);
876  ok(lstrcmpA(text, "30") == 0, "Expected '30', got '%s'\n", text);
877  DestroyWindow(updown);
878 }
879 
880 static void test_CreateUpDownControl(void)
881 {
882  HWND updown, buddy;
883  DWORD range, pos;
884  RECT rect;
885 
887  updown = pCreateUpDownControl(WS_CHILD | WS_BORDER | WS_VISIBLE,
888  0, 0, rect.right, rect.bottom, parent_wnd, 1, GetModuleHandleA(NULL), g_edit, 100, 10, 50);
889  ok(updown != NULL, "Failed to create control.\n");
890 
891  buddy = (HWND)SendMessageA(updown, UDM_GETBUDDY, 0, 0);
892  ok(buddy == g_edit, "Unexpected buddy window.\n");
893 
894  range = SendMessageA(updown, UDM_GETRANGE, 0, 0);
895  ok(range == MAKELONG(100, 10), "Unexpected range.\n");
896 
897  pos = SendMessageA(updown, UDM_GETPOS, 0, 0);
898  ok(pos == MAKELONG(50, 1), "Unexpected position.\n");
899 
900  DestroyWindow(updown);
901 }
902 
903 static void init_functions(void)
904 {
905  HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
906 
907 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
908 #define X2(f, ord) p##f = (void*)GetProcAddress(hComCtl32, (const char *)ord);
910  X2(SetWindowSubclass, 410);
911 #undef X
912 #undef X2
913 }
914 
915 START_TEST(updown)
916 {
917  init_functions();
918 
920 
922  ok(parent_wnd != NULL, "Failed to create parent window!\n");
924  ok(g_edit != NULL, "Failed to create edit control\n");
925 
927  test_updown_pos();
934 
937 }
HGDIOBJ WINAPI GetStockObject(_In_ int)
static SUBCLASSPROC
Definition: updown.c:68
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition: updown.c:168
RECT rect2
Definition: edittest.c:51
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
static HWND
Definition: updown.c:66
Definition: tftpd.h:59
#define TRUE
Definition: types.h:120
#define NUM_MSG_SEQUENCES
Definition: updown.c:56
#define UDM_GETPOS
Definition: commctrl.h:2116
#define UDM_GETPOS32
Definition: commctrl.h:2128
int WINAPI GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
Definition: window.c:1326
#define X(f)
#define X2(f, ord)
static void test_CreateUpDownControl(void)
Definition: updown.c:880
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static LRESULT WINAPI updown_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition: updown.c:269
const WCHAR * text
Definition: package.c:1827
#define WM_NCCALCSIZE
Definition: winuser.h:1667
char CHAR
Definition: xmlstorage.h:175
#define WM_GETTEXT
Definition: winuser.h:1600
Definition: msg.h:39
static void test_updown_unicode(void)
Definition: updown.c:714
#define SIZE_RESTORED
Definition: winuser.h:2480
static void test_updown_pos(void)
Definition: updown.c:315
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: glext.h:5579
int cbClsExtra
Definition: winuser.h:3139
int WINAPI lstrcmpA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:18
#define UDM_SETACCEL
Definition: commctrl.h:2119
#define WM_MOVE
Definition: winuser.h:1592
LPCSTR lpszMenuName
Definition: winuser.h:3145
#define WHITE_BRUSH
Definition: wingdi.h:901
#define WM_NCHITTEST
Definition: winuser.h:1668
static UINT_PTR
Definition: updown.c:68
UINT_PTR WPARAM
Definition: windef.h:207
HBRUSH hbrBackground
Definition: winuser.h:3144
static HANDLE proc()
Definition: pdb.c:32
#define WS_CHILD
Definition: pedump.c:617
#define BUDDY_ID
Definition: updown.c:62
static const struct message test_updown_pos_nochange_seq[]
Definition: updown.c:163
static DWORD_PTR
Definition: updown.c:68
#define UDM_GETRANGE32
Definition: commctrl.h:2124
BOOL WINAPI DestroyWindow(_In_ HWND)
#define DWORD
Definition: nt_native.h:44
& rect
Definition: startmenu.cpp:1413
WPARAM wParam
Definition: combotst.c:138
static BOOL register_parent_wnd_class(void)
Definition: updown.c:199
LRESULT WINAPI CallWindowProcA(_In_ WNDPROC, _In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_NCPAINT
Definition: winuser.h:1669
int cbWndExtra
Definition: winuser.h:3140
#define WC_EDITA
Definition: commctrl.h:4657
static void test_updown_base(void)
Definition: updown.c:652
#define UDM_GETBASE
Definition: commctrl.h:2122
#define VK_UP
Definition: winuser.h:2200
LONG WINAPI GetWindowLongA(_In_ HWND, _In_ int)
#define UPDOWN_SEQ_INDEX
Definition: updown.c:59
#define WM_PARENTNOTIFY
Definition: winuser.h:1785
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
HWND WINAPI CreateUpDownControl(DWORD style, INT x, INT y, INT cx, INT cy, HWND parent, INT id, HINSTANCE inst, HWND buddy, INT maxVal, INT minVal, INT curVal)
Definition: commctrl.c:829
static UINT WPARAM LPARAM lparam
Definition: combo.c:716
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4216
HCURSOR hCursor
Definition: winuser.h:3143
static void init_msg_sequences(struct msg_sequence **seq, int n)
Definition: msg.h:391
#define GWLP_USERDATA
Definition: treelist.c:63
static HWND create_parent_window(void)
Definition: updown.c:216
#define MAKELONG(a, b)
Definition: typedefs.h:248
#define UDS_ARROWKEYS
Definition: commctrl.h:2108
static HWND create_updown_control(DWORD style, HWND buddy)
Definition: updown.c:291
smooth NULL
Definition: ftsmooth.c:416
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:652
static void init_functions(void)
Definition: updown.c:903
#define WM_KEYDOWN
Definition: winuser.h:1697
LONG_PTR LPARAM
Definition: windef.h:208
#define UDM_SETRANGE
Definition: commctrl.h:2113
const char * LPCSTR
Definition: xmlstorage.h:183
#define UDM_SETRANGE32
Definition: commctrl.h:2123
#define WS_MAXIMIZEBOX
Definition: pedump.c:632
Definition: msg.h:41
#define GetWindowLongPtrA
Definition: winuser.h:4729
BOOL WINAPI SetWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uIDSubclass, DWORD_PTR dwRef)
Definition: commctrl.c:1261
#define WS_CAPTION
Definition: pedump.c:624
#define WM_SIZE
Definition: winuser.h:1593
#define expect(EXPECTED, GOT)
Definition: updown.c:54
BOOL WINAPI SetWindowTextA(_In_ HWND, _In_opt_ LPCSTR)
UINT nSec
Definition: commctrl.h:2096
#define WM_WINDOWPOSCHANGING
Definition: winuser.h:1643
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:8
#define ok_sequence(seq, index, exp, contx, todo)
Definition: msg.h:387
#define UDM_SETPOS32
Definition: commctrl.h:2127
unsigned long DWORD
Definition: ntddk_ex.h:95
static const struct message add_updown_to_parent_seq[]
Definition: updown.c:80
#define WM_PAINT
Definition: winuser.h:1602
static struct msg_sequence * sequences[NUM_MSG_SEQUENCES]
Definition: updown.c:70
#define PARENT_SEQ_INDEX
Definition: updown.c:57
static const struct message get_edit_text_seq[]
Definition: updown.c:87
int ret
Definition: msg.h:34
#define todo_wine
Definition: test.h:154
#define SetWindowLongPtrA
Definition: winuser.h:5246
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
UINT nInc
Definition: commctrl.h:2097
#define UDS_HORZ
Definition: commctrl.h:2109
START_TEST(updown)
Definition: updown.c:915
#define UPDOWN_CLASSA
Definition: commctrl.h:2090
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
LPCSTR lpszClassName
Definition: winuser.h:3146
uint32_t DWORD_PTR
Definition: typedefs.h:63
static void test_updown_buddy(void)
Definition: updown.c:524
#define WM_USER
Definition: winuser.h:1877
HCURSOR WINAPI LoadCursorA(_In_opt_ HINSTANCE, _In_ LPCSTR)
Definition: cursoricon.c:2059
static const struct message add_updown_with_edit_seq[]
Definition: updown.c:72
#define GWLP_WNDPROC
Definition: treelist.c:66
#define NF_QUERY
Definition: winuser.h:2435
GLenum GLint * range
Definition: glext.h:7539
UINT style
Definition: winuser.h:3137
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2880
static const struct message test_updown_buddy_seq[]
Definition: updown.c:124
#define GWL_STYLE
Definition: winuser.h:846
#define UDM_SETBUDDY
Definition: commctrl.h:2117
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define EDIT_SEQ_INDEX
Definition: updown.c:58
#define WS_BORDER
Definition: pedump.c:625
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
static void test_updown_pos32(void)
Definition: updown.c:436
static LRESULT WINAPI edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition: updown.c:229
BOOL WINAPI EqualRect(_In_ LPCRECT, _In_ LPCRECT)
static BOOL(WINAPI *pSetWindowSubclass)(HWND
static HINSTANCE
Definition: updown.c:66
#define WS_MINIMIZEBOX
Definition: pedump.c:631
HANDLE WINAPI GetPropA(_In_ HWND, _In_ LPCSTR)
HINSTANCE hInstance
Definition: winuser.h:3141
#define add_message(msg)
Definition: msg.c:2142
#define ARRAY_SIZE(a)
Definition: main.h:24
#define UDS_ALIGNRIGHT
Definition: commctrl.h:2105
#define ok(value,...)
Definition: atltest.h:57
static void flush_sequences(struct msg_sequence **seq, int n)
Definition: msg.h:97
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
static HWND create_edit_control(void)
Definition: updown.c:250
#define UDM_SETPOS
Definition: commctrl.h:2115
#define UDM_GETRANGE
Definition: commctrl.h:2114
unsigned int UINT
Definition: ndis.h:50
#define UDM_GETBUDDY
Definition: commctrl.h:2118
LONG WINAPI SetWindowLongA(_In_ HWND, _In_ int, _In_ LONG)
#define WM_DEVICECHANGE
Definition: winuser.h:1793
WNDPROC lpfnWndProc
Definition: winuser.h:3138
static void test_UDS_SETBUDDYINT(void)
Definition: updown.c:822
#define WM_WINDOWPOSCHANGED
Definition: winuser.h:1644
#define msg(x)
Definition: auth_time.c:54
#define IDC_ARROW
Definition: winuser.h:682
#define WM_CREATE
Definition: winuser.h:1590
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
#define UDS_SETBUDDYINT
Definition: commctrl.h:2104
#define HIWORD(l)
Definition: typedefs.h:246
GLenum GLuint id
Definition: glext.h:5579
static const struct message test_updown_pos32_seq[]
Definition: updown.c:108
#define WM_ERASEBKGND
Definition: winuser.h:1607
static void test_updown_create(void)
Definition: updown.c:751
LONG_PTR LRESULT
Definition: windef.h:209
Arabic default style
Definition: afstyles.h:93
#define WS_VISIBLE
Definition: pedump.c:620
#define WS_SYSMENU
Definition: pedump.c:629
static INT
Definition: updown.c:66
static const struct message test_updown_base_seq[]
Definition: updown.c:139
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
#define win_skip
Definition: test.h:141
#define UDM_GETUNICODEFORMAT
Definition: commctrl.h:2126
LPARAM lParam
Definition: combotst.c:139
#define LOWORD(l)
Definition: pedump.c:82
static const struct message test_updown_unicode_seq[]
Definition: updown.c:153
#define UDM_SETBASE
Definition: commctrl.h:2121
#define UPDOWN_ID
Definition: updown.c:61
ATOM WINAPI RegisterClassA(_In_ CONST WNDCLASSA *)
static const struct message test_updown_pos_seq[]
Definition: updown.c:92
static HWND parent_wnd
Definition: updown.c:64
static HWND g_edit
Definition: updown.c:64
static UINT WPARAM wparam
Definition: combo.c:716
#define UDM_SETUNICODEFORMAT
Definition: commctrl.h:2125
HICON hIcon
Definition: winuser.h:3142