push 8b07bf1f08b23b9893a622b47d2be359556765b1
[wine/hacks.git] / dlls / user32 / tests / listbox.c
blob942c7800f670595d8c4940fdd37847366e9ca003
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 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, (LPARAM)-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, (LPARAM)-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, (LPARAM)-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, (LPARAM)-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, (LPARAM)-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, (LPARAM)-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 p = pathBuffer + strlen(pathBuffer);
844 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
845 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
849 /* This tests behavior when no files match the wildcard */
850 strcpy(pathBuffer, BAD_EXTENSION);
851 SendMessage(hList, LB_RESETCONTENT, 0, 0);
852 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
853 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
854 BAD_EXTENSION, res, itemCount_justDrives -1);
856 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
857 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
861 /* Test DDL_DIRECTORY|DDL_DRIVES. */
862 strcpy(pathBuffer, "w*.c");
863 SendMessage(hList, LB_RESETCONTENT, 0, 0);
864 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
865 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
867 /* There should be some content in the listbox. In particular, there should
868 * be exactly the number of plain files, plus the number of mapped drives.
870 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
871 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
872 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
873 itemCount, itemCount_justFiles + itemCount_justDrives);
874 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
876 /* Every single item in the control should start with a w and end in .c,
877 * except the mapped drives in the format "[-X-]". The "[..]" directory
878 * should not appear.
880 for (i = 0; i < itemCount; i++) {
881 memset(pathBuffer, 0, MAX_PATH);
882 driveletter = '\0';
883 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
884 p = pathBuffer + strlen(pathBuffer);
885 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
886 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
887 } else {
889 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
890 (*(p-1) == 'c' || *(p-1) == 'C') &&
891 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
895 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
896 strcpy(pathBuffer, wildcard);
897 SendMessage(hList, LB_RESETCONTENT, 0, 0);
898 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
899 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError());
901 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
902 ok (itemCount == itemCount_allDirs,
903 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
904 itemCount, itemCount_allDirs);
905 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
907 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
909 memset(pathBuffer, 0, MAX_PATH);
910 SendMessage(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
911 ok( !strcmp(pathBuffer, "[..]"), "First element is not [..]\n");
914 /* This tests behavior when no files match the wildcard */
915 strcpy(pathBuffer, BAD_EXTENSION);
916 SendMessage(hList, LB_RESETCONTENT, 0, 0);
917 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
918 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
919 BAD_EXTENSION, res, -1);
921 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
922 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
925 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
926 strcpy(pathBuffer, "w*.c");
927 SendMessage(hList, LB_RESETCONTENT, 0, 0);
928 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
929 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
931 /* There should be no elements, since "[..]" does not fit w*.c */
932 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
933 ok (itemCount == 0,
934 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
935 itemCount, 0);
937 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
938 strcpy(pathBuffer, wildcard);
939 SendMessage(hList, LB_RESETCONTENT, 0, 0);
940 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
941 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
943 /* There should be no plain files on the listbox */
944 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
945 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
946 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
947 itemCount, itemCount_justDrives + itemCount_allDirs);
948 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
950 for (i = 0; i < itemCount; i++) {
951 memset(pathBuffer, 0, MAX_PATH);
952 driveletter = '\0';
953 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
954 p = pathBuffer + strlen(pathBuffer);
955 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
956 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
957 } else {
958 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
959 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
963 /* This tests behavior when no files match the wildcard */
964 strcpy(pathBuffer, BAD_EXTENSION);
965 SendMessage(hList, LB_RESETCONTENT, 0, 0);
966 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
967 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
968 BAD_EXTENSION, res, itemCount_justDrives -1);
970 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
971 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
973 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
974 strcpy(pathBuffer, "w*.c");
975 SendMessage(hList, LB_RESETCONTENT, 0, 0);
976 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
977 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
979 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
980 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
981 ok (itemCount == itemCount_justDrives,
982 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
983 itemCount, itemCount_justDrives);
984 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
986 for (i = 0; i < itemCount; i++) {
987 memset(pathBuffer, 0, MAX_PATH);
988 driveletter = '\0';
989 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
990 p = pathBuffer + strlen(pathBuffer);
991 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
992 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
994 DestroyWindow(hList);
996 DeleteFileA( "wtest1.tmp.c" );
999 HWND g_listBox;
1000 HWND g_label;
1002 #define ID_TEST_LABEL 1001
1003 #define ID_TEST_LISTBOX 1002
1005 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCT lpcs)
1007 g_label = CreateWindow(
1008 "Static",
1009 "Contents of static control before DlgDirList.",
1010 WS_CHILD | WS_VISIBLE,
1011 10, 10, 512, 32,
1012 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1013 if (!g_label) return FALSE;
1014 g_listBox = CreateWindow(
1015 "ListBox",
1016 "DlgDirList test",
1017 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1018 10, 60, 256, 256,
1019 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1020 if (!g_listBox) return FALSE;
1022 return TRUE;
1025 static LRESULT CALLBACK listbox_container_window_procA (
1026 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1028 LRESULT result = 0;
1030 switch (uiMsg) {
1031 case WM_DESTROY:
1032 PostQuitMessage(0);
1033 break;
1034 case WM_CREATE:
1035 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1036 ? 0 : (LRESULT)-1;
1037 break;
1038 default:
1039 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1040 break;
1042 return result;
1045 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1047 WNDCLASSA cls;
1049 cls.style = 0;
1050 cls.cbClsExtra = 0;
1051 cls.cbWndExtra = 0;
1052 cls.hInstance = hInst;
1053 cls.hIcon = NULL;
1054 cls.hCursor = LoadCursorA (NULL, IDC_ARROW);
1055 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1056 cls.lpszMenuName = NULL;
1057 cls.lpfnWndProc = listbox_container_window_procA;
1058 cls.lpszClassName = "ListboxContainerClass";
1059 if (!RegisterClassA (&cls)) return FALSE;
1061 return TRUE;
1064 static void test_listbox_dlgdir(void)
1066 HINSTANCE hInst;
1067 HWND hWnd;
1068 int res, itemCount;
1069 int itemCount_allDirs;
1070 int itemCount_justFiles;
1071 int itemCount_justDrives;
1072 int i;
1073 char pathBuffer[MAX_PATH];
1074 char itemBuffer[MAX_PATH];
1075 char tempBuffer[MAX_PATH];
1076 char * p;
1077 char driveletter;
1078 HANDLE file;
1080 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1081 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1082 CloseHandle( file );
1084 /* NOTE: for this test to succeed, there must be no subdirectories
1085 under the current directory. In addition, there must be at least
1086 one file that fits the wildcard w*.c . Normally, the test
1087 directory itself satisfies both conditions.
1090 hInst = GetModuleHandleA(0);
1091 if (!RegisterListboxWindowClass(hInst)) assert(0);
1092 hWnd = CreateWindow("ListboxContainerClass", "ListboxContainerClass",
1093 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1094 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1095 NULL, NULL, hInst, 0);
1096 assert(hWnd);
1098 /* Test for standard usage */
1100 /* The following should be overwritten by the directory path */
1101 SendMessage(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1103 /* This should list all the w*.c files in the test directory
1104 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1106 strcpy(pathBuffer, "w*.c");
1107 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1108 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1110 /* Path specification gets converted to uppercase */
1111 ok (!strcmp(pathBuffer, "W*.C"),
1112 "expected conversion to uppercase, got %s\n", pathBuffer);
1114 /* Loaded path should have overwritten the label text */
1115 SendMessage(g_label, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)pathBuffer);
1116 trace("Static control after DlgDirList: %s\n", pathBuffer);
1117 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1119 /* There should be some content in the listbox */
1120 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1121 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1122 itemCount_justFiles = itemCount;
1124 /* Every single item in the control should start with a w and end in .c */
1125 for (i = 0; i < itemCount; i++) {
1126 memset(pathBuffer, 0, MAX_PATH);
1127 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1128 p = pathBuffer + strlen(pathBuffer);
1129 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1130 (*(p-1) == 'c' || *(p-1) == 'C') &&
1131 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1134 /* Test behavior when no files match the wildcard */
1135 strcpy(pathBuffer, BAD_EXTENSION);
1136 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1137 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1139 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1140 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1142 /* Test DDL_DIRECTORY */
1143 strcpy(pathBuffer, "w*.c");
1144 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1145 DDL_DIRECTORY);
1146 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1148 /* There should be some content in the listbox. In particular, there should
1149 * be exactly more elements than before, since the directories should
1150 * have been added.
1152 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1153 itemCount_allDirs = itemCount - itemCount_justFiles;
1154 ok (itemCount >= itemCount_justFiles,
1155 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1156 itemCount, itemCount_justFiles);
1158 /* Every single item in the control should start with a w and end in .c,
1159 * except for the "[..]" string, which should appear exactly as it is.
1161 for (i = 0; i < itemCount; i++) {
1162 memset(pathBuffer, 0, MAX_PATH);
1163 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1164 p = pathBuffer + strlen(pathBuffer);
1165 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1166 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1167 (*(p-1) == 'c' || *(p-1) == 'C') &&
1168 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1171 /* Test behavior when no files match the wildcard */
1172 strcpy(pathBuffer, BAD_EXTENSION);
1173 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1174 DDL_DIRECTORY);
1175 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1177 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1178 ok (itemCount == itemCount_allDirs,
1179 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1180 itemCount_allDirs, itemCount);
1181 for (i = 0; i < itemCount; i++) {
1182 memset(pathBuffer, 0, MAX_PATH);
1183 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1184 p = pathBuffer + strlen(pathBuffer);
1185 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1186 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1190 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1191 strcpy(pathBuffer, "w*.c");
1192 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1193 DDL_DRIVES);
1194 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1196 /* There should be some content in the listbox. In particular, there should
1197 * be at least one element before, since the string "[-c-]" should
1198 * have been added. Depending on the user setting, more drives might have
1199 * been added.
1201 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1202 ok (itemCount >= 1,
1203 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1204 itemCount, 1);
1205 itemCount_justDrives = itemCount;
1207 /* Every single item in the control should fit the format [-c-] */
1208 for (i = 0; i < itemCount; i++) {
1209 memset(pathBuffer, 0, MAX_PATH);
1210 driveletter = '\0';
1211 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1212 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1213 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1214 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1215 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1216 /* Correct after invalid entry is found */
1217 trace("removing count of invalid entry %s\n", pathBuffer);
1218 itemCount_justDrives--;
1222 /* Test behavior when no files match the wildcard */
1223 strcpy(pathBuffer, BAD_EXTENSION);
1224 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1225 DDL_DRIVES);
1226 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1228 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1229 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1232 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1233 strcpy(pathBuffer, "w*.c");
1234 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1235 DDL_DIRECTORY|DDL_DRIVES);
1236 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1238 /* There should be some content in the listbox. In particular, there should
1239 * be exactly the number of plain files, plus the number of mapped drives,
1240 * plus one "[..]"
1242 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1243 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1244 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1245 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1247 /* Every single item in the control should start with a w and end in .c,
1248 * except for the "[..]" string, which should appear exactly as it is,
1249 * and the mapped drives in the format "[-X-]".
1251 for (i = 0; i < itemCount; i++) {
1252 memset(pathBuffer, 0, MAX_PATH);
1253 driveletter = '\0';
1254 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1255 p = pathBuffer + strlen(pathBuffer);
1256 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1257 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1258 } else {
1259 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1260 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1261 (*(p-1) == 'c' || *(p-1) == 'C') &&
1262 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1266 /* Test behavior when no files match the wildcard */
1267 strcpy(pathBuffer, BAD_EXTENSION);
1268 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1269 DDL_DIRECTORY|DDL_DRIVES);
1270 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1272 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1273 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1274 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1275 itemCount_justDrives + itemCount_allDirs, itemCount);
1279 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1280 strcpy(pathBuffer, "w*.c");
1281 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1282 DDL_DIRECTORY|DDL_EXCLUSIVE);
1283 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1285 /* There should be exactly one element: "[..]" */
1286 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1287 ok (itemCount == itemCount_allDirs,
1288 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1289 itemCount, itemCount_allDirs);
1291 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1293 memset(pathBuffer, 0, MAX_PATH);
1294 SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1295 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1298 /* Test behavior when no files match the wildcard */
1299 strcpy(pathBuffer, BAD_EXTENSION);
1300 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1301 DDL_DIRECTORY|DDL_EXCLUSIVE);
1302 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1304 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1305 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1308 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1309 strcpy(pathBuffer, "w*.c");
1310 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1311 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1312 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1314 /* There should be no plain files on the listbox */
1315 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1316 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1317 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1318 itemCount, itemCount_justDrives + itemCount_allDirs);
1320 for (i = 0; i < itemCount; i++) {
1321 memset(pathBuffer, 0, MAX_PATH);
1322 driveletter = '\0';
1323 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1324 p = pathBuffer + strlen(pathBuffer);
1325 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1326 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1327 } else {
1328 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1329 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1333 /* Test behavior when no files match the wildcard */
1334 strcpy(pathBuffer, BAD_EXTENSION);
1335 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1336 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1337 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1339 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1340 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1341 "DlgDirList() incorrectly filled the listbox!\n");
1344 /* Now test DlgDirSelectEx() in normal operation */
1345 /* Fill with everything - drives, directory and all plain files. */
1346 strcpy(pathBuffer, "*");
1347 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1348 DDL_DIRECTORY|DDL_DRIVES);
1349 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1351 SendMessage(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1352 memset(pathBuffer, 0, MAX_PATH);
1353 SetLastError(0xdeadbeef);
1354 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1355 ok (GetLastError() == 0xdeadbeef,
1356 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1357 GetLastError());
1358 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1359 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1361 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1363 /* Test proper drive/dir/file recognition */
1364 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1365 for (i = 0; i < itemCount; i++) {
1366 memset(itemBuffer, 0, MAX_PATH);
1367 memset(pathBuffer, 0, MAX_PATH);
1368 memset(tempBuffer, 0, MAX_PATH);
1369 driveletter = '\0';
1370 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1371 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1372 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1373 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1374 /* Current item is a drive letter */
1375 SetLastError(0xdeadbeef);
1376 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1377 ok (GetLastError() == 0xdeadbeef,
1378 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1379 i, GetLastError());
1380 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1382 /* For drive letters, DlgDirSelectEx tacks on a colon */
1383 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1384 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1385 } else if (itemBuffer[0] == '[') {
1386 /* Current item is the parent directory */
1387 SetLastError(0xdeadbeef);
1388 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1389 ok (GetLastError() == 0xdeadbeef,
1390 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1391 i, GetLastError());
1392 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1394 /* For directories, DlgDirSelectEx tacks on a backslash */
1395 p = pathBuffer + strlen(pathBuffer);
1396 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1398 tempBuffer[0] = '[';
1399 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1400 strcat(tempBuffer, "]");
1401 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1402 } else {
1403 /* Current item is a plain file */
1404 SetLastError(0xdeadbeef);
1405 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1406 ok (GetLastError() == 0xdeadbeef,
1407 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1408 i, GetLastError());
1409 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1411 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1412 * for example, "Makefile", which gets reported as "Makefile."
1414 strcpy(tempBuffer, itemBuffer);
1415 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1416 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1420 /* Now test DlgDirSelectEx() in abnormal operation */
1421 /* Fill list with bogus entries, that look somewhat valid */
1422 SendMessage(g_listBox, LB_RESETCONTENT, 0, 0);
1423 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1424 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1425 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1426 for (i = 0; i < itemCount; i++) {
1427 memset(itemBuffer, 0, MAX_PATH);
1428 memset(pathBuffer, 0, MAX_PATH);
1429 memset(tempBuffer, 0, MAX_PATH);
1430 driveletter = '\0';
1431 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1432 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1433 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1434 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1435 /* Current item is a drive letter */
1436 SetLastError(0xdeadbeef);
1437 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1438 ok (GetLastError() == 0xdeadbeef,
1439 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1440 i, GetLastError());
1441 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1443 /* For drive letters, DlgDirSelectEx tacks on a colon */
1444 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1445 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1446 } else if (itemBuffer[0] == '[') {
1447 /* Current item is the parent directory */
1448 SetLastError(0xdeadbeef);
1449 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1450 ok (GetLastError() == 0xdeadbeef,
1451 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1452 i, GetLastError());
1453 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1455 /* For directories, DlgDirSelectEx tacks on a backslash */
1456 p = pathBuffer + strlen(pathBuffer);
1457 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1459 tempBuffer[0] = '[';
1460 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1461 strcat(tempBuffer, "]");
1462 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1463 } else {
1464 /* Current item is a plain file */
1465 SetLastError(0xdeadbeef);
1466 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1467 ok (GetLastError() == 0xdeadbeef,
1468 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1469 i, GetLastError());
1470 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1472 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1473 * This affects for example, "Makefile", which gets reported as "Makefile."
1475 strcpy(tempBuffer, itemBuffer);
1476 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1477 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1480 DestroyWindow(hWnd);
1482 DeleteFileA( "wtest1.tmp.c" );
1485 START_TEST(listbox)
1487 const struct listbox_test SS =
1488 /* {add_style} */
1489 {{0},
1490 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1491 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1492 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1493 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1494 /* {selected, anchor, caret, selcount}{TODO fields} */
1495 const struct listbox_test SS_NS =
1496 {{LBS_NOSEL},
1497 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1498 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1499 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1500 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1501 const struct listbox_test MS =
1502 {{LBS_MULTIPLESEL},
1503 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1504 { 1, 1, 1, 1}, {0,0,0,0},
1505 { 2, 1, 2, 1}, {0,0,0,0},
1506 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1507 const struct listbox_test MS_NS =
1508 {{LBS_MULTIPLESEL | LBS_NOSEL},
1509 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1510 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1511 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1512 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1513 const struct listbox_test ES =
1514 {{LBS_EXTENDEDSEL},
1515 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1516 { 1, 1, 1, 1}, {0,0,0,0},
1517 { 2, 2, 2, 1}, {0,0,0,0},
1518 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1519 const struct listbox_test ES_NS =
1520 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1521 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1522 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1523 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1524 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1525 const struct listbox_test EMS =
1526 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1527 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1528 { 1, 1, 1, 1}, {0,0,0,0},
1529 { 2, 2, 2, 1}, {0,0,0,0},
1530 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1531 const struct listbox_test EMS_NS =
1532 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1533 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1534 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1535 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1536 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1538 trace (" Testing single selection...\n");
1539 check (SS);
1540 trace (" ... with NOSEL\n");
1541 check (SS_NS);
1542 trace (" Testing multiple selection...\n");
1543 check (MS);
1544 trace (" ... with NOSEL\n");
1545 check (MS_NS);
1546 trace (" Testing extended selection...\n");
1547 check (ES);
1548 trace (" ... with NOSEL\n");
1549 check (ES_NS);
1550 trace (" Testing extended and multiple selection...\n");
1551 check (EMS);
1552 trace (" ... with NOSEL\n");
1553 check (EMS_NS);
1555 check_item_height();
1556 test_ownerdraw();
1557 test_selection();
1558 test_listbox_height();
1559 test_itemfrompoint();
1560 test_listbox_item_data();
1561 test_listbox_LB_DIR();
1562 test_listbox_dlgdir();