amstream/tests: Fix crosstest build.
[wine/hacks.git] / dlls / user32 / tests / listbox.c
blob0aef698dbf55920a5cf519d8dd08e35e387c40e7
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, (WPARAM) 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 assert(RegisterClass(&cls));
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 UpdateWindow(hLB);
308 /* make height short enough */
309 SendMessage(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
310 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
311 SWP_NOZORDER | SWP_NOMOVE);
313 /* make 0 item invisible */
314 SendMessage(hLB, LB_SETTOPINDEX, 1, 0);
315 ret = SendMessage(hLB, LB_GETTOPINDEX, 0, 0);
316 ok(ret == 1, "wrong top index %d\n", ret);
318 SendMessage(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
319 trace("item 0 rect (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom);
320 ok(!IsRectEmpty(&rc), "empty item rect\n");
321 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
323 DestroyWindow(hLB);
324 DestroyWindow(parent);
327 #define listbox_test_query(exp, got) \
328 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
329 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
330 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
331 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
333 static void test_selection(void)
335 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
336 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
337 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
338 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
339 HWND hLB;
340 struct listbox_stat answer;
341 INT ret;
343 trace("testing LB_SELITEMRANGE\n");
345 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
346 assert(hLB);
348 listbox_query(hLB, &answer);
349 listbox_test_query(test_nosel, answer);
351 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
352 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
353 listbox_query(hLB, &answer);
354 listbox_test_query(test_1, answer);
356 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
357 listbox_query(hLB, &answer);
358 listbox_test_query(test_nosel, answer);
360 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
361 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
362 listbox_query(hLB, &answer);
363 listbox_test_query(test_3, answer);
365 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
366 listbox_query(hLB, &answer);
367 listbox_test_query(test_nosel, answer);
369 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
370 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
371 listbox_query(hLB, &answer);
372 listbox_test_query(test_nosel, answer);
374 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
375 listbox_query(hLB, &answer);
376 listbox_test_query(test_nosel, answer);
378 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
379 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
380 listbox_query(hLB, &answer);
381 listbox_test_query(test_1, answer);
383 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
384 listbox_query(hLB, &answer);
385 listbox_test_query(test_nosel, answer);
387 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
388 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
389 listbox_query(hLB, &answer);
390 listbox_test_query(test_nosel, answer);
392 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
393 listbox_query(hLB, &answer);
394 listbox_test_query(test_nosel, answer);
396 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
397 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
398 listbox_query(hLB, &answer);
399 listbox_test_query(test_2, answer);
401 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
402 listbox_query(hLB, &answer);
403 listbox_test_query(test_nosel, answer);
405 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
406 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
407 listbox_query(hLB, &answer);
408 listbox_test_query(test_2, answer);
410 DestroyWindow(hLB);
413 static void test_listbox_height(void)
415 HWND hList;
416 int r, id;
418 hList = CreateWindow( "ListBox", "list test", 0,
419 1, 1, 600, 100, NULL, NULL, NULL, NULL );
420 ok( hList != NULL, "failed to create listbox\n");
422 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
423 ok( id == 0, "item id wrong\n");
425 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
426 ok( r == 0, "send message failed\n");
428 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
429 ok( r == 20, "height wrong\n");
431 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
432 ok( r == -1, "send message failed\n");
434 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
435 ok( r == 20, "height wrong\n");
437 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
438 ok( r == -1, "send message failed\n");
440 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
441 ok( r == 20, "height wrong\n");
443 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
444 ok( r == 0, "send message failed\n");
446 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
447 ok( r == 0xff, "height wrong\n");
449 DestroyWindow( hList );
452 static void test_itemfrompoint(void)
454 /* WS_POPUP is required in order to have a more accurate size calculation (
455 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
456 behavior of partially-displayed item.
458 HWND hList = CreateWindow( "ListBox", "list test",
459 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
460 1, 1, 600, 100, NULL, NULL, NULL, NULL );
461 ULONG r, id;
462 RECT rc;
464 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000, nt4 returns 0xffffffff */
465 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
466 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
468 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
469 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
471 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
472 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
474 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
475 ok( id == 0, "item id wrong\n");
476 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
477 ok( id == 1, "item id wrong\n");
479 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
480 ok( r == 0x1, "ret %x\n", r );
482 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
483 ok( r == 0x10001 || broken(r == 1), /* nt4 */
484 "ret %x\n", r );
486 /* Resize control so that below assertions about sizes are valid */
487 r = SendMessage( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
488 ok( r == 1, "ret %x\n", r);
489 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
490 ok( r != 0, "ret %x\n", r);
492 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
493 ok( id == 2, "item id wrong\n");
494 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
495 ok( id == 3, "item id wrong\n");
496 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
497 ok( id == 4, "item id wrong\n");
498 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
499 ok( id == 5, "item id wrong\n");
500 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
501 ok( id == 6, "item id wrong\n");
502 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
503 ok( id == 7, "item id wrong\n");
505 /* Set the listbox up so that id 1 is at the top, this leaves 5
506 partially visible at the bottom and 6, 7 are invisible */
508 SendMessage( hList, LB_SETTOPINDEX, 1, 0);
509 r = SendMessage( hList, LB_GETTOPINDEX, 0, 0);
510 ok( r == 1, "top %d\n", r);
512 r = SendMessage( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
513 ok( r == 1, "ret %x\n", r);
514 r = SendMessage( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
515 ok( r == 0, "ret %x\n", r);
517 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
518 ok( r == 1, "ret %x\n", r);
520 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
521 ok( r == 0x10001 || broken(r == 1), /* nt4 */
522 "ret %x\n", r );
524 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
525 ok( r == 0x10001 || broken(r == 1), /* nt4 */
526 "ret %x\n", r );
528 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
529 ok( r == 0x10005 || broken(r == 5), /* nt4 */
530 "item %x\n", r );
532 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
533 ok( r == 0x10005 || broken(r == 5), /* nt4 */
534 "item %x\n", r );
536 DestroyWindow( hList );
539 static void test_listbox_item_data(void)
541 HWND hList;
542 int r, id;
544 hList = CreateWindow( "ListBox", "list test", 0,
545 1, 1, 600, 100, NULL, NULL, NULL, NULL );
546 ok( hList != NULL, "failed to create listbox\n");
548 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
549 ok( id == 0, "item id wrong\n");
551 r = SendMessage( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
552 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
554 r = SendMessage( hList, LB_GETITEMDATA, 0, 0);
555 ok( r == 20, "get item data failed\n");
557 DestroyWindow( hList );
560 static void test_listbox_LB_DIR(void)
562 HWND hList;
563 int res, itemCount;
564 int itemCount_justFiles;
565 int itemCount_justDrives;
566 int itemCount_allFiles;
567 int itemCount_allDirs;
568 int i;
569 char pathBuffer[MAX_PATH];
570 char * p;
571 char driveletter;
572 const char *wildcard = "*";
573 HANDLE file;
575 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
576 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
577 CloseHandle( file );
579 /* NOTE: for this test to succeed, there must be no subdirectories
580 under the current directory. In addition, there must be at least
581 one file that fits the wildcard w*.c . Normally, the test
582 directory itself satisfies both conditions.
584 hList = CreateWindow( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
585 1, 1, 600, 100, NULL, NULL, NULL, NULL );
586 assert(hList);
588 /* Test for standard usage */
590 /* This should list all the files in the test directory. */
591 strcpy(pathBuffer, wildcard);
592 SendMessage(hList, LB_RESETCONTENT, 0, 0);
593 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
594 if (res == -1) /* "*" wildcard doesn't work on win9x */
596 wildcard = "*.*";
597 strcpy(pathBuffer, wildcard);
598 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
600 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
602 /* There should be some content in the listbox */
603 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
604 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
605 itemCount_allFiles = itemCount;
606 ok(res + 1 == itemCount,
607 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
608 itemCount - 1, res);
610 /* This tests behavior when no files match the wildcard */
611 strcpy(pathBuffer, BAD_EXTENSION);
612 SendMessage(hList, LB_RESETCONTENT, 0, 0);
613 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
614 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
616 /* There should be NO content in the listbox */
617 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
618 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
621 /* This should list all the w*.c files in the test directory
622 * As of this writing, this includes win.c, winstation.c, wsprintf.c
624 strcpy(pathBuffer, "w*.c");
625 SendMessage(hList, LB_RESETCONTENT, 0, 0);
626 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
627 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
629 /* Path specification does NOT converted to uppercase */
630 ok (!strcmp(pathBuffer, "w*.c"),
631 "expected no change to pathBuffer, got %s\n", pathBuffer);
633 /* There should be some content in the listbox */
634 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
635 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
636 itemCount_justFiles = itemCount;
637 ok(res + 1 == itemCount,
638 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
639 itemCount - 1, res);
641 /* Every single item in the control should start with a w and end in .c */
642 for (i = 0; i < itemCount; i++) {
643 memset(pathBuffer, 0, MAX_PATH);
644 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
645 p = pathBuffer + strlen(pathBuffer);
646 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
647 (*(p-1) == 'c' || *(p-1) == 'C') &&
648 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
651 /* Test DDL_DIRECTORY */
652 strcpy(pathBuffer, wildcard);
653 SendMessage(hList, LB_RESETCONTENT, 0, 0);
654 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
655 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
657 /* There should be some content in the listbox.
658 * All files plus "[..]"
660 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
661 itemCount_allDirs = itemCount - itemCount_allFiles;
662 ok (itemCount > itemCount_allFiles,
663 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
664 itemCount, itemCount_allFiles);
665 ok(res + 1 == itemCount,
666 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
667 itemCount - 1, res);
669 /* This tests behavior when no files match the wildcard */
670 strcpy(pathBuffer, BAD_EXTENSION);
671 SendMessage(hList, LB_RESETCONTENT, 0, 0);
672 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
673 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
675 /* There should be NO content in the listbox */
676 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
677 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
680 /* Test DDL_DIRECTORY */
681 strcpy(pathBuffer, "w*.c");
682 SendMessage(hList, LB_RESETCONTENT, 0, 0);
683 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
684 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
686 /* There should be some content in the listbox. Since the parent directory does not
687 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
689 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
690 ok (itemCount == itemCount_justFiles,
691 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
692 itemCount, itemCount_justFiles);
693 ok(res + 1 == itemCount,
694 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
695 itemCount - 1, res);
697 /* Every single item in the control should start with a w and end in .c. */
698 for (i = 0; i < itemCount; i++) {
699 memset(pathBuffer, 0, MAX_PATH);
700 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
701 p = pathBuffer + strlen(pathBuffer);
703 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
704 (*(p-1) == 'c' || *(p-1) == 'C') &&
705 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
709 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
710 strcpy(pathBuffer, wildcard);
711 SendMessage(hList, LB_RESETCONTENT, 0, 0);
712 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
713 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
715 /* There should be some content in the listbox. In particular, there should
716 * be at least one element before, since the string "[-c-]" should
717 * have been added. Depending on the user setting, more drives might have
718 * been added.
720 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
721 ok (itemCount >= 1,
722 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
723 itemCount, 1);
724 itemCount_justDrives = itemCount;
725 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
727 /* Every single item in the control should fit the format [-c-] */
728 for (i = 0; i < itemCount; i++) {
729 memset(pathBuffer, 0, MAX_PATH);
730 driveletter = '\0';
731 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
732 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
733 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
734 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
735 if (!(driveletter >= 'a' && driveletter <= 'z')) {
736 /* Correct after invalid entry is found */
737 trace("removing count of invalid entry %s\n", pathBuffer);
738 itemCount_justDrives--;
742 /* This tests behavior when no files match the wildcard */
743 strcpy(pathBuffer, BAD_EXTENSION);
744 SendMessage(hList, LB_RESETCONTENT, 0, 0);
745 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
746 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
747 BAD_EXTENSION, res, itemCount_justDrives -1);
749 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
750 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
751 itemCount, itemCount_justDrives);
753 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
754 itemCount_justFiles, itemCount_justDrives);
756 /* Test DDL_DRIVES. */
757 strcpy(pathBuffer, wildcard);
758 SendMessage(hList, LB_RESETCONTENT, 0, 0);
759 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
760 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
762 /* There should be some content in the listbox. In particular, there should
763 * be at least one element before, since the string "[-c-]" should
764 * have been added. Depending on the user setting, more drives might have
765 * been added.
767 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
768 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
769 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
770 itemCount, itemCount_justDrives + itemCount_allFiles);
771 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
773 /* This tests behavior when no files match the wildcard */
774 strcpy(pathBuffer, BAD_EXTENSION);
775 SendMessage(hList, LB_RESETCONTENT, 0, 0);
776 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
777 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
778 BAD_EXTENSION, res, itemCount_justDrives -1);
780 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
781 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
784 /* Test DDL_DRIVES. */
785 strcpy(pathBuffer, "w*.c");
786 SendMessage(hList, LB_RESETCONTENT, 0, 0);
787 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
788 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
790 /* There should be some content in the listbox. In particular, there should
791 * be at least one element before, since the string "[-c-]" should
792 * have been added. Depending on the user setting, more drives might have
793 * been added.
795 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
796 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
797 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
798 itemCount, itemCount_justDrives + itemCount_justFiles);
799 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
801 /* Every single item in the control should fit the format [-c-], or w*.c */
802 for (i = 0; i < itemCount; i++) {
803 memset(pathBuffer, 0, MAX_PATH);
804 driveletter = '\0';
805 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
806 p = pathBuffer + strlen(pathBuffer);
807 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
808 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
809 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
810 } else {
812 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
813 (*(p-1) == 'c' || *(p-1) == 'C') &&
814 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
819 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
820 strcpy(pathBuffer, wildcard);
821 SendMessage(hList, LB_RESETCONTENT, 0, 0);
822 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
823 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
825 /* There should be some content in the listbox. In particular, there should
826 * be exactly the number of plain files, plus the number of mapped drives.
828 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
829 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
830 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
831 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
832 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
834 /* Every single item in the control should start with a w and end in .c,
835 * except for the "[..]" string, which should appear exactly as it is,
836 * and the mapped drives in the format "[-X-]".
838 for (i = 0; i < itemCount; i++) {
839 memset(pathBuffer, 0, MAX_PATH);
840 driveletter = '\0';
841 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
842 p = pathBuffer + strlen(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 p = pathBuffer + strlen(pathBuffer);
954 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
955 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
956 } else {
957 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
958 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
962 /* This tests behavior when no files match the wildcard */
963 strcpy(pathBuffer, BAD_EXTENSION);
964 SendMessage(hList, LB_RESETCONTENT, 0, 0);
965 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
966 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
967 BAD_EXTENSION, res, itemCount_justDrives -1);
969 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
970 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
972 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
973 strcpy(pathBuffer, "w*.c");
974 SendMessage(hList, LB_RESETCONTENT, 0, 0);
975 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
976 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
978 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
979 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
980 ok (itemCount == itemCount_justDrives,
981 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
982 itemCount, itemCount_justDrives);
983 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
985 for (i = 0; i < itemCount; i++) {
986 memset(pathBuffer, 0, MAX_PATH);
987 driveletter = '\0';
988 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
989 p = pathBuffer + strlen(pathBuffer);
990 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
991 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
993 DestroyWindow(hList);
995 DeleteFileA( "wtest1.tmp.c" );
998 HWND g_listBox;
999 HWND g_label;
1001 #define ID_TEST_LABEL 1001
1002 #define ID_TEST_LISTBOX 1002
1004 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCT lpcs)
1006 g_label = CreateWindow(
1007 "Static",
1008 "Contents of static control before DlgDirList.",
1009 WS_CHILD | WS_VISIBLE,
1010 10, 10, 512, 32,
1011 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1012 if (!g_label) return FALSE;
1013 g_listBox = CreateWindow(
1014 "ListBox",
1015 "DlgDirList test",
1016 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1017 10, 60, 256, 256,
1018 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1019 if (!g_listBox) return FALSE;
1021 return TRUE;
1024 static LRESULT CALLBACK listbox_container_window_procA (
1025 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1027 LRESULT result = 0;
1029 switch (uiMsg) {
1030 case WM_DESTROY:
1031 PostQuitMessage(0);
1032 break;
1033 case WM_CREATE:
1034 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1035 ? 0 : (LRESULT)-1;
1036 break;
1037 default:
1038 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1039 break;
1041 return result;
1044 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1046 WNDCLASSA cls;
1048 cls.style = 0;
1049 cls.cbClsExtra = 0;
1050 cls.cbWndExtra = 0;
1051 cls.hInstance = hInst;
1052 cls.hIcon = NULL;
1053 cls.hCursor = LoadCursorA (NULL, IDC_ARROW);
1054 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1055 cls.lpszMenuName = NULL;
1056 cls.lpfnWndProc = listbox_container_window_procA;
1057 cls.lpszClassName = "ListboxContainerClass";
1058 if (!RegisterClassA (&cls)) return FALSE;
1060 return TRUE;
1063 static void test_listbox_dlgdir(void)
1065 HINSTANCE hInst;
1066 HWND hWnd;
1067 int res, itemCount;
1068 int itemCount_allDirs;
1069 int itemCount_justFiles;
1070 int itemCount_justDrives;
1071 int i;
1072 char pathBuffer[MAX_PATH];
1073 char itemBuffer[MAX_PATH];
1074 char tempBuffer[MAX_PATH];
1075 char * p;
1076 char driveletter;
1077 HANDLE file;
1079 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1080 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1081 CloseHandle( file );
1083 /* NOTE: for this test to succeed, there must be no subdirectories
1084 under the current directory. In addition, there must be at least
1085 one file that fits the wildcard w*.c . Normally, the test
1086 directory itself satisfies both conditions.
1089 hInst = GetModuleHandleA(0);
1090 if (!RegisterListboxWindowClass(hInst)) assert(0);
1091 hWnd = CreateWindow("ListboxContainerClass", "ListboxContainerClass",
1092 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1093 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1094 NULL, NULL, hInst, 0);
1095 assert(hWnd);
1097 /* Test for standard usage */
1099 /* The following should be overwritten by the directory path */
1100 SendMessage(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1102 /* This should list all the w*.c files in the test directory
1103 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1105 strcpy(pathBuffer, "w*.c");
1106 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1107 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1109 /* Path specification gets converted to uppercase */
1110 ok (!strcmp(pathBuffer, "W*.C"),
1111 "expected conversion to uppercase, got %s\n", pathBuffer);
1113 /* Loaded path should have overwritten the label text */
1114 SendMessage(g_label, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)pathBuffer);
1115 trace("Static control after DlgDirList: %s\n", pathBuffer);
1116 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1118 /* There should be some content in the listbox */
1119 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1120 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1121 itemCount_justFiles = itemCount;
1123 /* Every single item in the control should start with a w and end in .c */
1124 for (i = 0; i < itemCount; i++) {
1125 memset(pathBuffer, 0, MAX_PATH);
1126 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1127 p = pathBuffer + strlen(pathBuffer);
1128 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1129 (*(p-1) == 'c' || *(p-1) == 'C') &&
1130 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1133 /* Test behavior when no files match the wildcard */
1134 strcpy(pathBuffer, BAD_EXTENSION);
1135 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1136 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1138 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1139 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1141 /* Test DDL_DIRECTORY */
1142 strcpy(pathBuffer, "w*.c");
1143 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1144 DDL_DIRECTORY);
1145 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1147 /* There should be some content in the listbox. In particular, there should
1148 * be exactly more elements than before, since the directories should
1149 * have been added.
1151 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1152 itemCount_allDirs = itemCount - itemCount_justFiles;
1153 ok (itemCount >= itemCount_justFiles,
1154 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1155 itemCount, itemCount_justFiles);
1157 /* Every single item in the control should start with a w and end in .c,
1158 * except for the "[..]" string, which should appear exactly as it is.
1160 for (i = 0; i < itemCount; i++) {
1161 memset(pathBuffer, 0, MAX_PATH);
1162 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1163 p = pathBuffer + strlen(pathBuffer);
1164 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1165 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1166 (*(p-1) == 'c' || *(p-1) == 'C') &&
1167 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1170 /* Test behavior when no files match the wildcard */
1171 strcpy(pathBuffer, BAD_EXTENSION);
1172 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1173 DDL_DIRECTORY);
1174 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1176 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1177 ok (itemCount == itemCount_allDirs,
1178 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1179 itemCount_allDirs, itemCount);
1180 for (i = 0; i < itemCount; i++) {
1181 memset(pathBuffer, 0, MAX_PATH);
1182 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1183 p = pathBuffer + strlen(pathBuffer);
1184 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1185 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1189 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1190 strcpy(pathBuffer, "w*.c");
1191 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1192 DDL_DRIVES);
1193 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1195 /* There should be some content in the listbox. In particular, there should
1196 * be at least one element before, since the string "[-c-]" should
1197 * have been added. Depending on the user setting, more drives might have
1198 * been added.
1200 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1201 ok (itemCount >= 1,
1202 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1203 itemCount, 1);
1204 itemCount_justDrives = itemCount;
1206 /* Every single item in the control should fit the format [-c-] */
1207 for (i = 0; i < itemCount; i++) {
1208 memset(pathBuffer, 0, MAX_PATH);
1209 driveletter = '\0';
1210 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1211 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1212 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1213 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1214 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1215 /* Correct after invalid entry is found */
1216 trace("removing count of invalid entry %s\n", pathBuffer);
1217 itemCount_justDrives--;
1221 /* Test behavior when no files match the wildcard */
1222 strcpy(pathBuffer, BAD_EXTENSION);
1223 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1224 DDL_DRIVES);
1225 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1227 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1228 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1231 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1232 strcpy(pathBuffer, "w*.c");
1233 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1234 DDL_DIRECTORY|DDL_DRIVES);
1235 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1237 /* There should be some content in the listbox. In particular, there should
1238 * be exactly the number of plain files, plus the number of mapped drives,
1239 * plus one "[..]"
1241 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1242 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1243 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1244 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1246 /* Every single item in the control should start with a w and end in .c,
1247 * except for the "[..]" string, which should appear exactly as it is,
1248 * and the mapped drives in the format "[-X-]".
1250 for (i = 0; i < itemCount; i++) {
1251 memset(pathBuffer, 0, MAX_PATH);
1252 driveletter = '\0';
1253 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1254 p = pathBuffer + strlen(pathBuffer);
1255 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1256 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1257 } else {
1258 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1259 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1260 (*(p-1) == 'c' || *(p-1) == 'C') &&
1261 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1265 /* Test behavior when no files match the wildcard */
1266 strcpy(pathBuffer, BAD_EXTENSION);
1267 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1268 DDL_DIRECTORY|DDL_DRIVES);
1269 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1271 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1272 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1273 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1274 itemCount_justDrives + itemCount_allDirs, itemCount);
1278 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1279 strcpy(pathBuffer, "w*.c");
1280 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1281 DDL_DIRECTORY|DDL_EXCLUSIVE);
1282 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1284 /* There should be exactly one element: "[..]" */
1285 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1286 ok (itemCount == itemCount_allDirs,
1287 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1288 itemCount, itemCount_allDirs);
1290 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1292 memset(pathBuffer, 0, MAX_PATH);
1293 SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1294 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1297 /* Test behavior when no files match the wildcard */
1298 strcpy(pathBuffer, BAD_EXTENSION);
1299 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1300 DDL_DIRECTORY|DDL_EXCLUSIVE);
1301 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1303 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1304 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1307 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1308 strcpy(pathBuffer, "w*.c");
1309 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1310 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1311 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1313 /* There should be no plain files on the listbox */
1314 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1315 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1316 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1317 itemCount, itemCount_justDrives + itemCount_allDirs);
1319 for (i = 0; i < itemCount; i++) {
1320 memset(pathBuffer, 0, MAX_PATH);
1321 driveletter = '\0';
1322 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1323 p = pathBuffer + strlen(pathBuffer);
1324 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1325 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1326 } else {
1327 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1328 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1332 /* Test behavior when no files match the wildcard */
1333 strcpy(pathBuffer, BAD_EXTENSION);
1334 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1335 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1336 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1338 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1339 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1340 "DlgDirList() incorrectly filled the listbox!\n");
1343 /* Now test DlgDirSelectEx() in normal operation */
1344 /* Fill with everything - drives, directory and all plain files. */
1345 strcpy(pathBuffer, "*");
1346 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1347 DDL_DIRECTORY|DDL_DRIVES);
1348 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1350 SendMessage(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1351 memset(pathBuffer, 0, MAX_PATH);
1352 SetLastError(0xdeadbeef);
1353 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1354 ok (GetLastError() == 0xdeadbeef,
1355 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1356 GetLastError());
1357 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1358 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1360 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1362 /* Test proper drive/dir/file recognition */
1363 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1364 for (i = 0; i < itemCount; i++) {
1365 memset(itemBuffer, 0, MAX_PATH);
1366 memset(pathBuffer, 0, MAX_PATH);
1367 memset(tempBuffer, 0, MAX_PATH);
1368 driveletter = '\0';
1369 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1370 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1371 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1372 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1373 /* Current item is a drive letter */
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 == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1381 /* For drive letters, DlgDirSelectEx tacks on a colon */
1382 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1383 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1384 } else if (itemBuffer[0] == '[') {
1385 /* Current item is the parent directory */
1386 SetLastError(0xdeadbeef);
1387 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1388 ok (GetLastError() == 0xdeadbeef,
1389 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1390 i, GetLastError());
1391 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1393 /* For directories, DlgDirSelectEx tacks on a backslash */
1394 p = pathBuffer + strlen(pathBuffer);
1395 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1397 tempBuffer[0] = '[';
1398 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1399 strcat(tempBuffer, "]");
1400 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1401 } else {
1402 /* Current item is a plain file */
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 == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1410 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1411 * for example, "Makefile", which gets reported as "Makefile."
1413 strcpy(tempBuffer, itemBuffer);
1414 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1415 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1419 /* Now test DlgDirSelectEx() in abnormal operation */
1420 /* Fill list with bogus entries, that look somewhat valid */
1421 SendMessage(g_listBox, LB_RESETCONTENT, 0, 0);
1422 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1423 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1424 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1425 for (i = 0; i < itemCount; i++) {
1426 memset(itemBuffer, 0, MAX_PATH);
1427 memset(pathBuffer, 0, MAX_PATH);
1428 memset(tempBuffer, 0, MAX_PATH);
1429 driveletter = '\0';
1430 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1431 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1432 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1433 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1434 /* Current item is a drive letter */
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 == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1442 /* For drive letters, DlgDirSelectEx tacks on a colon */
1443 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1444 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1445 } else if (itemBuffer[0] == '[') {
1446 /* Current item is the parent directory */
1447 SetLastError(0xdeadbeef);
1448 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1449 ok (GetLastError() == 0xdeadbeef,
1450 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1451 i, GetLastError());
1452 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1454 /* For directories, DlgDirSelectEx tacks on a backslash */
1455 p = pathBuffer + strlen(pathBuffer);
1456 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1458 tempBuffer[0] = '[';
1459 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1460 strcat(tempBuffer, "]");
1461 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1462 } else {
1463 /* Current item is a plain file */
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 == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1471 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1472 * This affects for example, "Makefile", which gets reported as "Makefile."
1474 strcpy(tempBuffer, itemBuffer);
1475 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1476 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1479 DestroyWindow(hWnd);
1481 DeleteFileA( "wtest1.tmp.c" );
1484 START_TEST(listbox)
1486 const struct listbox_test SS =
1487 /* {add_style} */
1488 {{0},
1489 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1490 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1491 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1492 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1493 /* {selected, anchor, caret, selcount}{TODO fields} */
1494 const struct listbox_test SS_NS =
1495 {{LBS_NOSEL},
1496 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1497 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1498 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1499 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1500 const struct listbox_test MS =
1501 {{LBS_MULTIPLESEL},
1502 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1503 { 1, 1, 1, 1}, {0,0,0,0},
1504 { 2, 1, 2, 1}, {0,0,0,0},
1505 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1506 const struct listbox_test MS_NS =
1507 {{LBS_MULTIPLESEL | LBS_NOSEL},
1508 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1509 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1510 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1511 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1512 const struct listbox_test ES =
1513 {{LBS_EXTENDEDSEL},
1514 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1515 { 1, 1, 1, 1}, {0,0,0,0},
1516 { 2, 2, 2, 1}, {0,0,0,0},
1517 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1518 const struct listbox_test ES_NS =
1519 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1520 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1521 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1522 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1523 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1524 const struct listbox_test EMS =
1525 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1526 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1527 { 1, 1, 1, 1}, {0,0,0,0},
1528 { 2, 2, 2, 1}, {0,0,0,0},
1529 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1530 const struct listbox_test EMS_NS =
1531 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1532 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1533 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1534 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1535 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1537 trace (" Testing single selection...\n");
1538 check (SS);
1539 trace (" ... with NOSEL\n");
1540 check (SS_NS);
1541 trace (" Testing multiple selection...\n");
1542 check (MS);
1543 trace (" ... with NOSEL\n");
1544 check (MS_NS);
1545 trace (" Testing extended selection...\n");
1546 check (ES);
1547 trace (" ... with NOSEL\n");
1548 check (ES_NS);
1549 trace (" Testing extended and multiple selection...\n");
1550 check (EMS);
1551 trace (" ... with NOSEL\n");
1552 check (EMS_NS);
1554 check_item_height();
1555 test_ownerdraw();
1556 test_selection();
1557 test_listbox_height();
1558 test_itemfrompoint();
1559 test_listbox_item_data();
1560 test_listbox_LB_DIR();
1561 test_listbox_dlgdir();