ole32: Use interface macros to call methods.
[wine/multimedia.git] / dlls / user32 / tests / listbox.c
blob4be760471d038d4e33351f3a20736e382d8f9b2e
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 const char BAD_EXTENSION[] = "*.badtxt";
49 static HWND
50 create_listbox (DWORD add_style, HWND parent)
52 HWND handle;
53 INT_PTR ctl_id=0;
54 if (parent)
55 ctl_id=1;
56 handle=CreateWindow ("LISTBOX", "TestList",
57 (LBS_STANDARD & ~LBS_SORT) | add_style,
58 0, 0, 100, 100,
59 parent, (HMENU)ctl_id, NULL, 0);
61 assert (handle);
62 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) strings[0]);
63 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) strings[1]);
64 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) strings[2]);
65 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) strings[3]);
67 #ifdef VISIBLE
68 ShowWindow (handle, SW_SHOW);
69 #endif
70 REDRAW;
72 return handle;
75 struct listbox_prop {
76 DWORD add_style;
79 struct listbox_stat {
80 int selected, anchor, caret, selcount;
83 struct listbox_test {
84 struct listbox_prop prop;
85 struct listbox_stat init, init_todo;
86 struct listbox_stat click, click_todo;
87 struct listbox_stat step, step_todo;
88 struct listbox_stat sel, sel_todo;
91 static void
92 listbox_query (HWND handle, struct listbox_stat *results)
94 results->selected = SendMessage (handle, LB_GETCURSEL, 0, 0);
95 results->anchor = SendMessage (handle, LB_GETANCHORINDEX, 0, 0);
96 results->caret = SendMessage (handle, LB_GETCARETINDEX, 0, 0);
97 results->selcount = SendMessage (handle, LB_GETSELCOUNT, 0, 0);
100 static void
101 buttonpress (HWND handle, WORD x, WORD y)
103 LPARAM lp=x+(y<<16);
105 WAIT;
106 SendMessage (handle, WM_LBUTTONDOWN, MK_LBUTTON, lp);
107 SendMessage (handle, WM_LBUTTONUP, 0, lp);
108 REDRAW;
111 static void
112 keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
114 LPARAM lp=1+(scancode<<16)+(extended?KEYEVENTF_EXTENDEDKEY:0);
116 WAIT;
117 SendMessage (handle, WM_KEYDOWN, keycode, lp);
118 SendMessage (handle, WM_KEYUP , keycode, lp | 0xc000000);
119 REDRAW;
122 #define listbox_field_ok(t, s, f, got) \
123 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
124 ": expected %d, got %d\n", (unsigned int)t.prop.add_style, \
125 t.s.f, got.f)
127 #define listbox_todo_field_ok(t, s, f, got) \
128 if (t.s##_todo.f) todo_wine { listbox_field_ok(t, s, f, got); } \
129 else listbox_field_ok(t, s, f, got)
131 #define listbox_ok(t, s, got) \
132 listbox_todo_field_ok(t, s, selected, got); \
133 listbox_todo_field_ok(t, s, anchor, got); \
134 listbox_todo_field_ok(t, s, caret, got); \
135 listbox_todo_field_ok(t, s, selcount, got)
137 static void
138 check (const struct listbox_test test)
140 struct listbox_stat answer;
141 HWND hLB=create_listbox (test.prop.add_style, 0);
142 RECT second_item;
143 int i;
144 int res;
146 listbox_query (hLB, &answer);
147 listbox_ok (test, init, answer);
149 SendMessage (hLB, LB_GETITEMRECT, 1, (LPARAM) &second_item);
150 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
152 listbox_query (hLB, &answer);
153 listbox_ok (test, click, answer);
155 keypress (hLB, VK_DOWN, 0x50, TRUE);
157 listbox_query (hLB, &answer);
158 listbox_ok (test, step, answer);
160 DestroyWindow (hLB);
161 hLB=create_listbox (test.prop.add_style, 0);
163 SendMessage (hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
164 listbox_query (hLB, &answer);
165 listbox_ok (test, sel, answer);
167 for (i=0;i<4;i++) {
168 DWORD size = SendMessage (hLB, LB_GETTEXTLEN, i, 0);
169 CHAR *txt;
170 WCHAR *txtw;
171 int resA, resW;
173 txt = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, size+1);
174 resA=SendMessageA(hLB, LB_GETTEXT, i, (LPARAM)txt);
175 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
177 txtw = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, 2*size+2);
178 resW=SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
179 if (resA != resW) {
180 trace("SendMessageW(LB_GETTEXT) not supported on this platform (resA=%d resW=%d), skipping...\n",
181 resA, resW);
182 } else {
183 WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL );
184 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
187 HeapFree (GetProcessHeap(), 0, txtw);
188 HeapFree (GetProcessHeap(), 0, txt);
191 /* Confirm the count of items, and that an invalid delete does not remove anything */
192 res = SendMessage (hLB, LB_GETCOUNT, 0, 0);
193 ok((res==4), "Expected 4 items, got %d\n", res);
194 res = SendMessage (hLB, LB_DELETESTRING, -1, 0);
195 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
196 res = SendMessage (hLB, LB_DELETESTRING, 4, 0);
197 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
198 res = SendMessage (hLB, LB_GETCOUNT, 0, 0);
199 ok((res==4), "Expected 4 items, got %d\n", res);
201 WAIT;
202 DestroyWindow (hLB);
205 static void check_item_height(void)
207 HWND hLB;
208 HDC hdc;
209 HFONT font;
210 TEXTMETRIC tm;
211 INT itemHeight;
213 hLB = create_listbox (0, 0);
214 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n");
215 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n");
216 ok (GetTextMetrics( hdc, &tm ), "Can't read font metrics\n");
217 ReleaseDC( hLB, hdc);
219 ok (SendMessage(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
221 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, 0, 0);
222 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight);
224 DestroyWindow (hLB);
226 hLB = CreateWindow ("LISTBOX", "TestList", LBS_OWNERDRAWVARIABLE,
227 0, 0, 100, 100, NULL, NULL, NULL, 0);
228 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, 0, 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 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, -5, 0);
233 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
234 DestroyWindow (hLB);
237 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
239 switch (msg)
241 case WM_DRAWITEM:
243 RECT rc_item, rc_client, rc_clip;
244 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
246 trace("%p WM_DRAWITEM %08lx %08lx\n", hwnd, wparam, lparam);
248 ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
249 wparam, dis->CtlID);
250 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
252 GetClientRect(dis->hwndItem, &rc_client);
253 trace("hwndItem %p client rect (%d,%d-%d,%d)\n", dis->hwndItem,
254 rc_client.left, rc_client.top, rc_client.right, rc_client.bottom);
255 GetClipBox(dis->hDC, &rc_clip);
256 trace("clip rect (%d,%d-%d,%d)\n", rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
257 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip),
258 "client rect of the listbox should be equal to the clip box,"
259 "or the clip box should be empty\n");
261 trace("rcItem (%d,%d-%d,%d)\n", dis->rcItem.left, dis->rcItem.top,
262 dis->rcItem.right, dis->rcItem.bottom);
263 SendMessage(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
264 trace("item rect (%d,%d-%d,%d)\n", rc_item.left, rc_item.top, rc_item.right, rc_item.bottom);
265 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
267 break;
270 default:
271 break;
274 return DefWindowProc(hwnd, msg, wparam, lparam);
277 static void test_ownerdraw(void)
279 WNDCLASS cls;
280 HWND parent, hLB;
281 INT ret;
282 RECT rc;
284 cls.style = 0;
285 cls.lpfnWndProc = main_window_proc;
286 cls.cbClsExtra = 0;
287 cls.cbWndExtra = 0;
288 cls.hInstance = GetModuleHandle(0);
289 cls.hIcon = 0;
290 cls.hCursor = LoadCursor(0, IDC_ARROW);
291 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
292 cls.lpszMenuName = NULL;
293 cls.lpszClassName = "main_window_class";
294 ok (RegisterClass(&cls), "RegisterClass failed\n");
296 parent = CreateWindowEx(0, "main_window_class", NULL,
297 WS_POPUP | WS_VISIBLE,
298 100, 100, 400, 400,
299 GetDesktopWindow(), 0,
300 GetModuleHandle(0), NULL);
301 assert(parent);
303 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
304 assert(hLB);
306 SetForegroundWindow(hLB);
307 UpdateWindow(hLB);
309 /* make height short enough */
310 SendMessage(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
311 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
312 SWP_NOZORDER | SWP_NOMOVE);
314 /* make 0 item invisible */
315 SendMessage(hLB, LB_SETTOPINDEX, 1, 0);
316 ret = SendMessage(hLB, LB_GETTOPINDEX, 0, 0);
317 ok(ret == 1, "wrong top index %d\n", ret);
319 SendMessage(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
320 trace("item 0 rect (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom);
321 ok(!IsRectEmpty(&rc), "empty item rect\n");
322 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
324 DestroyWindow(hLB);
325 DestroyWindow(parent);
328 #define listbox_test_query(exp, got) \
329 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
330 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
331 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
332 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
334 static void test_selection(void)
336 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
337 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
338 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
339 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
340 HWND hLB;
341 struct listbox_stat answer;
342 INT ret;
344 trace("testing LB_SELITEMRANGE\n");
346 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
347 assert(hLB);
349 listbox_query(hLB, &answer);
350 listbox_test_query(test_nosel, answer);
352 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
353 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
354 listbox_query(hLB, &answer);
355 listbox_test_query(test_1, answer);
357 SendMessage(hLB, LB_SETSEL, FALSE, -1);
358 listbox_query(hLB, &answer);
359 listbox_test_query(test_nosel, answer);
361 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
362 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
363 listbox_query(hLB, &answer);
364 listbox_test_query(test_3, answer);
366 SendMessage(hLB, LB_SETSEL, FALSE, -1);
367 listbox_query(hLB, &answer);
368 listbox_test_query(test_nosel, answer);
370 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
371 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
372 listbox_query(hLB, &answer);
373 listbox_test_query(test_nosel, answer);
375 SendMessage(hLB, LB_SETSEL, FALSE, -1);
376 listbox_query(hLB, &answer);
377 listbox_test_query(test_nosel, answer);
379 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
380 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
381 listbox_query(hLB, &answer);
382 listbox_test_query(test_1, answer);
384 SendMessage(hLB, LB_SETSEL, FALSE, -1);
385 listbox_query(hLB, &answer);
386 listbox_test_query(test_nosel, answer);
388 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
389 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
390 listbox_query(hLB, &answer);
391 listbox_test_query(test_nosel, answer);
393 SendMessage(hLB, LB_SETSEL, FALSE, -1);
394 listbox_query(hLB, &answer);
395 listbox_test_query(test_nosel, answer);
397 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
398 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
399 listbox_query(hLB, &answer);
400 listbox_test_query(test_2, answer);
402 SendMessage(hLB, LB_SETSEL, FALSE, -1);
403 listbox_query(hLB, &answer);
404 listbox_test_query(test_nosel, answer);
406 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
407 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
408 listbox_query(hLB, &answer);
409 listbox_test_query(test_2, answer);
411 DestroyWindow(hLB);
414 static void test_listbox_height(void)
416 HWND hList;
417 int r, id;
419 hList = CreateWindow( "ListBox", "list test", 0,
420 1, 1, 600, 100, NULL, NULL, NULL, NULL );
421 ok( hList != NULL, "failed to create listbox\n");
423 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
424 ok( id == 0, "item id wrong\n");
426 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
427 ok( r == 0, "send message failed\n");
429 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
430 ok( r == 20, "height wrong\n");
432 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
433 ok( r == -1, "send message failed\n");
435 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
436 ok( r == 20, "height wrong\n");
438 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
439 ok( r == -1, "send message failed\n");
441 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
442 ok( r == 20, "height wrong\n");
444 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
445 ok( r == 0, "send message failed\n");
447 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
448 ok( r == 0xff, "height wrong\n");
450 DestroyWindow( hList );
453 static void test_itemfrompoint(void)
455 /* WS_POPUP is required in order to have a more accurate size calculation (
456 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
457 behavior of partially-displayed item.
459 HWND hList = CreateWindow( "ListBox", "list test",
460 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
461 1, 1, 600, 100, NULL, NULL, NULL, NULL );
462 ULONG r, id;
463 RECT rc;
465 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000, nt4 returns 0xffffffff */
466 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
467 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
469 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
470 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
472 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
473 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
475 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
476 ok( id == 0, "item id wrong\n");
477 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
478 ok( id == 1, "item id wrong\n");
480 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
481 ok( r == 0x1, "ret %x\n", r );
483 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
484 ok( r == 0x10001 || broken(r == 1), /* nt4 */
485 "ret %x\n", r );
487 /* Resize control so that below assertions about sizes are valid */
488 r = SendMessage( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
489 ok( r == 1, "ret %x\n", r);
490 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
491 ok( r != 0, "ret %x\n", r);
493 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
494 ok( id == 2, "item id wrong\n");
495 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
496 ok( id == 3, "item id wrong\n");
497 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
498 ok( id == 4, "item id wrong\n");
499 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
500 ok( id == 5, "item id wrong\n");
501 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
502 ok( id == 6, "item id wrong\n");
503 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
504 ok( id == 7, "item id wrong\n");
506 /* Set the listbox up so that id 1 is at the top, this leaves 5
507 partially visible at the bottom and 6, 7 are invisible */
509 SendMessage( hList, LB_SETTOPINDEX, 1, 0);
510 r = SendMessage( hList, LB_GETTOPINDEX, 0, 0);
511 ok( r == 1, "top %d\n", r);
513 r = SendMessage( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
514 ok( r == 1, "ret %x\n", r);
515 r = SendMessage( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
516 ok( r == 0, "ret %x\n", r);
518 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
519 ok( r == 1, "ret %x\n", r);
521 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
522 ok( r == 0x10001 || broken(r == 1), /* nt4 */
523 "ret %x\n", r );
525 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
526 ok( r == 0x10001 || broken(r == 1), /* nt4 */
527 "ret %x\n", r );
529 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
530 ok( r == 0x10005 || broken(r == 5), /* nt4 */
531 "item %x\n", r );
533 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
534 ok( r == 0x10005 || broken(r == 5), /* nt4 */
535 "item %x\n", r );
537 DestroyWindow( hList );
540 static void test_listbox_item_data(void)
542 HWND hList;
543 int r, id;
545 hList = CreateWindow( "ListBox", "list test", 0,
546 1, 1, 600, 100, NULL, NULL, NULL, NULL );
547 ok( hList != NULL, "failed to create listbox\n");
549 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
550 ok( id == 0, "item id wrong\n");
552 r = SendMessage( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
553 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
555 r = SendMessage( hList, LB_GETITEMDATA, 0, 0);
556 ok( r == 20, "get item data failed\n");
558 DestroyWindow( hList );
561 static void test_listbox_LB_DIR(void)
563 HWND hList;
564 int res, itemCount;
565 int itemCount_justFiles;
566 int itemCount_justDrives;
567 int itemCount_allFiles;
568 int itemCount_allDirs;
569 int i;
570 char pathBuffer[MAX_PATH];
571 char * p;
572 char driveletter;
573 const char *wildcard = "*";
574 HANDLE file;
576 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
577 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
578 CloseHandle( file );
580 /* NOTE: for this test to succeed, there must be no subdirectories
581 under the current directory. In addition, there must be at least
582 one file that fits the wildcard w*.c . Normally, the test
583 directory itself satisfies both conditions.
585 hList = CreateWindow( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
586 1, 1, 600, 100, NULL, NULL, NULL, NULL );
587 assert(hList);
589 /* Test for standard usage */
591 /* This should list all the files in the test directory. */
592 strcpy(pathBuffer, wildcard);
593 SendMessage(hList, LB_RESETCONTENT, 0, 0);
594 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
595 if (res == -1) /* "*" wildcard doesn't work on win9x */
597 wildcard = "*.*";
598 strcpy(pathBuffer, wildcard);
599 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
601 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
603 /* There should be some content in the listbox */
604 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
605 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
606 itemCount_allFiles = itemCount;
607 ok(res + 1 == itemCount,
608 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
609 itemCount - 1, res);
611 /* This tests behavior when no files match the wildcard */
612 strcpy(pathBuffer, BAD_EXTENSION);
613 SendMessage(hList, LB_RESETCONTENT, 0, 0);
614 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
615 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
617 /* There should be NO content in the listbox */
618 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
619 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
622 /* This should list all the w*.c files in the test directory
623 * As of this writing, this includes win.c, winstation.c, wsprintf.c
625 strcpy(pathBuffer, "w*.c");
626 SendMessage(hList, LB_RESETCONTENT, 0, 0);
627 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
628 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
630 /* Path specification does NOT converted to uppercase */
631 ok (!strcmp(pathBuffer, "w*.c"),
632 "expected no change to pathBuffer, got %s\n", pathBuffer);
634 /* There should be some content in the listbox */
635 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
636 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
637 itemCount_justFiles = itemCount;
638 ok(res + 1 == itemCount,
639 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
640 itemCount - 1, res);
642 /* Every single item in the control should start with a w and end in .c */
643 for (i = 0; i < itemCount; i++) {
644 memset(pathBuffer, 0, MAX_PATH);
645 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
646 p = pathBuffer + strlen(pathBuffer);
647 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
648 (*(p-1) == 'c' || *(p-1) == 'C') &&
649 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
652 /* Test DDL_DIRECTORY */
653 strcpy(pathBuffer, wildcard);
654 SendMessage(hList, LB_RESETCONTENT, 0, 0);
655 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
656 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
658 /* There should be some content in the listbox.
659 * All files plus "[..]"
661 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
662 itemCount_allDirs = itemCount - itemCount_allFiles;
663 ok (itemCount > itemCount_allFiles,
664 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
665 itemCount, itemCount_allFiles);
666 ok(res + 1 == itemCount,
667 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
668 itemCount - 1, res);
670 /* This tests behavior when no files match the wildcard */
671 strcpy(pathBuffer, BAD_EXTENSION);
672 SendMessage(hList, LB_RESETCONTENT, 0, 0);
673 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
674 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
676 /* There should be NO content in the listbox */
677 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
678 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
681 /* Test DDL_DIRECTORY */
682 strcpy(pathBuffer, "w*.c");
683 SendMessage(hList, LB_RESETCONTENT, 0, 0);
684 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
685 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
687 /* There should be some content in the listbox. Since the parent directory does not
688 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
690 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
691 ok (itemCount == itemCount_justFiles,
692 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
693 itemCount, itemCount_justFiles);
694 ok(res + 1 == itemCount,
695 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
696 itemCount - 1, res);
698 /* Every single item in the control should start with a w and end in .c. */
699 for (i = 0; i < itemCount; i++) {
700 memset(pathBuffer, 0, MAX_PATH);
701 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
702 p = pathBuffer + strlen(pathBuffer);
704 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
705 (*(p-1) == 'c' || *(p-1) == 'C') &&
706 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
710 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
711 strcpy(pathBuffer, wildcard);
712 SendMessage(hList, LB_RESETCONTENT, 0, 0);
713 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
714 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
716 /* There should be some content in the listbox. In particular, there should
717 * be at least one element before, since the string "[-c-]" should
718 * have been added. Depending on the user setting, more drives might have
719 * been added.
721 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
722 ok (itemCount >= 1,
723 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
724 itemCount, 1);
725 itemCount_justDrives = itemCount;
726 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
728 /* Every single item in the control should fit the format [-c-] */
729 for (i = 0; i < itemCount; i++) {
730 memset(pathBuffer, 0, MAX_PATH);
731 driveletter = '\0';
732 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
733 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
734 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
735 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
736 if (!(driveletter >= 'a' && driveletter <= 'z')) {
737 /* Correct after invalid entry is found */
738 trace("removing count of invalid entry %s\n", pathBuffer);
739 itemCount_justDrives--;
743 /* This tests behavior when no files match the wildcard */
744 strcpy(pathBuffer, BAD_EXTENSION);
745 SendMessage(hList, LB_RESETCONTENT, 0, 0);
746 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
747 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
748 BAD_EXTENSION, res, itemCount_justDrives -1);
750 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
751 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
752 itemCount, itemCount_justDrives);
754 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
755 itemCount_justFiles, itemCount_justDrives);
757 /* Test DDL_DRIVES. */
758 strcpy(pathBuffer, wildcard);
759 SendMessage(hList, LB_RESETCONTENT, 0, 0);
760 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
761 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
763 /* There should be some content in the listbox. In particular, there should
764 * be at least one element before, since the string "[-c-]" should
765 * have been added. Depending on the user setting, more drives might have
766 * been added.
768 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
769 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
770 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
771 itemCount, itemCount_justDrives + itemCount_allFiles);
772 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
774 /* This tests behavior when no files match the wildcard */
775 strcpy(pathBuffer, BAD_EXTENSION);
776 SendMessage(hList, LB_RESETCONTENT, 0, 0);
777 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
778 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
779 BAD_EXTENSION, res, itemCount_justDrives -1);
781 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
782 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
785 /* Test DDL_DRIVES. */
786 strcpy(pathBuffer, "w*.c");
787 SendMessage(hList, LB_RESETCONTENT, 0, 0);
788 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
789 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
791 /* There should be some content in the listbox. In particular, there should
792 * be at least one element before, since the string "[-c-]" should
793 * have been added. Depending on the user setting, more drives might have
794 * been added.
796 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
797 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
798 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
799 itemCount, itemCount_justDrives + itemCount_justFiles);
800 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
802 /* Every single item in the control should fit the format [-c-], or w*.c */
803 for (i = 0; i < itemCount; i++) {
804 memset(pathBuffer, 0, MAX_PATH);
805 driveletter = '\0';
806 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
807 p = pathBuffer + strlen(pathBuffer);
808 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
809 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
810 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
811 } else {
813 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
814 (*(p-1) == 'c' || *(p-1) == 'C') &&
815 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
820 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
821 strcpy(pathBuffer, wildcard);
822 SendMessage(hList, LB_RESETCONTENT, 0, 0);
823 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
824 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
826 /* There should be some content in the listbox. In particular, there should
827 * be exactly the number of plain files, plus the number of mapped drives.
829 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
830 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
831 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
832 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
833 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
835 /* Every single item in the control should start with a w and end in .c,
836 * except for the "[..]" string, which should appear exactly as it is,
837 * and the mapped drives in the format "[-X-]".
839 for (i = 0; i < itemCount; i++) {
840 memset(pathBuffer, 0, MAX_PATH);
841 driveletter = '\0';
842 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
843 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
844 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
848 /* This tests behavior when no files match the wildcard */
849 strcpy(pathBuffer, BAD_EXTENSION);
850 SendMessage(hList, LB_RESETCONTENT, 0, 0);
851 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
852 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
853 BAD_EXTENSION, res, itemCount_justDrives -1);
855 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
856 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
860 /* Test DDL_DIRECTORY|DDL_DRIVES. */
861 strcpy(pathBuffer, "w*.c");
862 SendMessage(hList, LB_RESETCONTENT, 0, 0);
863 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
864 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
866 /* There should be some content in the listbox. In particular, there should
867 * be exactly the number of plain files, plus the number of mapped drives.
869 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
870 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
871 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
872 itemCount, itemCount_justFiles + itemCount_justDrives);
873 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
875 /* Every single item in the control should start with a w and end in .c,
876 * except the mapped drives in the format "[-X-]". The "[..]" directory
877 * should not appear.
879 for (i = 0; i < itemCount; i++) {
880 memset(pathBuffer, 0, MAX_PATH);
881 driveletter = '\0';
882 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
883 p = pathBuffer + strlen(pathBuffer);
884 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
885 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
886 } else {
888 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
889 (*(p-1) == 'c' || *(p-1) == 'C') &&
890 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
894 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
895 strcpy(pathBuffer, wildcard);
896 SendMessage(hList, LB_RESETCONTENT, 0, 0);
897 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
898 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError());
900 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
901 ok (itemCount == itemCount_allDirs,
902 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
903 itemCount, itemCount_allDirs);
904 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
906 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
908 memset(pathBuffer, 0, MAX_PATH);
909 SendMessage(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
910 ok( !strcmp(pathBuffer, "[..]"), "First element is not [..]\n");
913 /* This tests behavior when no files match the wildcard */
914 strcpy(pathBuffer, BAD_EXTENSION);
915 SendMessage(hList, LB_RESETCONTENT, 0, 0);
916 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
917 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
918 BAD_EXTENSION, res, -1);
920 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
921 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
924 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
925 strcpy(pathBuffer, "w*.c");
926 SendMessage(hList, LB_RESETCONTENT, 0, 0);
927 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
928 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
930 /* There should be no elements, since "[..]" does not fit w*.c */
931 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
932 ok (itemCount == 0,
933 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
934 itemCount, 0);
936 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
937 strcpy(pathBuffer, wildcard);
938 SendMessage(hList, LB_RESETCONTENT, 0, 0);
939 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
940 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
942 /* There should be no plain files on the listbox */
943 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
944 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
945 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
946 itemCount, itemCount_justDrives + itemCount_allDirs);
947 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
949 for (i = 0; i < itemCount; i++) {
950 memset(pathBuffer, 0, MAX_PATH);
951 driveletter = '\0';
952 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
953 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
954 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
955 } else {
956 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
957 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
961 /* This tests behavior when no files match the wildcard */
962 strcpy(pathBuffer, BAD_EXTENSION);
963 SendMessage(hList, LB_RESETCONTENT, 0, 0);
964 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
965 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
966 BAD_EXTENSION, res, itemCount_justDrives -1);
968 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
969 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
971 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
972 strcpy(pathBuffer, "w*.c");
973 SendMessage(hList, LB_RESETCONTENT, 0, 0);
974 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
975 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
977 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
978 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
979 ok (itemCount == itemCount_justDrives,
980 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
981 itemCount, itemCount_justDrives);
982 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
984 for (i = 0; i < itemCount; i++) {
985 memset(pathBuffer, 0, MAX_PATH);
986 driveletter = '\0';
987 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
988 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
989 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
991 DestroyWindow(hList);
993 DeleteFileA( "wtest1.tmp.c" );
996 static HWND g_listBox;
997 static HWND g_label;
999 #define ID_TEST_LABEL 1001
1000 #define ID_TEST_LISTBOX 1002
1002 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCT lpcs)
1004 g_label = CreateWindow(
1005 "Static",
1006 "Contents of static control before DlgDirList.",
1007 WS_CHILD | WS_VISIBLE,
1008 10, 10, 512, 32,
1009 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1010 if (!g_label) return FALSE;
1011 g_listBox = CreateWindow(
1012 "ListBox",
1013 "DlgDirList test",
1014 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1015 10, 60, 256, 256,
1016 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1017 if (!g_listBox) return FALSE;
1019 return TRUE;
1022 static LRESULT CALLBACK listbox_container_window_procA (
1023 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1025 LRESULT result = 0;
1027 switch (uiMsg) {
1028 case WM_DESTROY:
1029 PostQuitMessage(0);
1030 break;
1031 case WM_CREATE:
1032 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1033 ? 0 : (LRESULT)-1;
1034 break;
1035 default:
1036 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1037 break;
1039 return result;
1042 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1044 WNDCLASSA cls;
1046 cls.style = 0;
1047 cls.cbClsExtra = 0;
1048 cls.cbWndExtra = 0;
1049 cls.hInstance = hInst;
1050 cls.hIcon = NULL;
1051 cls.hCursor = LoadCursorA (NULL, IDC_ARROW);
1052 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1053 cls.lpszMenuName = NULL;
1054 cls.lpfnWndProc = listbox_container_window_procA;
1055 cls.lpszClassName = "ListboxContainerClass";
1056 if (!RegisterClassA (&cls)) return FALSE;
1058 return TRUE;
1061 static void test_listbox_dlgdir(void)
1063 HINSTANCE hInst;
1064 HWND hWnd;
1065 int res, itemCount;
1066 int itemCount_allDirs;
1067 int itemCount_justFiles;
1068 int itemCount_justDrives;
1069 int i;
1070 char pathBuffer[MAX_PATH];
1071 char itemBuffer[MAX_PATH];
1072 char tempBuffer[MAX_PATH];
1073 char * p;
1074 char driveletter;
1075 HANDLE file;
1077 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1078 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1079 CloseHandle( file );
1081 /* NOTE: for this test to succeed, there must be no subdirectories
1082 under the current directory. In addition, there must be at least
1083 one file that fits the wildcard w*.c . Normally, the test
1084 directory itself satisfies both conditions.
1087 hInst = GetModuleHandleA(0);
1088 if (!RegisterListboxWindowClass(hInst)) assert(0);
1089 hWnd = CreateWindow("ListboxContainerClass", "ListboxContainerClass",
1090 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1091 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1092 NULL, NULL, hInst, 0);
1093 assert(hWnd);
1095 /* Test for standard usage */
1097 /* The following should be overwritten by the directory path */
1098 SendMessage(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1100 /* This should list all the w*.c files in the test directory
1101 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1103 strcpy(pathBuffer, "w*.c");
1104 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1105 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1107 /* Path specification gets converted to uppercase */
1108 ok (!strcmp(pathBuffer, "W*.C"),
1109 "expected conversion to uppercase, got %s\n", pathBuffer);
1111 /* Loaded path should have overwritten the label text */
1112 SendMessage(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer);
1113 trace("Static control after DlgDirList: %s\n", pathBuffer);
1114 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1116 /* There should be some content in the listbox */
1117 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1118 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1119 itemCount_justFiles = itemCount;
1121 /* Every single item in the control should start with a w and end in .c */
1122 for (i = 0; i < itemCount; i++) {
1123 memset(pathBuffer, 0, MAX_PATH);
1124 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1125 p = pathBuffer + strlen(pathBuffer);
1126 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1127 (*(p-1) == 'c' || *(p-1) == 'C') &&
1128 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1131 /* Test behavior when no files match the wildcard */
1132 strcpy(pathBuffer, BAD_EXTENSION);
1133 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1134 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1136 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1137 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1139 /* Test DDL_DIRECTORY */
1140 strcpy(pathBuffer, "w*.c");
1141 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1142 DDL_DIRECTORY);
1143 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1145 /* There should be some content in the listbox. In particular, there should
1146 * be exactly more elements than before, since the directories should
1147 * have been added.
1149 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1150 itemCount_allDirs = itemCount - itemCount_justFiles;
1151 ok (itemCount >= itemCount_justFiles,
1152 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1153 itemCount, itemCount_justFiles);
1155 /* Every single item in the control should start with a w and end in .c,
1156 * except for the "[..]" string, which should appear exactly as it is.
1158 for (i = 0; i < itemCount; i++) {
1159 memset(pathBuffer, 0, MAX_PATH);
1160 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1161 p = pathBuffer + strlen(pathBuffer);
1162 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1163 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1164 (*(p-1) == 'c' || *(p-1) == 'C') &&
1165 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1168 /* Test behavior when no files match the wildcard */
1169 strcpy(pathBuffer, BAD_EXTENSION);
1170 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1171 DDL_DIRECTORY);
1172 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1174 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1175 ok (itemCount == itemCount_allDirs,
1176 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1177 itemCount_allDirs, itemCount);
1178 for (i = 0; i < itemCount; i++) {
1179 memset(pathBuffer, 0, MAX_PATH);
1180 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1181 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1182 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1186 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1187 strcpy(pathBuffer, "w*.c");
1188 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1189 DDL_DRIVES);
1190 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1192 /* There should be some content in the listbox. In particular, there should
1193 * be at least one element before, since the string "[-c-]" should
1194 * have been added. Depending on the user setting, more drives might have
1195 * been added.
1197 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1198 ok (itemCount >= 1,
1199 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1200 itemCount, 1);
1201 itemCount_justDrives = itemCount;
1203 /* Every single item in the control should fit the format [-c-] */
1204 for (i = 0; i < itemCount; i++) {
1205 memset(pathBuffer, 0, MAX_PATH);
1206 driveletter = '\0';
1207 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1208 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1209 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1210 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1211 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1212 /* Correct after invalid entry is found */
1213 trace("removing count of invalid entry %s\n", pathBuffer);
1214 itemCount_justDrives--;
1218 /* Test behavior when no files match the wildcard */
1219 strcpy(pathBuffer, BAD_EXTENSION);
1220 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1221 DDL_DRIVES);
1222 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1224 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1225 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1228 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1229 strcpy(pathBuffer, "w*.c");
1230 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1231 DDL_DIRECTORY|DDL_DRIVES);
1232 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1234 /* There should be some content in the listbox. In particular, there should
1235 * be exactly the number of plain files, plus the number of mapped drives,
1236 * plus one "[..]"
1238 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1239 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1240 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1241 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1243 /* Every single item in the control should start with a w and end in .c,
1244 * except for the "[..]" string, which should appear exactly as it is,
1245 * and the mapped drives in the format "[-X-]".
1247 for (i = 0; i < itemCount; i++) {
1248 memset(pathBuffer, 0, MAX_PATH);
1249 driveletter = '\0';
1250 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1251 p = pathBuffer + strlen(pathBuffer);
1252 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1253 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1254 } else {
1255 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1256 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1257 (*(p-1) == 'c' || *(p-1) == 'C') &&
1258 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1262 /* Test behavior when no files match the wildcard */
1263 strcpy(pathBuffer, BAD_EXTENSION);
1264 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1265 DDL_DIRECTORY|DDL_DRIVES);
1266 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1268 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1269 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1270 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1271 itemCount_justDrives + itemCount_allDirs, itemCount);
1275 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1276 strcpy(pathBuffer, "w*.c");
1277 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1278 DDL_DIRECTORY|DDL_EXCLUSIVE);
1279 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1281 /* There should be exactly one element: "[..]" */
1282 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1283 ok (itemCount == itemCount_allDirs,
1284 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1285 itemCount, itemCount_allDirs);
1287 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1289 memset(pathBuffer, 0, MAX_PATH);
1290 SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1291 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1294 /* Test behavior when no files match the wildcard */
1295 strcpy(pathBuffer, BAD_EXTENSION);
1296 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1297 DDL_DIRECTORY|DDL_EXCLUSIVE);
1298 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1300 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1301 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1304 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1305 strcpy(pathBuffer, "w*.c");
1306 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1307 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1308 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1310 /* There should be no plain files on the listbox */
1311 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1312 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1313 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1314 itemCount, itemCount_justDrives + itemCount_allDirs);
1316 for (i = 0; i < itemCount; i++) {
1317 memset(pathBuffer, 0, MAX_PATH);
1318 driveletter = '\0';
1319 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1320 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1321 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1322 } else {
1323 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1324 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1328 /* Test behavior when no files match the wildcard */
1329 strcpy(pathBuffer, BAD_EXTENSION);
1330 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1331 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1332 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1334 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1335 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1336 "DlgDirList() incorrectly filled the listbox!\n");
1338 /* Test behavior when loading folders from root with and without wildcard */
1339 strcpy(pathBuffer, "C:\\");
1340 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1341 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\ folders\n");
1342 todo_wine ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1343 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1345 strcpy(pathBuffer, "C:\\*");
1346 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1347 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\* folders\n");
1348 ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1349 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1351 /* Try loading files from an invalid folder */
1352 SetLastError(0xdeadbeef);
1353 strcpy(pathBuffer, "C:\\INVALID$$DIR");
1354 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1355 todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
1356 todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
1357 "GetLastError should return 0x589, got 0x%X\n",GetLastError());
1360 /* Now test DlgDirSelectEx() in normal operation */
1361 /* Fill with everything - drives, directory and all plain files. */
1362 strcpy(pathBuffer, "*");
1363 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1364 DDL_DIRECTORY|DDL_DRIVES);
1365 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1367 SendMessage(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1368 memset(pathBuffer, 0, MAX_PATH);
1369 SetLastError(0xdeadbeef);
1370 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1371 ok (GetLastError() == 0xdeadbeef,
1372 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1373 GetLastError());
1374 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1375 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1377 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1379 /* Test proper drive/dir/file recognition */
1380 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1381 for (i = 0; i < itemCount; i++) {
1382 memset(itemBuffer, 0, MAX_PATH);
1383 memset(pathBuffer, 0, MAX_PATH);
1384 memset(tempBuffer, 0, MAX_PATH);
1385 driveletter = '\0';
1386 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1387 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1388 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1389 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1390 /* Current item is a drive letter */
1391 SetLastError(0xdeadbeef);
1392 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1393 ok (GetLastError() == 0xdeadbeef,
1394 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1395 i, GetLastError());
1396 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1398 /* For drive letters, DlgDirSelectEx tacks on a colon */
1399 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1400 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1401 } else if (itemBuffer[0] == '[') {
1402 /* Current item is the parent directory */
1403 SetLastError(0xdeadbeef);
1404 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1405 ok (GetLastError() == 0xdeadbeef,
1406 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1407 i, GetLastError());
1408 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1410 /* For directories, DlgDirSelectEx tacks on a backslash */
1411 p = pathBuffer + strlen(pathBuffer);
1412 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1414 tempBuffer[0] = '[';
1415 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1416 strcat(tempBuffer, "]");
1417 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1418 } else {
1419 /* Current item is a plain file */
1420 SetLastError(0xdeadbeef);
1421 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1422 ok (GetLastError() == 0xdeadbeef,
1423 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1424 i, GetLastError());
1425 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1427 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1428 * for example, "Makefile", which gets reported as "Makefile."
1430 strcpy(tempBuffer, itemBuffer);
1431 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1432 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1436 /* Now test DlgDirSelectEx() in abnormal operation */
1437 /* Fill list with bogus entries, that look somewhat valid */
1438 SendMessage(g_listBox, LB_RESETCONTENT, 0, 0);
1439 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1440 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1441 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1442 for (i = 0; i < itemCount; i++) {
1443 memset(itemBuffer, 0, MAX_PATH);
1444 memset(pathBuffer, 0, MAX_PATH);
1445 memset(tempBuffer, 0, MAX_PATH);
1446 driveletter = '\0';
1447 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1448 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1449 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1450 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1451 /* Current item is a drive letter */
1452 SetLastError(0xdeadbeef);
1453 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1454 ok (GetLastError() == 0xdeadbeef,
1455 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1456 i, GetLastError());
1457 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1459 /* For drive letters, DlgDirSelectEx tacks on a colon */
1460 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1461 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1462 } else if (itemBuffer[0] == '[') {
1463 /* Current item is the parent directory */
1464 SetLastError(0xdeadbeef);
1465 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1466 ok (GetLastError() == 0xdeadbeef,
1467 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1468 i, GetLastError());
1469 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1471 /* For directories, DlgDirSelectEx tacks on a backslash */
1472 p = pathBuffer + strlen(pathBuffer);
1473 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1475 tempBuffer[0] = '[';
1476 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1477 strcat(tempBuffer, "]");
1478 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1479 } else {
1480 /* Current item is a plain file */
1481 SetLastError(0xdeadbeef);
1482 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1483 ok (GetLastError() == 0xdeadbeef,
1484 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1485 i, GetLastError());
1486 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1488 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1489 * This affects for example, "Makefile", which gets reported as "Makefile."
1491 strcpy(tempBuffer, itemBuffer);
1492 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1493 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1496 DestroyWindow(hWnd);
1498 DeleteFileA( "wtest1.tmp.c" );
1501 START_TEST(listbox)
1503 const struct listbox_test SS =
1504 /* {add_style} */
1505 {{0},
1506 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1507 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1508 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1509 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1510 /* {selected, anchor, caret, selcount}{TODO fields} */
1511 const struct listbox_test SS_NS =
1512 {{LBS_NOSEL},
1513 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1514 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1515 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1516 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1517 const struct listbox_test MS =
1518 {{LBS_MULTIPLESEL},
1519 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1520 { 1, 1, 1, 1}, {0,0,0,0},
1521 { 2, 1, 2, 1}, {0,0,0,0},
1522 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1523 const struct listbox_test MS_NS =
1524 {{LBS_MULTIPLESEL | LBS_NOSEL},
1525 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1526 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1527 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1528 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1529 const struct listbox_test ES =
1530 {{LBS_EXTENDEDSEL},
1531 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1532 { 1, 1, 1, 1}, {0,0,0,0},
1533 { 2, 2, 2, 1}, {0,0,0,0},
1534 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1535 const struct listbox_test ES_NS =
1536 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1537 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1538 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1539 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1540 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1541 const struct listbox_test EMS =
1542 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1543 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1544 { 1, 1, 1, 1}, {0,0,0,0},
1545 { 2, 2, 2, 1}, {0,0,0,0},
1546 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1547 const struct listbox_test EMS_NS =
1548 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1549 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1550 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1551 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1552 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1554 trace (" Testing single selection...\n");
1555 check (SS);
1556 trace (" ... with NOSEL\n");
1557 check (SS_NS);
1558 trace (" Testing multiple selection...\n");
1559 check (MS);
1560 trace (" ... with NOSEL\n");
1561 check (MS_NS);
1562 trace (" Testing extended selection...\n");
1563 check (ES);
1564 trace (" ... with NOSEL\n");
1565 check (ES_NS);
1566 trace (" Testing extended and multiple selection...\n");
1567 check (EMS);
1568 trace (" ... with NOSEL\n");
1569 check (EMS_NS);
1571 check_item_height();
1572 test_ownerdraw();
1573 test_selection();
1574 test_listbox_height();
1575 test_itemfrompoint();
1576 test_listbox_item_data();
1577 test_listbox_LB_DIR();
1578 test_listbox_dlgdir();