user32/tests: Add the trailing '\n' to ok() calls.
[wine/gsoc_dplay.git] / dlls / user32 / tests / listbox.c
blob6d0d2c87ae96af9c2ed4082c3949734e441ef1ab
1 /* Unit test suite for list boxes.
3 * Copyright 2003 Ferenc Wagner
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winnls.h"
30 #include "wine/test.h"
32 #ifdef VISIBLE
33 #define WAIT Sleep (1000)
34 #define REDRAW RedrawWindow (handle, NULL, 0, RDW_UPDATENOW)
35 #else
36 #define WAIT
37 #define REDRAW
38 #endif
40 static const char * const strings[4] = {
41 "First added",
42 "Second added",
43 "Third added",
44 "Fourth added which is very long because at some time we only had a 256 byte character buffer and that was overflowing in one of those applications that had a common dialog file open box and tried to add a 300 characters long custom filter string which of course the code did not like and crashed. Just make sure this string is longer than 256 characters."
47 static HWND
48 create_listbox (DWORD add_style, HWND parent)
50 HWND handle;
51 int ctl_id=0;
52 if (parent)
53 ctl_id=1;
54 handle=CreateWindow ("LISTBOX", "TestList",
55 (LBS_STANDARD & ~LBS_SORT) | add_style,
56 0, 0, 100, 100,
57 parent, (HMENU)ctl_id, NULL, 0);
59 assert (handle);
60 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[0]);
61 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[1]);
62 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[2]);
63 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[3]);
65 #ifdef VISIBLE
66 ShowWindow (handle, SW_SHOW);
67 #endif
68 REDRAW;
70 return handle;
73 struct listbox_prop {
74 DWORD add_style;
77 struct listbox_stat {
78 int selected, anchor, caret, selcount;
81 struct listbox_test {
82 struct listbox_prop prop;
83 struct listbox_stat init, init_todo;
84 struct listbox_stat click, click_todo;
85 struct listbox_stat step, step_todo;
86 struct listbox_stat sel, sel_todo;
89 static void
90 listbox_query (HWND handle, struct listbox_stat *results)
92 results->selected = SendMessage (handle, LB_GETCURSEL, 0, 0);
93 results->anchor = SendMessage (handle, LB_GETANCHORINDEX, 0, 0);
94 results->caret = SendMessage (handle, LB_GETCARETINDEX, 0, 0);
95 results->selcount = SendMessage (handle, LB_GETSELCOUNT, 0, 0);
98 static void
99 buttonpress (HWND handle, WORD x, WORD y)
101 LPARAM lp=x+(y<<16);
103 WAIT;
104 SendMessage (handle, WM_LBUTTONDOWN, (WPARAM) MK_LBUTTON, lp);
105 SendMessage (handle, WM_LBUTTONUP , (WPARAM) 0 , lp);
106 REDRAW;
109 static void
110 keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
112 LPARAM lp=1+(scancode<<16)+(extended?KEYEVENTF_EXTENDEDKEY:0);
114 WAIT;
115 SendMessage (handle, WM_KEYDOWN, keycode, lp);
116 SendMessage (handle, WM_KEYUP , keycode, lp | 0xc000000);
117 REDRAW;
120 #define listbox_field_ok(t, s, f, got) \
121 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
122 ": expected %d, got %d\n", (unsigned int)t.prop.add_style, \
123 t.s.f, got.f)
125 #define listbox_todo_field_ok(t, s, f, got) \
126 if (t.s##_todo.f) todo_wine { listbox_field_ok(t, s, f, got); } \
127 else listbox_field_ok(t, s, f, got)
129 #define listbox_ok(t, s, got) \
130 listbox_todo_field_ok(t, s, selected, got); \
131 listbox_todo_field_ok(t, s, anchor, got); \
132 listbox_todo_field_ok(t, s, caret, got); \
133 listbox_todo_field_ok(t, s, selcount, got)
135 static void
136 check (const struct listbox_test test)
138 struct listbox_stat answer;
139 HWND hLB=create_listbox (test.prop.add_style, 0);
140 RECT second_item;
141 int i;
142 int res;
144 listbox_query (hLB, &answer);
145 listbox_ok (test, init, answer);
147 SendMessage (hLB, LB_GETITEMRECT, (WPARAM) 1, (LPARAM) &second_item);
148 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
150 listbox_query (hLB, &answer);
151 listbox_ok (test, click, answer);
153 keypress (hLB, VK_DOWN, 0x50, TRUE);
155 listbox_query (hLB, &answer);
156 listbox_ok (test, step, answer);
158 DestroyWindow (hLB);
159 hLB=create_listbox (test.prop.add_style, 0);
161 SendMessage (hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
162 listbox_query (hLB, &answer);
163 listbox_ok (test, sel, answer);
165 for (i=0;i<4;i++) {
166 DWORD size = SendMessage (hLB, LB_GETTEXTLEN, i, 0);
167 CHAR *txt;
168 WCHAR *txtw;
169 int resA, resW;
171 txt = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, size+1);
172 resA=SendMessageA(hLB, LB_GETTEXT, i, (LPARAM)txt);
173 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
175 txtw = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, 2*size+2);
176 resW=SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
177 if (resA != resW) {
178 trace("SendMessageW(LB_GETTEXT) not supported on this platform (resA=%d resW=%d), skipping...\n",
179 resA, resW);
180 } else {
181 WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL );
182 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
185 HeapFree (GetProcessHeap(), 0, txtw);
186 HeapFree (GetProcessHeap(), 0, txt);
189 /* Confirm the count of items, and that an invalid delete does not remove anything */
190 res = SendMessage (hLB, LB_GETCOUNT, 0, 0);
191 ok((res==4), "Expected 4 items, got %d\n", res);
192 res = SendMessage (hLB, LB_DELETESTRING, -1, 0);
193 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
194 res = SendMessage (hLB, LB_DELETESTRING, 4, 0);
195 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
196 res = SendMessage (hLB, LB_GETCOUNT, 0, 0);
197 ok((res==4), "Expected 4 items, got %d\n", res);
199 WAIT;
200 DestroyWindow (hLB);
203 static void check_item_height(void)
205 HWND hLB;
206 HDC hdc;
207 HFONT font;
208 TEXTMETRIC tm;
209 INT itemHeight;
211 hLB = create_listbox (0, 0);
212 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n");
213 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n");
214 ok (GetTextMetrics( hdc, &tm ), "Can't read font metrics\n");
215 ReleaseDC( hLB, hdc);
217 ok (SendMessage(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
219 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, 0, 0);
220 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight);
222 DestroyWindow (hLB);
224 hLB = CreateWindow ("LISTBOX", "TestList", LBS_OWNERDRAWVARIABLE,
225 0, 0, 100, 100, NULL, NULL, NULL, 0);
226 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, 0, 0);
227 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
228 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, 5, 0);
229 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
230 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, -5, 0);
231 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
232 DestroyWindow (hLB);
235 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
237 switch (msg)
239 case WM_DRAWITEM:
241 RECT rc_item, rc_client, rc_clip;
242 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
244 trace("%p WM_DRAWITEM %08lx %08lx\n", hwnd, wparam, lparam);
246 ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
247 wparam, dis->CtlID);
248 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
250 GetClientRect(dis->hwndItem, &rc_client);
251 trace("hwndItem %p client rect (%d,%d-%d,%d)\n", dis->hwndItem,
252 rc_client.left, rc_client.top, rc_client.right, rc_client.bottom);
253 GetClipBox(dis->hDC, &rc_clip);
254 trace("clip rect (%d,%d-%d,%d)\n", rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
255 ok(EqualRect(&rc_client, &rc_clip), "client rect of the listbox should be equal to the clip box\n");
257 trace("rcItem (%d,%d-%d,%d)\n", dis->rcItem.left, dis->rcItem.top,
258 dis->rcItem.right, dis->rcItem.bottom);
259 SendMessage(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
260 trace("item rect (%d,%d-%d,%d)\n", rc_item.left, rc_item.top, rc_item.right, rc_item.bottom);
261 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
263 break;
266 default:
267 break;
270 return DefWindowProc(hwnd, msg, wparam, lparam);
273 static void test_ownerdraw(void)
275 WNDCLASS cls;
276 HWND parent, hLB;
277 INT ret;
278 RECT rc;
280 cls.style = 0;
281 cls.lpfnWndProc = main_window_proc;
282 cls.cbClsExtra = 0;
283 cls.cbWndExtra = 0;
284 cls.hInstance = GetModuleHandle(0);
285 cls.hIcon = 0;
286 cls.hCursor = LoadCursor(0, (LPSTR)IDC_ARROW);
287 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
288 cls.lpszMenuName = NULL;
289 cls.lpszClassName = "main_window_class";
290 assert(RegisterClass(&cls));
292 parent = CreateWindowEx(0, "main_window_class", NULL,
293 WS_POPUP | WS_VISIBLE,
294 100, 100, 400, 400,
295 GetDesktopWindow(), 0,
296 GetModuleHandle(0), NULL);
297 assert(parent);
299 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
300 assert(hLB);
302 UpdateWindow(hLB);
304 /* make height short enough */
305 SendMessage(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
306 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
307 SWP_NOZORDER | SWP_NOMOVE);
309 /* make 0 item invisible */
310 SendMessage(hLB, LB_SETTOPINDEX, 1, 0);
311 ret = SendMessage(hLB, LB_GETTOPINDEX, 0, 0);
312 ok(ret == 1, "wrong top index %d\n", ret);
314 SendMessage(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
315 trace("item 0 rect (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom);
316 ok(!IsRectEmpty(&rc), "empty item rect\n");
317 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
319 DestroyWindow(hLB);
320 DestroyWindow(parent);
323 #define listbox_test_query(exp, got) \
324 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
325 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
326 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
327 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
329 static void test_selection(void)
331 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
332 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
333 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
334 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
335 HWND hLB;
336 struct listbox_stat answer;
337 INT ret;
339 trace("testing LB_SELITEMRANGE\n");
341 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
342 assert(hLB);
344 listbox_query(hLB, &answer);
345 listbox_test_query(test_nosel, answer);
347 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
348 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
349 listbox_query(hLB, &answer);
350 listbox_test_query(test_1, answer);
352 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
353 listbox_query(hLB, &answer);
354 listbox_test_query(test_nosel, answer);
356 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
357 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
358 listbox_query(hLB, &answer);
359 listbox_test_query(test_3, answer);
361 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
362 listbox_query(hLB, &answer);
363 listbox_test_query(test_nosel, answer);
365 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
366 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
367 listbox_query(hLB, &answer);
368 listbox_test_query(test_nosel, answer);
370 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
371 listbox_query(hLB, &answer);
372 listbox_test_query(test_nosel, answer);
374 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
375 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
376 listbox_query(hLB, &answer);
377 listbox_test_query(test_1, answer);
379 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
380 listbox_query(hLB, &answer);
381 listbox_test_query(test_nosel, answer);
383 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
384 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
385 listbox_query(hLB, &answer);
386 listbox_test_query(test_nosel, answer);
388 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
389 listbox_query(hLB, &answer);
390 listbox_test_query(test_nosel, answer);
392 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
393 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
394 listbox_query(hLB, &answer);
395 listbox_test_query(test_2, answer);
397 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
398 listbox_query(hLB, &answer);
399 listbox_test_query(test_nosel, answer);
401 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
402 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
403 listbox_query(hLB, &answer);
404 listbox_test_query(test_2, answer);
406 DestroyWindow(hLB);
409 static void test_listbox_height(void)
411 HWND hList;
412 int r, id;
414 hList = CreateWindow( "ListBox", "list test", 0,
415 1, 1, 600, 100, NULL, NULL, NULL, NULL );
416 ok( hList != NULL, "failed to create listbox\n");
418 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
419 ok( id == 0, "item id wrong\n");
421 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
422 ok( r == 0, "send message failed\n");
424 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
425 ok( r == 20, "height wrong\n");
427 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
428 ok( r == -1, "send message failed\n");
430 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
431 ok( r == 20, "height wrong\n");
433 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
434 ok( r == -1, "send message failed\n");
436 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
437 ok( r == 20, "height wrong\n");
439 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
440 ok( r == 0, "send message failed\n");
442 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
443 ok( r == 0xff, "height wrong\n");
445 DestroyWindow( hList );
448 static void test_itemfrompoint(void)
450 /* WS_POPUP is required in order to have a more accurate size calculation (
451 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
452 behavior of partially-displayed item.
454 HWND hList = CreateWindow( "ListBox", "list test",
455 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
456 1, 1, 600, 100, NULL, NULL, NULL, NULL );
457 LONG r, id;
458 RECT rc;
460 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000 */
461 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
462 ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r );
464 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
465 ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r );
467 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
468 ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r );
470 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
471 ok( id == 0, "item id wrong\n");
472 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
473 ok( id == 1, "item id wrong\n");
475 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
476 ok( r == 0x1, "ret %x\n", r );
478 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
479 ok( r == 0x10001, "ret %x\n", r );
481 /* Resize control so that below assertions about sizes are valid */
482 r = SendMessage( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
483 ok( r == 1, "ret %x\n", r);
484 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
485 ok( r != 0, "ret %x\n", r);
487 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
488 ok( id == 2, "item id wrong\n");
489 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
490 ok( id == 3, "item id wrong\n");
491 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
492 ok( id == 4, "item id wrong\n");
493 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
494 ok( id == 5, "item id wrong\n");
495 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
496 ok( id == 6, "item id wrong\n");
497 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
498 ok( id == 7, "item id wrong\n");
500 /* Set the listbox up so that id 1 is at the top, this leaves 5
501 partially visible at the bottom and 6, 7 are invisible */
503 SendMessage( hList, LB_SETTOPINDEX, 1, 0);
504 r = SendMessage( hList, LB_GETTOPINDEX, 0, 0);
505 ok( r == 1, "top %d\n", r);
507 r = SendMessage( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
508 ok( r == 1, "ret %x\n", r);
509 r = SendMessage( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
510 ok( r == 0, "ret %x\n", r);
512 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
513 ok( r == 1, "ret %x\n", r);
515 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
516 ok( r == 0x10001, "ret %x\n", r );
518 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
519 ok( r == 0x10001, "ret %x\n", r );
521 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
522 ok( r == 0x10005, "item %x\n", r );
524 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
525 ok( r == 0x10005, "item %x\n", r );
527 DestroyWindow( hList );
530 static void test_listbox_item_data(void)
532 HWND hList;
533 int r, id;
535 hList = CreateWindow( "ListBox", "list test", 0,
536 1, 1, 600, 100, NULL, NULL, NULL, NULL );
537 ok( hList != NULL, "failed to create listbox\n");
539 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
540 ok( id == 0, "item id wrong\n");
542 r = SendMessage( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
543 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
545 r = SendMessage( hList, LB_GETITEMDATA, 0, 0);
546 ok( r == 20, "get item data failed\n");
548 DestroyWindow( hList );
551 static void test_listbox_LB_DIR()
553 HWND hList;
554 int res, itemCount;
555 int itemCount_justFiles;
556 int itemCount_justDrives;
557 int itemCount_allFiles;
558 int i;
559 char pathBuffer[MAX_PATH];
560 char * p;
561 char driveletter;
562 HANDLE file;
564 file = CreateFileA( "wtest1.tmp.c", FILE_ALL_ACCESS, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
565 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
566 CloseHandle( file );
568 /* NOTE: for this test to succeed, there must be no subdirectories
569 under the current directory. In addition, there must be at least
570 one file that fits the wildcard w*.c . Normally, the test
571 directory itself satisfies both conditions.
573 hList = CreateWindow( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
574 1, 1, 600, 100, NULL, NULL, NULL, NULL );
575 assert(hList);
577 /* Test for standard usage */
579 /* This should list all the files in the test directory. */
580 strcpy(pathBuffer, "*");
581 SendMessage(hList, LB_RESETCONTENT, 0, 0);
582 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
583 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
585 /* There should be some content in the listbox */
586 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
587 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
588 itemCount_allFiles = itemCount;
589 ok(res + 1 == itemCount,
590 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
591 itemCount - 1, res);
593 /* This tests behavior when no files match the wildcard */
594 strcpy(pathBuffer, "*.txt");
595 SendMessage(hList, LB_RESETCONTENT, 0, 0);
596 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
597 ok (res == -1, "SendMessage(LB_DIR, 0, *.txt) returned %d, expected -1\n", res);
599 /* There should be NO content in the listbox */
600 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
601 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
604 /* This should list all the w*.c files in the test directory
605 * As of this writing, this includes win.c, winstation.c, wsprintf.c
607 strcpy(pathBuffer, "w*.c");
608 SendMessage(hList, LB_RESETCONTENT, 0, 0);
609 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
610 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
612 /* Path specification does NOT converted to uppercase */
613 ok (!strcmp(pathBuffer, "w*.c"),
614 "expected no change to pathBuffer, got %s\n", pathBuffer);
616 /* There should be some content in the listbox */
617 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
618 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
619 itemCount_justFiles = itemCount;
620 ok(res + 1 == itemCount,
621 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
622 itemCount - 1, res);
624 /* Every single item in the control should start with a w and end in .c */
625 for (i = 0; i < itemCount; i++) {
626 memset(pathBuffer, 0, MAX_PATH);
627 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
628 p = pathBuffer + strlen(pathBuffer);
629 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
630 (*(p-1) == 'c' || *(p-1) == 'C') &&
631 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
634 /* Test DDL_DIRECTORY */
635 strcpy(pathBuffer, "*");
636 SendMessage(hList, LB_RESETCONTENT, 0, 0);
637 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
638 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
640 /* There should be some content in the listbox.
641 * All files plus "[..]"
643 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
644 ok (itemCount == itemCount_allFiles + 1,
645 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected %d\n",
646 itemCount, itemCount_allFiles + 1);
647 ok(res + 1 == itemCount,
648 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
649 itemCount - 1, res);
651 /* This tests behavior when no files match the wildcard */
652 strcpy(pathBuffer, "*.txt");
653 SendMessage(hList, LB_RESETCONTENT, 0, 0);
654 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
655 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, *.txt) returned %d, expected -1\n", res);
657 /* There should be NO content in the listbox */
658 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
659 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
662 /* Test DDL_DIRECTORY */
663 strcpy(pathBuffer, "w*.c");
664 SendMessage(hList, LB_RESETCONTENT, 0, 0);
665 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
666 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
668 /* There should be some content in the listbox. Since the parent directory does not
669 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
671 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
672 ok (itemCount == itemCount_justFiles,
673 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
674 itemCount, itemCount_justFiles);
675 ok(res + 1 == itemCount,
676 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
677 itemCount - 1, res);
679 /* Every single item in the control should start with a w and end in .c. */
680 for (i = 0; i < itemCount; i++) {
681 memset(pathBuffer, 0, MAX_PATH);
682 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
683 p = pathBuffer + strlen(pathBuffer);
685 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
686 (*(p-1) == 'c' || *(p-1) == 'C') &&
687 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
691 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
692 strcpy(pathBuffer, "*");
693 SendMessage(hList, LB_RESETCONTENT, 0, 0);
694 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
695 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
697 /* There should be some content in the listbox. In particular, there should
698 * be at least one element before, since the string "[-c-]" should
699 * have been added. Depending on the user setting, more drives might have
700 * been added.
702 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
703 ok (itemCount >= 1,
704 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
705 itemCount, 1);
706 itemCount_justDrives = itemCount;
707 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
709 /* Every single item in the control should fit the format [-c-] */
710 for (i = 0; i < itemCount; i++) {
711 memset(pathBuffer, 0, MAX_PATH);
712 driveletter = '\0';
713 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
714 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
715 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
716 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
717 if (!(driveletter >= 'a' && driveletter <= 'z')) {
718 /* Correct after invalid entry is found */
719 trace("removing count of invalid entry %s\n", pathBuffer);
720 itemCount_justDrives--;
724 /* This tests behavior when no files match the wildcard */
725 strcpy(pathBuffer, "*.txt");
726 SendMessage(hList, LB_RESETCONTENT, 0, 0);
727 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
728 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *.txt) returned %d, expected %d\n",
729 res, itemCount_justDrives -1);
731 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
732 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
733 itemCount, itemCount_justDrives);
735 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
736 itemCount_justFiles, itemCount_justDrives);
738 /* Test DDL_DRIVES. */
739 strcpy(pathBuffer, "*");
740 SendMessage(hList, LB_RESETCONTENT, 0, 0);
741 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
742 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
744 /* There should be some content in the listbox. In particular, there should
745 * be at least one element before, since the string "[-c-]" should
746 * have been added. Depending on the user setting, more drives might have
747 * been added.
749 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
750 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
751 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
752 itemCount, itemCount_justDrives + itemCount_allFiles);
753 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
755 /* This tests behavior when no files match the wildcard */
756 strcpy(pathBuffer, "*.txt");
757 SendMessage(hList, LB_RESETCONTENT, 0, 0);
758 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
759 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, *.txt) returned %d, expected %d\n",
760 res, itemCount_justDrives -1);
762 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
763 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
766 /* Test DDL_DRIVES. */
767 strcpy(pathBuffer, "w*.c");
768 SendMessage(hList, LB_RESETCONTENT, 0, 0);
769 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
770 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
772 /* There should be some content in the listbox. In particular, there should
773 * be at least one element before, since the string "[-c-]" should
774 * have been added. Depending on the user setting, more drives might have
775 * been added.
777 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
778 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
779 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
780 itemCount, itemCount_justDrives + itemCount_justFiles);
781 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
783 /* Every single item in the control should fit the format [-c-], or w*.c */
784 for (i = 0; i < itemCount; i++) {
785 memset(pathBuffer, 0, MAX_PATH);
786 driveletter = '\0';
787 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
788 p = pathBuffer + strlen(pathBuffer);
789 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
790 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
791 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
792 } else {
794 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
795 (*(p-1) == 'c' || *(p-1) == 'C') &&
796 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
801 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
802 strcpy(pathBuffer, "*");
803 SendMessage(hList, LB_RESETCONTENT, 0, 0);
804 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
805 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
807 /* There should be some content in the listbox. In particular, there should
808 * be exactly the number of plain files, plus the number of mapped drives.
810 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
811 ok (itemCount == itemCount_allFiles + itemCount_justDrives + 1,
812 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
813 itemCount, itemCount_allFiles + itemCount_justDrives + 1);
814 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
816 /* Every single item in the control should start with a w and end in .c,
817 * except for the "[..]" string, which should appear exactly as it is,
818 * and the mapped drives in the format "[-X-]".
820 for (i = 0; i < itemCount; i++) {
821 memset(pathBuffer, 0, MAX_PATH);
822 driveletter = '\0';
823 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
824 p = pathBuffer + strlen(pathBuffer);
825 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
826 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
830 /* This tests behavior when no files match the wildcard */
831 strcpy(pathBuffer, "*.txt");
832 SendMessage(hList, LB_RESETCONTENT, 0, 0);
833 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
834 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *.txt) returned %d, expected %d\n",
835 res, itemCount_justDrives -1);
837 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
838 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
842 /* Test DDL_DIRECTORY|DDL_DRIVES. */
843 strcpy(pathBuffer, "w*.c");
844 SendMessage(hList, LB_RESETCONTENT, 0, 0);
845 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
846 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
848 /* There should be some content in the listbox. In particular, there should
849 * be exactly the number of plain files, plus the number of mapped drives.
851 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
852 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
853 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
854 itemCount, itemCount_justFiles + itemCount_justDrives);
855 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
857 /* Every single item in the control should start with a w and end in .c,
858 * except the mapped drives in the format "[-X-]". The "[..]" directory
859 * should not appear.
861 for (i = 0; i < itemCount; i++) {
862 memset(pathBuffer, 0, MAX_PATH);
863 driveletter = '\0';
864 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
865 p = pathBuffer + strlen(pathBuffer);
866 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
867 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
868 } else {
870 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
871 (*(p-1) == 'c' || *(p-1) == 'C') &&
872 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
876 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
877 strcpy(pathBuffer, "*");
878 SendMessage(hList, LB_RESETCONTENT, 0, 0);
879 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
880 ok (res == 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
882 /* There should be exactly one element: "[..]" */
883 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
884 ok (itemCount == 1,
885 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
886 itemCount, 1);
887 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
889 memset(pathBuffer, 0, MAX_PATH);
890 SendMessage(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
891 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
893 /* This tests behavior when no files match the wildcard */
894 strcpy(pathBuffer, "*.txt");
895 SendMessage(hList, LB_RESETCONTENT, 0, 0);
896 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
897 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *.txt) returned %d, expected %d\n",
898 res, -1);
900 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
901 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
904 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
905 strcpy(pathBuffer, "w*.c");
906 SendMessage(hList, LB_RESETCONTENT, 0, 0);
907 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
908 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
910 /* There should be no elements, since "[..]" does not fit w*.c */
911 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
912 ok (itemCount == 0,
913 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
914 itemCount, 0);
916 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
917 strcpy(pathBuffer, "*");
918 SendMessage(hList, LB_RESETCONTENT, 0, 0);
919 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
920 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
922 /* There should be no plain files on the listbox */
923 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
924 ok (itemCount == itemCount_justDrives + 1,
925 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
926 itemCount, itemCount_justDrives + 1);
927 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
929 for (i = 0; i < itemCount; i++) {
930 memset(pathBuffer, 0, MAX_PATH);
931 driveletter = '\0';
932 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
933 p = pathBuffer + strlen(pathBuffer);
934 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
935 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
936 } else {
937 ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit expected [..]\n", i, pathBuffer);
941 /* This tests behavior when no files match the wildcard */
942 strcpy(pathBuffer, "*.txt");
943 SendMessage(hList, LB_RESETCONTENT, 0, 0);
944 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
945 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, *.txt) returned %d, expected %d\n",
946 res, itemCount_justDrives -1);
948 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
949 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
951 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
952 strcpy(pathBuffer, "w*.c");
953 SendMessage(hList, LB_RESETCONTENT, 0, 0);
954 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
955 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
957 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
958 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
959 ok (itemCount == itemCount_justDrives,
960 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
961 itemCount, itemCount_justDrives);
962 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
964 for (i = 0; i < itemCount; i++) {
965 memset(pathBuffer, 0, MAX_PATH);
966 driveletter = '\0';
967 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
968 p = pathBuffer + strlen(pathBuffer);
969 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
970 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
972 DestroyWindow(hList);
974 DeleteFileA( "wtest1.tmp.c" );
977 HWND g_listBox;
978 HWND g_label;
980 #define ID_TEST_LABEL 1001
981 #define ID_TEST_LISTBOX 1002
983 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCT lpcs)
985 g_label = CreateWindow(
986 "Static",
987 "Contents of static control before DlgDirList.",
988 WS_CHILD | WS_VISIBLE,
989 10, 10, 512, 32,
990 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
991 if (!g_label) return FALSE;
992 g_listBox = CreateWindow(
993 "ListBox",
994 "DlgDirList test",
995 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
996 10, 60, 256, 256,
997 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
998 if (!g_listBox) return FALSE;
1000 return TRUE;
1003 static LRESULT CALLBACK listbox_container_window_procA (
1004 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1006 LRESULT result = 0;
1008 switch (uiMsg) {
1009 case WM_DESTROY:
1010 PostQuitMessage(0);
1011 break;
1012 case WM_CREATE:
1013 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1014 ? 0 : (LRESULT)-1;
1015 break;
1016 default:
1017 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1018 break;
1020 return result;
1023 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1025 WNDCLASSA cls;
1027 cls.style = 0;
1028 cls.cbClsExtra = 0;
1029 cls.cbWndExtra = 0;
1030 cls.hInstance = hInst;
1031 cls.hIcon = NULL;
1032 cls.hCursor = LoadCursorA (NULL, IDC_ARROW);
1033 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1034 cls.lpszMenuName = NULL;
1035 cls.lpfnWndProc = listbox_container_window_procA;
1036 cls.lpszClassName = "ListboxContainerClass";
1037 if (!RegisterClassA (&cls)) return FALSE;
1039 return TRUE;
1042 static void test_listbox_dlgdir(void)
1044 HINSTANCE hInst;
1045 HWND hWnd;
1046 int res, itemCount;
1047 int itemCount_justFiles;
1048 int itemCount_justDrives;
1049 int i;
1050 char pathBuffer[MAX_PATH];
1051 char itemBuffer[MAX_PATH];
1052 char tempBuffer[MAX_PATH];
1053 char * p;
1054 char driveletter;
1055 HANDLE file;
1057 file = CreateFileA( "wtest1.tmp.c", FILE_ALL_ACCESS, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1058 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1059 CloseHandle( file );
1061 /* NOTE: for this test to succeed, there must be no subdirectories
1062 under the current directory. In addition, there must be at least
1063 one file that fits the wildcard w*.c . Normally, the test
1064 directory itself satisfies both conditions.
1067 hInst = GetModuleHandleA(0);
1068 if (!RegisterListboxWindowClass(hInst)) assert(0);
1069 hWnd = CreateWindow("ListboxContainerClass", "ListboxContainerClass",
1070 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1071 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1072 NULL, NULL, hInst, 0);
1073 assert(hWnd);
1075 /* Test for standard usage */
1077 /* The following should be overwritten by the directory path */
1078 SendMessage(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1080 /* This should list all the w*.c files in the test directory
1081 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1083 strcpy(pathBuffer, "w*.c");
1084 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1085 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1087 /* Path specification gets converted to uppercase */
1088 ok (!strcmp(pathBuffer, "W*.C"),
1089 "expected conversion to uppercase, got %s\n", pathBuffer);
1091 /* Loaded path should have overwritten the label text */
1092 SendMessage(g_label, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)pathBuffer);
1093 trace("Static control after DlgDirList: %s\n", pathBuffer);
1094 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1096 /* There should be some content in the listbox */
1097 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1098 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1099 itemCount_justFiles = itemCount;
1101 /* Every single item in the control should start with a w and end in .c */
1102 for (i = 0; i < itemCount; i++) {
1103 memset(pathBuffer, 0, MAX_PATH);
1104 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1105 p = pathBuffer + strlen(pathBuffer);
1106 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1107 (*(p-1) == 'c' || *(p-1) == 'C') &&
1108 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1111 /* Test behavior when no files match the wildcard */
1112 strcpy(pathBuffer, "*.txt");
1113 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1114 ok (res == 1, "DlgDirList(*.txt, 0) returned %d expected 1\n", res);
1116 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1117 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1119 /* Test DDL_DIRECTORY */
1120 strcpy(pathBuffer, "w*.c");
1121 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1122 DDL_DIRECTORY);
1123 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1125 /* There should be some content in the listbox. In particular, there should
1126 * be exactly one more element than before, since the string "[..]" should
1127 * have been added.
1129 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1130 ok (itemCount == itemCount_justFiles + 1,
1131 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected %d\n",
1132 itemCount, itemCount_justFiles + 1);
1134 /* Every single item in the control should start with a w and end in .c,
1135 * except for the "[..]" string, which should appear exactly as it is.
1137 for (i = 0; i < itemCount; i++) {
1138 memset(pathBuffer, 0, MAX_PATH);
1139 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1140 p = pathBuffer + strlen(pathBuffer);
1141 ok( !strcmp(pathBuffer, "[..]") ||
1142 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1143 (*(p-1) == 'c' || *(p-1) == 'C') &&
1144 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1147 /* Test behavior when no files match the wildcard */
1148 strcpy(pathBuffer, "*.txt");
1149 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1150 DDL_DIRECTORY);
1151 ok (res == 1, "DlgDirList(*.txt, DDL_DIRECTORY) returned %d expected 1\n", res);
1153 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1154 ok (itemCount == 1, "DlgDirList() incorrectly filled the listbox! (expected 1 got %d)\n",
1155 itemCount);
1156 for (i = 0; i < itemCount; i++) {
1157 memset(pathBuffer, 0, MAX_PATH);
1158 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1159 p = pathBuffer + strlen(pathBuffer);
1160 ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit requested [..]\n", i, pathBuffer);
1164 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1165 strcpy(pathBuffer, "w*.c");
1166 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1167 DDL_DRIVES);
1168 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1170 /* There should be some content in the listbox. In particular, there should
1171 * be at least one element before, since the string "[-c-]" should
1172 * have been added. Depending on the user setting, more drives might have
1173 * been added.
1175 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1176 ok (itemCount >= 1,
1177 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1178 itemCount, 1);
1179 itemCount_justDrives = itemCount;
1181 /* Every single item in the control should fit the format [-c-] */
1182 for (i = 0; i < itemCount; i++) {
1183 memset(pathBuffer, 0, MAX_PATH);
1184 driveletter = '\0';
1185 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1186 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1187 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1188 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1189 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1190 /* Correct after invalid entry is found */
1191 trace("removing count of invalid entry %s\n", pathBuffer);
1192 itemCount_justDrives--;
1196 /* Test behavior when no files match the wildcard */
1197 strcpy(pathBuffer, "*.txt");
1198 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1199 DDL_DRIVES);
1200 ok (res == 1, "DlgDirList(*.txt, DDL_DRIVES) returned %d expected 1\n", res);
1202 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1203 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1206 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1207 strcpy(pathBuffer, "w*.c");
1208 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1209 DDL_DIRECTORY|DDL_DRIVES);
1210 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1212 /* There should be some content in the listbox. In particular, there should
1213 * be exactly the number of plain files, plus the number of mapped drives,
1214 * plus one "[..]"
1216 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1217 ok (itemCount == itemCount_justFiles + itemCount_justDrives + 1,
1218 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1219 itemCount, itemCount_justFiles + itemCount_justDrives + 1);
1221 /* Every single item in the control should start with a w and end in .c,
1222 * except for the "[..]" string, which should appear exactly as it is,
1223 * and the mapped drives in the format "[-X-]".
1225 for (i = 0; i < itemCount; i++) {
1226 memset(pathBuffer, 0, MAX_PATH);
1227 driveletter = '\0';
1228 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1229 p = pathBuffer + strlen(pathBuffer);
1230 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1231 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1232 } else {
1233 ok( !strcmp(pathBuffer, "[..]") ||
1234 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1235 (*(p-1) == 'c' || *(p-1) == 'C') &&
1236 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1240 /* Test behavior when no files match the wildcard */
1241 strcpy(pathBuffer, "*.txt");
1242 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1243 DDL_DIRECTORY|DDL_DRIVES);
1244 ok (res == 1, "DlgDirList(*.txt, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", res);
1246 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1247 ok (itemCount == itemCount_justDrives + 1,
1248 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1249 itemCount_justDrives + 1, itemCount);
1253 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1254 strcpy(pathBuffer, "w*.c");
1255 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1256 DDL_DIRECTORY|DDL_EXCLUSIVE);
1257 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1259 /* There should be exactly one element: "[..]" */
1260 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1261 ok (itemCount == 1,
1262 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1263 itemCount, 1);
1265 memset(pathBuffer, 0, MAX_PATH);
1266 SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1267 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1270 /* Test behavior when no files match the wildcard */
1271 strcpy(pathBuffer, "*.txt");
1272 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1273 DDL_DIRECTORY|DDL_EXCLUSIVE);
1274 ok (res == 1, "DlgDirList(*.txt, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", res);
1276 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1277 ok (itemCount == 1, "DlgDirList() incorrectly filled the listbox!\n");
1280 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1281 strcpy(pathBuffer, "w*.c");
1282 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1283 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1284 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1286 /* There should be no plain files on the listbox */
1287 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1288 ok (itemCount == itemCount_justDrives + 1,
1289 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1290 itemCount, itemCount_justDrives + 1);
1292 for (i = 0; i < itemCount; i++) {
1293 memset(pathBuffer, 0, MAX_PATH);
1294 driveletter = '\0';
1295 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1296 p = pathBuffer + strlen(pathBuffer);
1297 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1298 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1299 } else {
1300 ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit expected [..]\n", i, pathBuffer);
1304 /* Test behavior when no files match the wildcard */
1305 strcpy(pathBuffer, "*.txt");
1306 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1307 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1308 ok (res == 1, "DlgDirList(*.txt, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", res);
1310 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1311 ok (itemCount == itemCount_justDrives + 1, "DlgDirList() incorrectly filled the listbox!\n");
1314 /* Now test DlgDirSelectEx() in normal operation */
1315 /* Fill with everything - drives, directory and all plain files. */
1316 strcpy(pathBuffer, "*");
1317 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1318 DDL_DIRECTORY|DDL_DRIVES);
1319 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1321 SendMessage(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1322 memset(pathBuffer, 0, MAX_PATH);
1323 SetLastError(0xdeadbeef);
1324 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1325 ok (GetLastError() == 0xdeadbeef,
1326 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1327 GetLastError());
1328 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1329 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1331 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1333 /* Test proper drive/dir/file recognition */
1334 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1335 for (i = 0; i < itemCount; i++) {
1336 memset(itemBuffer, 0, MAX_PATH);
1337 memset(pathBuffer, 0, MAX_PATH);
1338 memset(tempBuffer, 0, MAX_PATH);
1339 driveletter = '\0';
1340 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1341 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1342 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1343 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1344 /* Current item is a drive letter */
1345 SetLastError(0xdeadbeef);
1346 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1347 ok (GetLastError() == 0xdeadbeef,
1348 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1349 i, GetLastError());
1350 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1352 /* For drive letters, DlgDirSelectEx tacks on a colon */
1353 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1354 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1355 } else if (itemBuffer[0] == '[') {
1356 /* Current item is the parent directory */
1357 SetLastError(0xdeadbeef);
1358 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1359 ok (GetLastError() == 0xdeadbeef,
1360 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1361 i, GetLastError());
1362 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1364 /* For directories, DlgDirSelectEx tacks on a backslash */
1365 p = pathBuffer + strlen(pathBuffer);
1366 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1368 tempBuffer[0] = '[';
1369 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1370 strcat(tempBuffer, "]");
1371 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1372 } else {
1373 /* Current item is a plain file */
1374 SetLastError(0xdeadbeef);
1375 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1376 ok (GetLastError() == 0xdeadbeef,
1377 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1378 i, GetLastError());
1379 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1381 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1382 * for example, "Makefile", which gets reported as "Makefile."
1384 strcpy(tempBuffer, itemBuffer);
1385 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1386 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1390 /* Now test DlgDirSelectEx() in abnormal operation */
1391 /* Fill list with bogus entries, that look somewhat valid */
1392 SendMessage(g_listBox, LB_RESETCONTENT, 0, 0);
1393 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1394 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1395 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1396 for (i = 0; i < itemCount; i++) {
1397 memset(itemBuffer, 0, MAX_PATH);
1398 memset(pathBuffer, 0, MAX_PATH);
1399 memset(tempBuffer, 0, MAX_PATH);
1400 driveletter = '\0';
1401 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1402 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1403 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1404 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1405 /* Current item is a drive letter */
1406 SetLastError(0xdeadbeef);
1407 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1408 ok (GetLastError() == 0xdeadbeef,
1409 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1410 i, GetLastError());
1411 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1413 /* For drive letters, DlgDirSelectEx tacks on a colon */
1414 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1415 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1416 } else if (itemBuffer[0] == '[') {
1417 /* Current item is the parent directory */
1418 SetLastError(0xdeadbeef);
1419 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1420 ok (GetLastError() == 0xdeadbeef,
1421 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1422 i, GetLastError());
1423 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1425 /* For directories, DlgDirSelectEx tacks on a backslash */
1426 p = pathBuffer + strlen(pathBuffer);
1427 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1429 tempBuffer[0] = '[';
1430 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1431 strcat(tempBuffer, "]");
1432 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1433 } else {
1434 /* Current item is a plain file */
1435 SetLastError(0xdeadbeef);
1436 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1437 ok (GetLastError() == 0xdeadbeef,
1438 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1439 i, GetLastError());
1440 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1442 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1443 * This affects for example, "Makefile", which gets reported as "Makefile."
1445 strcpy(tempBuffer, itemBuffer);
1446 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1447 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1450 DestroyWindow(hWnd);
1452 DeleteFileA( "wtest1.tmp.c" );
1455 START_TEST(listbox)
1457 const struct listbox_test SS =
1458 /* {add_style} */
1459 {{0},
1460 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1461 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1462 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1463 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1464 /* {selected, anchor, caret, selcount}{TODO fields} */
1465 const struct listbox_test SS_NS =
1466 {{LBS_NOSEL},
1467 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1468 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1469 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1470 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1471 const struct listbox_test MS =
1472 {{LBS_MULTIPLESEL},
1473 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1474 { 1, 1, 1, 1}, {0,0,0,0},
1475 { 2, 1, 2, 1}, {0,0,0,0},
1476 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1477 const struct listbox_test MS_NS =
1478 {{LBS_MULTIPLESEL | LBS_NOSEL},
1479 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1480 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1481 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1482 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1483 const struct listbox_test ES =
1484 {{LBS_EXTENDEDSEL},
1485 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1486 { 1, 1, 1, 1}, {0,0,0,0},
1487 { 2, 2, 2, 1}, {0,0,0,0},
1488 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1489 const struct listbox_test ES_NS =
1490 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1491 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1492 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1493 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1494 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1495 const struct listbox_test EMS =
1496 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1497 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1498 { 1, 1, 1, 1}, {0,0,0,0},
1499 { 2, 2, 2, 1}, {0,0,0,0},
1500 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1501 const struct listbox_test EMS_NS =
1502 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1503 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1504 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1505 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1506 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1508 trace (" Testing single selection...\n");
1509 check (SS);
1510 trace (" ... with NOSEL\n");
1511 check (SS_NS);
1512 trace (" Testing multiple selection...\n");
1513 check (MS);
1514 trace (" ... with NOSEL\n");
1515 check (MS_NS);
1516 trace (" Testing extended selection...\n");
1517 check (ES);
1518 trace (" ... with NOSEL\n");
1519 check (ES_NS);
1520 trace (" Testing extended and multiple selection...\n");
1521 check (EMS);
1522 trace (" ... with NOSEL\n");
1523 check (EMS_NS);
1525 check_item_height();
1526 test_ownerdraw();
1527 test_selection();
1528 test_listbox_height();
1529 test_itemfrompoint();
1530 test_listbox_item_data();
1531 test_listbox_LB_DIR();
1532 test_listbox_dlgdir();