[COMCTL32_WINETEST] Add a PCH.
[reactos.git] / modules / rostests / winetests / comctl32 / updown.c
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 "precomp.h"
48
49 #define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
50
51 #define NUM_MSG_SEQUENCES 3
52 #define PARENT_SEQ_INDEX 0
53 #define EDIT_SEQ_INDEX 1
54 #define UPDOWN_SEQ_INDEX 2
55
56 #define UPDOWN_ID 0
57 #define BUDDY_ID 1
58
59 static HWND parent_wnd, g_edit;
60
61 static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
62
63 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
64
65 static const struct message add_updown_with_edit_seq[] = {
66 { WM_WINDOWPOSCHANGING, sent },
67 { WM_NCCALCSIZE, sent|wparam, TRUE },
68 { WM_WINDOWPOSCHANGED, sent },
69 { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED /*, MAKELONG(91, 75) exact size depends on font */ },
70 { 0 }
71 };
72
73 static const struct message add_updown_to_parent_seq[] = {
74 { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
75 { WM_QUERYUISTATE, sent|optional },
76 { WM_PARENTNOTIFY, sent|wparam, MAKELONG(WM_CREATE, WM_CREATE) },
77 { 0 }
78 };
79
80 static const struct message get_edit_text_seq[] = {
81 { WM_GETTEXT, sent },
82 { 0 }
83 };
84
85 static const struct message test_updown_pos_seq[] = {
86 { UDM_SETRANGE, sent|lparam, 0, MAKELONG(100,0) },
87 { UDM_GETRANGE, sent},
88 { UDM_SETPOS, sent|lparam, 0, 5},
89 { UDM_GETPOS, sent},
90 { UDM_SETPOS, sent|lparam, 0, 0},
91 { UDM_GETPOS, sent},
92 { UDM_SETPOS, sent|lparam, 0, MAKELONG(-1,0)},
93 { UDM_GETPOS, sent},
94 { UDM_SETPOS, sent|lparam, 0, 100},
95 { UDM_GETPOS, sent},
96 { UDM_SETPOS, sent|lparam, 0, 101},
97 { UDM_GETPOS, sent},
98 { 0 }
99 };
100
101 static const struct message test_updown_pos32_seq[] = {
102 { UDM_SETRANGE32, sent|lparam, 0, 1000 },
103 { UDM_GETRANGE32, sent}, /* Cannot check wparam and lparam as they are ptrs */
104 { UDM_SETPOS32, sent|lparam, 0, 500 },
105 { UDM_GETPOS32, sent},
106 { UDM_SETPOS32, sent|lparam, 0, 0 },
107 { UDM_GETPOS32, sent},
108 { UDM_SETPOS32, sent|lparam, 0, -1 },
109 { UDM_GETPOS32, sent},
110 { UDM_SETPOS32, sent|lparam, 0, 1000 },
111 { UDM_GETPOS32, sent},
112 { UDM_SETPOS32, sent|lparam, 0, 1001 },
113 { UDM_GETPOS32, sent},
114 { 0 }
115 };
116
117 static const struct message test_updown_buddy_seq[] = {
118 { UDM_GETBUDDY, sent },
119 { UDM_SETBUDDY, sent },
120 { WM_STYLECHANGING, sent|defwinproc },
121 { WM_STYLECHANGED, sent|defwinproc },
122 { WM_STYLECHANGING, sent|defwinproc },
123 { WM_STYLECHANGED, sent|defwinproc },
124 { WM_WINDOWPOSCHANGING, sent|defwinproc },
125 { WM_NCCALCSIZE, sent|wparam|optional|defwinproc, 1 },
126 { WM_WINDOWPOSCHANGED, sent|defwinproc },
127 { WM_MOVE, sent|defwinproc },
128 { UDM_GETBUDDY, sent },
129 { 0 }
130 };
131
132 static const struct message test_updown_base_seq[] = {
133 { UDM_SETBASE, sent|wparam, 10 },
134 { UDM_GETBASE, sent },
135 { UDM_SETBASE, sent|wparam, 80 },
136 { UDM_GETBASE, sent },
137 { UDM_SETBASE, sent|wparam, 16 },
138 { UDM_GETBASE, sent },
139 { UDM_SETBASE, sent|wparam, 80 },
140 { UDM_GETBASE, sent },
141 { UDM_SETBASE, sent|wparam, 10 },
142 { UDM_GETBASE, sent },
143 { 0 }
144 };
145
146 static const struct message test_updown_unicode_seq[] = {
147 { UDM_SETUNICODEFORMAT, sent|wparam, 0 },
148 { UDM_GETUNICODEFORMAT, sent },
149 { UDM_SETUNICODEFORMAT, sent|wparam, 1 },
150 { UDM_GETUNICODEFORMAT, sent },
151 { UDM_SETUNICODEFORMAT, sent|wparam, 0 },
152 { UDM_GETUNICODEFORMAT, sent },
153 { 0 }
154 };
155
156 static const struct message test_updown_pos_nochange_seq[] = {
157 { WM_GETTEXT, sent|id, 0, 0, BUDDY_ID },
158 { 0 }
159 };
160
161 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
162 {
163 static LONG defwndproc_counter = 0;
164 struct message msg = { 0 };
165 LRESULT ret;
166
167 /* log system messages, except for painting */
168 if (message < WM_USER &&
169 message != WM_PAINT &&
170 message != WM_ERASEBKGND &&
171 message != WM_NCPAINT &&
172 message != WM_NCHITTEST &&
173 message != WM_GETTEXT &&
174 message != WM_GETICON &&
175 message != WM_DEVICECHANGE)
176 {
177 msg.message = message;
178 msg.flags = sent|wparam|lparam;
179 if (defwndproc_counter) msg.flags |= defwinproc;
180 msg.wParam = wParam;
181 msg.lParam = lParam;
182 add_message(sequences, PARENT_SEQ_INDEX, &msg);
183 }
184
185 defwndproc_counter++;
186 ret = DefWindowProcA(hwnd, message, wParam, lParam);
187 defwndproc_counter--;
188
189 return ret;
190 }
191
192 static BOOL register_parent_wnd_class(void)
193 {
194 WNDCLASSA cls;
195
196 cls.style = 0;
197 cls.lpfnWndProc = parent_wnd_proc;
198 cls.cbClsExtra = 0;
199 cls.cbWndExtra = 0;
200 cls.hInstance = GetModuleHandleA(NULL);
201 cls.hIcon = 0;
202 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
203 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
204 cls.lpszMenuName = NULL;
205 cls.lpszClassName = "Up-Down test parent class";
206 return RegisterClassA(&cls);
207 }
208
209 static HWND create_parent_window(void)
210 {
211 if (!register_parent_wnd_class())
212 return NULL;
213
214 return CreateWindowExA(0, "Up-Down test parent class",
215 "Up-Down test parent window",
216 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
217 WS_MAXIMIZEBOX | WS_VISIBLE,
218 0, 0, 100, 100,
219 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
220 }
221
222 static LRESULT WINAPI edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
223 {
224 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
225 static LONG defwndproc_counter = 0;
226 struct message msg = { 0 };
227 LRESULT ret;
228
229 msg.message = message;
230 msg.flags = sent|wparam|lparam;
231 if (defwndproc_counter) msg.flags |= defwinproc;
232 msg.wParam = wParam;
233 msg.lParam = lParam;
234 msg.id = BUDDY_ID;
235 add_message(sequences, EDIT_SEQ_INDEX, &msg);
236
237 defwndproc_counter++;
238 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
239 defwndproc_counter--;
240 return ret;
241 }
242
243 static HWND create_edit_control(void)
244 {
245 WNDPROC oldproc;
246 HWND hwnd;
247 RECT rect;
248
249 GetClientRect(parent_wnd, &rect);
250 hwnd = CreateWindowExA(0, WC_EDITA, NULL, WS_CHILD | WS_BORDER | WS_VISIBLE,
251 0, 0, rect.right, rect.bottom,
252 parent_wnd, NULL, GetModuleHandleA(NULL), NULL);
253 if (!hwnd) return NULL;
254
255 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
256 (LONG_PTR)edit_subclass_proc);
257 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
258
259 return hwnd;
260 }
261
262 static LRESULT WINAPI updown_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
263 {
264 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
265 static LONG defwndproc_counter = 0;
266 struct message msg = { 0 };
267 LRESULT ret;
268
269 msg.message = message;
270 msg.flags = sent|wparam|lparam;
271 if (defwndproc_counter) msg.flags |= defwinproc;
272 msg.wParam = wParam;
273 msg.lParam = lParam;
274 msg.id = UPDOWN_ID;
275 add_message(sequences, UPDOWN_SEQ_INDEX, &msg);
276
277 defwndproc_counter++;
278 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
279 defwndproc_counter--;
280
281 return ret;
282 }
283
284 static HWND create_updown_control(DWORD style, HWND buddy)
285 {
286 WNDPROC oldproc;
287 HWND updown;
288 RECT rect;
289
290 GetClientRect(parent_wnd, &rect);
291 updown = CreateUpDownControl(WS_CHILD | WS_BORDER | WS_VISIBLE | style,
292 0, 0, rect.right, rect.bottom, parent_wnd, 1, GetModuleHandleA(NULL), buddy,
293 100, 0, 50);
294 if (!updown) return NULL;
295
296 oldproc = (WNDPROC)SetWindowLongPtrA(updown, GWLP_WNDPROC,
297 (LONG_PTR)updown_subclass_proc);
298 SetWindowLongPtrA(updown, GWLP_USERDATA, (LONG_PTR)oldproc);
299
300 return updown;
301 }
302
303 static void test_updown_pos(void)
304 {
305 HWND updown;
306 int r;
307
308 updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
309
310 flush_sequences(sequences, NUM_MSG_SEQUENCES);
311
312 /* Set Range from 0 to 100 */
313 SendMessageA(updown, UDM_SETRANGE, 0 , MAKELONG(100,0) );
314 r = SendMessageA(updown, UDM_GETRANGE, 0,0);
315 expect(100,LOWORD(r));
316 expect(0,HIWORD(r));
317
318 /* Set the position to 5, return is not checked as it was set before func call */
319 SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(5,0) );
320 /* Since UDM_SETBUDDYINT was not set at creation HIWORD(r) will always be 1 as a return from UDM_GETPOS */
321 /* Get the position, which should be 5 */
322 r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
323 expect(5,LOWORD(r));
324 expect(1,HIWORD(r));
325
326 /* Set the position to 0, return should be 5 */
327 r = SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(0,0) );
328 expect(5,r);
329 /* Get the position, which should be 0 */
330 r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
331 expect(0,LOWORD(r));
332 expect(1,HIWORD(r));
333
334 /* Set the position to -1, return should be 0 */
335 r = SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(-1,0) );
336 expect(0,r);
337 /* Get the position, which should be 0 */
338 r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
339 expect(0,LOWORD(r));
340 expect(1,HIWORD(r));
341
342 /* Set the position to 100, return should be 0 */
343 r = SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(100,0) );
344 expect(0,r);
345 /* Get the position, which should be 100 */
346 r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
347 expect(100,LOWORD(r));
348 expect(1,HIWORD(r));
349
350 /* Set the position to 101, return should be 100 */
351 r = SendMessageA(updown, UDM_SETPOS, 0 , MAKELONG(101,0) );
352 expect(100,r);
353 /* Get the position, which should be 100 */
354 r = SendMessageA(updown, UDM_GETPOS, 0 , 0 );
355 expect(100,LOWORD(r));
356 expect(1,HIWORD(r));
357
358 ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_pos_seq , "test updown pos", FALSE);
359
360 DestroyWindow(updown);
361
362 /* there's no attempt to update buddy Edit if text didn't change */
363 SetWindowTextA(g_edit, "50");
364 updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT | UDS_ARROWKEYS, g_edit);
365
366 /* test sequence only on 5.8x versions */
367 r = SendMessageA(updown, UDM_GETPOS32, 0, 0);
368 if (r)
369 {
370 UDACCEL accel;
371
372 flush_sequences(sequences, NUM_MSG_SEQUENCES);
373
374 r = SendMessageA(updown, UDM_SETPOS, 0, 50);
375 expect(50,r);
376
377 ok_sequence(sequences, EDIT_SEQ_INDEX, test_updown_pos_nochange_seq,
378 "test updown pos, no change", FALSE);
379
380 SendMessageA(updown, UDM_SETRANGE, 0, MAKELONG(1, 40));
381 r = SendMessageA(updown, UDM_GETRANGE, 0, 0);
382 expect(1, LOWORD(r));
383 expect(40, HIWORD(r));
384
385 accel.nSec = 0;
386 accel.nInc = 5;
387 r = SendMessageA(updown, UDM_SETACCEL, 1, (LPARAM)&accel);
388 expect(TRUE, r);
389
390 r = SendMessageA(updown, UDM_GETPOS, 0, 0);
391 expect(40, LOWORD(r));
392 expect(1, HIWORD(r));
393
394 r = SendMessageA(updown, UDM_SETPOS, 0, MAKELONG(0, 0));
395 expect(40, LOWORD(r));
396 expect(0, HIWORD(r));
397
398 r = SendMessageA(updown, UDM_GETPOS, 0, 0);
399 expect(1, LOWORD(r));
400 expect(0, HIWORD(r));
401
402 r = SendMessageA(updown, UDM_SETPOS, 0, MAKELONG(2, 0));
403 expect(1, LOWORD(r));
404 expect(0, HIWORD(r));
405
406 r = SendMessageA(g_edit, WM_KEYDOWN, VK_UP, 0);
407 expect(0, r);
408 r = SendMessageA(updown, UDM_GETPOS, 0, 0);
409 expect(1, LOWORD(r));
410 expect(0, HIWORD(r));
411
412 r = SendMessageA(updown, UDM_SETPOS, 0, MAKELONG(50, 0));
413 expect(1, LOWORD(r));
414 expect(0, HIWORD(r));
415
416 r = SendMessageA(updown, UDM_GETPOS, 0, 0);
417 expect(40, LOWORD(r));
418 expect(0, HIWORD(r));
419 }
420
421 DestroyWindow(updown);
422 }
423
424 static void test_updown_pos32(void)
425 {
426 HWND updown;
427 int r;
428 int low, high;
429
430 updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
431
432 flush_sequences(sequences, NUM_MSG_SEQUENCES);
433
434 /* Set the position to 0 to 1000 */
435 SendMessageA(updown, UDM_SETRANGE32, 0 , 1000 );
436
437 low = high = -1;
438 r = SendMessageA(updown, UDM_GETRANGE32, (WPARAM) &low , (LPARAM) &high );
439 expect(0,r);
440 if (low == -1)
441 {
442 win_skip("UDM_SETRANGE32/UDM_GETRANGE32 not available\n");
443 DestroyWindow(updown);
444 return;
445 }
446
447 expect(0,low);
448 expect(1000,high);
449
450 /* Set position to 500 */
451 r = SendMessageA(updown, UDM_SETPOS32, 0 , 500 );
452 if (!r)
453 {
454 win_skip("UDM_SETPOS32 and UDM_GETPOS32 need 5.80\n");
455 DestroyWindow(updown);
456 return;
457 }
458 expect(50,r);
459
460 /* Since UDM_SETBUDDYINT was not set at creation bRet will always be true as a return from UDM_GETPOS32 */
461
462 r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
463 expect(500,r);
464 expect(1,high);
465
466 /* Set position to 0, return should be 500 */
467 r = SendMessageA(updown, UDM_SETPOS32, 0 , 0 );
468 expect(500,r);
469 r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
470 expect(0,r);
471 expect(1,high);
472
473 /* Set position to -1 which should become 0, return should be 0 */
474 r = SendMessageA(updown, UDM_SETPOS32, 0 , -1 );
475 expect(0,r);
476 r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
477 expect(0,r);
478 expect(1,high);
479
480 /* Set position to 1000, return should be 0 */
481 r = SendMessageA(updown, UDM_SETPOS32, 0 , 1000 );
482 expect(0,r);
483 r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
484 expect(1000,r);
485 expect(1,high);
486
487 /* Set position to 1001 which should become 1000, return should be 1000 */
488 r = SendMessageA(updown, UDM_SETPOS32, 0 , 1001 );
489 expect(1000,r);
490 r = SendMessageA(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
491 expect(1000,r);
492 expect(1,high);
493
494 ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_pos32_seq, "test updown pos32", FALSE);
495
496 DestroyWindow(updown);
497
498 /* there's no attempt to update buddy Edit if text didn't change */
499 SetWindowTextA(g_edit, "50");
500 updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT, g_edit);
501
502 flush_sequences(sequences, NUM_MSG_SEQUENCES);
503
504 r = SendMessageA(updown, UDM_SETPOS32, 0, 50);
505 expect(50,r);
506 ok_sequence(sequences, EDIT_SEQ_INDEX, test_updown_pos_nochange_seq,
507 "test updown pos, no change", FALSE);
508
509 DestroyWindow(updown);
510 }
511
512 static void test_updown_buddy(void)
513 {
514 HWND updown, buddyReturn, buddy;
515 WNDPROC proc;
516 DWORD style;
517
518 updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
519
520 flush_sequences(sequences, NUM_MSG_SEQUENCES);
521
522 buddyReturn = (HWND)SendMessageA(updown, UDM_GETBUDDY, 0 , 0 );
523 ok(buddyReturn == g_edit, "Expected edit handle\n");
524
525 buddyReturn = (HWND)SendMessageA(updown, UDM_SETBUDDY, (WPARAM) g_edit, 0);
526 ok(buddyReturn == g_edit, "Expected edit handle\n");
527
528 buddyReturn = (HWND)SendMessageA(updown, UDM_GETBUDDY, 0 , 0 );
529 ok(buddyReturn == g_edit, "Expected edit handle\n");
530
531 ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_buddy_seq, "test updown buddy", TRUE);
532 ok_sequence(sequences, EDIT_SEQ_INDEX, add_updown_with_edit_seq, "test updown buddy_edit", FALSE);
533
534 DestroyWindow(updown);
535
536 buddy = create_edit_control();
537 proc = (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC);
538
539 updown= create_updown_control(UDS_ALIGNRIGHT, buddy);
540 ok(proc == (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "No subclassing expected\n");
541
542 style = GetWindowLongA(updown, GWL_STYLE);
543 SetWindowLongA(updown, GWL_STYLE, style | UDS_ARROWKEYS);
544 style = GetWindowLongA(updown, GWL_STYLE);
545 ok(style & UDS_ARROWKEYS, "Expected UDS_ARROWKEYS\n");
546 /* no subclass if UDS_ARROWKEYS set after creation */
547 ok(proc == (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "No subclassing expected\n");
548
549 DestroyWindow(updown);
550
551 updown= create_updown_control(UDS_ALIGNRIGHT | UDS_ARROWKEYS, buddy);
552 ok(proc != (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "Subclassing expected\n");
553
554 if (pSetWindowSubclass)
555 {
556 /* updown uses subclass helpers for buddy on >5.8x systems */
557 ok(GetPropA(buddy, "CC32SubclassInfo") != NULL, "Expected CC32SubclassInfo property\n");
558 }
559
560 DestroyWindow(updown);
561
562 DestroyWindow(buddy);
563 }
564
565 static void test_updown_base(void)
566 {
567 HWND updown;
568 int r;
569 CHAR text[10];
570
571 updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
572
573 flush_sequences(sequences, NUM_MSG_SEQUENCES);
574
575 SendMessageA(updown, UDM_SETBASE, 10 , 0);
576 r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
577 expect(10,r);
578
579 /* Set base to an invalid value, should return 0 and stay at 10 */
580 r = SendMessageA(updown, UDM_SETBASE, 80 , 0);
581 expect(0,r);
582 r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
583 expect(10,r);
584
585 /* Set base to 16 now, should get 16 as the return */
586 r = SendMessageA(updown, UDM_SETBASE, 16 , 0);
587 expect(10,r);
588 r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
589 expect(16,r);
590
591 /* Set base to an invalid value, should return 0 and stay at 16 */
592 r = SendMessageA(updown, UDM_SETBASE, 80 , 0);
593 expect(0,r);
594 r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
595 expect(16,r);
596
597 /* Set base back to 10, return should be 16 */
598 r = SendMessageA(updown, UDM_SETBASE, 10 , 0);
599 expect(16,r);
600 r = SendMessageA(updown, UDM_GETBASE, 0 , 0);
601 expect(10,r);
602
603 ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_base_seq, "test updown base", FALSE);
604
605 DestroyWindow(updown);
606
607 /* switch base with buddy attached */
608 updown = create_updown_control(UDS_SETBUDDYINT | UDS_ALIGNRIGHT, g_edit);
609
610 r = SendMessageA(updown, UDM_SETPOS, 0, 10);
611 expect(50, r);
612
613 GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
614 ok(lstrcmpA(text, "10") == 0, "Expected '10', got '%s'\n", text);
615
616 r = SendMessageA(updown, UDM_SETBASE, 16, 0);
617 expect(10, r);
618
619 GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
620 /* FIXME: currently hex output isn't properly formatted, but for this
621 test only change from initial text matters */
622 ok(lstrcmpA(text, "10") != 0, "Expected '0x000A', got '%s'\n", text);
623
624 DestroyWindow(updown);
625 }
626
627 static void test_updown_unicode(void)
628 {
629 HWND updown;
630 int r;
631
632 updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
633
634 flush_sequences(sequences, NUM_MSG_SEQUENCES);
635
636 /* Set it to ANSI, don't check return as we don't know previous state */
637 SendMessageA(updown, UDM_SETUNICODEFORMAT, 0 , 0);
638 r = SendMessageA(updown, UDM_GETUNICODEFORMAT, 0 , 0);
639 expect(0,r);
640
641 /* Now set it to Unicode format */
642 r = SendMessageA(updown, UDM_SETUNICODEFORMAT, 1 , 0);
643 expect(0,r);
644 r = SendMessageA(updown, UDM_GETUNICODEFORMAT, 0 , 0);
645 if (!r)
646 {
647 win_skip("UDM_SETUNICODEFORMAT not available\n");
648 DestroyWindow(updown);
649 return;
650 }
651 expect(1,r);
652
653 /* And now set it back to ANSI */
654 r = SendMessageA(updown, UDM_SETUNICODEFORMAT, 0 , 0);
655 expect(1,r);
656 r = SendMessageA(updown, UDM_GETUNICODEFORMAT, 0 , 0);
657 expect(0,r);
658
659 ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_unicode_seq, "test updown unicode", FALSE);
660
661 DestroyWindow(updown);
662 }
663
664 static void test_updown_create(void)
665 {
666 CHAR text[MAX_PATH];
667 HWND updown;
668 RECT r;
669
670 flush_sequences(sequences, NUM_MSG_SEQUENCES);
671
672 updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
673 ok(updown != NULL, "Failed to create updown control\n");
674 ok_sequence(sequences, PARENT_SEQ_INDEX, add_updown_to_parent_seq, "add updown control to parent", TRUE);
675 ok_sequence(sequences, EDIT_SEQ_INDEX, add_updown_with_edit_seq, "add updown control with edit", FALSE);
676
677 flush_sequences(sequences, NUM_MSG_SEQUENCES);
678
679 GetWindowTextA(g_edit, text, MAX_PATH);
680 ok(lstrlenA(text) == 0, "Expected empty string\n");
681 ok_sequence(sequences, EDIT_SEQ_INDEX, get_edit_text_seq, "get edit text", FALSE);
682
683 DestroyWindow(updown);
684
685 /* create with zero width */
686 updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
687 parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
688 ok(updown != NULL, "Failed to create updown control\n");
689 r.right = 0;
690 GetClientRect(updown, &r);
691 ok(r.right > 0, "Expected default width, got %d\n", r.right);
692 DestroyWindow(updown);
693 /* create with really small width */
694 updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 2, 0,
695 parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
696 ok(updown != NULL, "Failed to create updown control\n");
697 r.right = 0;
698 GetClientRect(updown, &r);
699 ok(r.right != 2 && r.right > 0, "Expected default width, got %d\n", r.right);
700 DestroyWindow(updown);
701 /* create with width greater than default */
702 updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 100, 0,
703 parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
704 ok(updown != NULL, "Failed to create updown control\n");
705 r.right = 0;
706 GetClientRect(updown, &r);
707 ok(r.right < 100 && r.right > 0, "Expected default width, got %d\n", r.right);
708 DestroyWindow(updown);
709 /* create with zero height, UDS_HORZ */
710 updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
711 parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
712 ok(updown != NULL, "Failed to create updown control\n");
713 r.bottom = 0;
714 GetClientRect(updown, &r);
715 ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
716 DestroyWindow(updown);
717 /* create with really small height, UDS_HORZ */
718 updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 2,
719 parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
720 ok(updown != NULL, "Failed to create updown control\n");
721 r.bottom = 0;
722 GetClientRect(updown, &r);
723 ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
724 DestroyWindow(updown);
725 /* create with height greater than default, UDS_HORZ */
726 updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 100,
727 parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
728 ok(updown != NULL, "Failed to create updown control\n");
729 r.bottom = 0;
730 GetClientRect(updown, &r);
731 ok(r.bottom < 100 && r.bottom > 0, "Expected default height, got %d\n", r.bottom);
732 DestroyWindow(updown);
733 }
734
735 static void test_UDS_SETBUDDYINT(void)
736 {
737 HWND updown;
738 DWORD style, ret;
739 CHAR text[10];
740
741 /* cleanup buddy */
742 text[0] = '\0';
743 SetWindowTextA(g_edit, text);
744
745 /* creating without UDS_SETBUDDYINT */
746 updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
747 /* try to set UDS_SETBUDDYINT after creation */
748 style = GetWindowLongA(updown, GWL_STYLE);
749 SetWindowLongA(updown, GWL_STYLE, style | UDS_SETBUDDYINT);
750 style = GetWindowLongA(updown, GWL_STYLE);
751 ok(style & UDS_SETBUDDYINT, "Expected UDS_SETBUDDY to be set\n");
752 SendMessageA(updown, UDM_SETPOS, 0, 20);
753 GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
754 ok(lstrlenA(text) == 0, "Expected empty string\n");
755 DestroyWindow(updown);
756
757 /* creating with UDS_SETBUDDYINT */
758 updown = create_updown_control(UDS_SETBUDDYINT | UDS_ALIGNRIGHT, g_edit);
759 GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
760 /* 50 is initial value here */
761 ok(lstrcmpA(text, "50") == 0, "Expected '50', got '%s'\n", text);
762 /* now remove style flag */
763 style = GetWindowLongA(updown, GWL_STYLE);
764 SetWindowLongA(updown, GWL_STYLE, style & ~UDS_SETBUDDYINT);
765 SendMessageA(updown, UDM_SETPOS, 0, 20);
766 GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
767 ok(lstrcmpA(text, "20") == 0, "Expected '20', got '%s'\n", text);
768 /* set edit text directly, check position */
769 strcpy(text, "10");
770 SetWindowTextA(g_edit, text);
771 ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
772 expect(10, ret);
773 strcpy(text, "11");
774 SetWindowTextA(g_edit, text);
775 ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
776 expect(11, LOWORD(ret));
777 expect(0, HIWORD(ret));
778 /* set to invalid value */
779 strcpy(text, "21st");
780 SetWindowTextA(g_edit, text);
781 ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
782 expect(11, LOWORD(ret));
783 expect(TRUE, HIWORD(ret));
784 /* set style back */
785 style = GetWindowLongA(updown, GWL_STYLE);
786 SetWindowLongA(updown, GWL_STYLE, style | UDS_SETBUDDYINT);
787 SendMessageA(updown, UDM_SETPOS, 0, 30);
788 GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
789 ok(lstrcmpA(text, "30") == 0, "Expected '30', got '%s'\n", text);
790 DestroyWindow(updown);
791 }
792
793 START_TEST(updown)
794 {
795 HMODULE mod = GetModuleHandleA("comctl32.dll");
796
797 pSetWindowSubclass = (void*)GetProcAddress(mod, (LPSTR)410);
798
799 InitCommonControls();
800 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
801
802 parent_wnd = create_parent_window();
803 ok(parent_wnd != NULL, "Failed to create parent window!\n");
804 g_edit = create_edit_control();
805 ok(g_edit != NULL, "Failed to create edit control\n");
806
807 test_updown_create();
808 test_updown_pos();
809 test_updown_pos32();
810 test_updown_buddy();
811 test_updown_base();
812 test_updown_unicode();
813 test_UDS_SETBUDDYINT();
814
815 DestroyWindow(g_edit);
816 DestroyWindow(parent_wnd);
817 }