push 9eb9af089d68d39110a91889d3a673043db63c4b
[wine/hacks.git] / dlls / user32 / tests / listbox.c
blob06cb44acf766cd054a314dbb7bd3acd72e5f5e17
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 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) (LPCTSTR) strings[0]);
63 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[1]);
64 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[2]);
65 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) 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, (LPSTR)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()
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 HANDLE file;
574 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
575 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
576 CloseHandle( file );
578 /* NOTE: for this test to succeed, there must be no subdirectories
579 under the current directory. In addition, there must be at least
580 one file that fits the wildcard w*.c . Normally, the test
581 directory itself satisfies both conditions.
583 hList = CreateWindow( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
584 1, 1, 600, 100, NULL, NULL, NULL, NULL );
585 assert(hList);
587 /* Test for standard usage */
589 /* This should list all the files in the test directory. */
590 strcpy(pathBuffer, "*");
591 SendMessage(hList, LB_RESETCONTENT, 0, 0);
592 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
593 if (res == -1) /* "*" wildcard doesn't work on win9x */
595 strcpy(pathBuffer, "*.*");
596 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
598 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
600 /* There should be some content in the listbox */
601 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
602 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
603 itemCount_allFiles = itemCount;
604 ok(res + 1 == itemCount,
605 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
606 itemCount - 1, res);
608 /* This tests behavior when no files match the wildcard */
609 strcpy(pathBuffer, BAD_EXTENSION);
610 SendMessage(hList, LB_RESETCONTENT, 0, 0);
611 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
612 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
614 /* There should be NO content in the listbox */
615 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
616 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
619 /* This should list all the w*.c files in the test directory
620 * As of this writing, this includes win.c, winstation.c, wsprintf.c
622 strcpy(pathBuffer, "w*.c");
623 SendMessage(hList, LB_RESETCONTENT, 0, 0);
624 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
625 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
627 /* Path specification does NOT converted to uppercase */
628 ok (!strcmp(pathBuffer, "w*.c"),
629 "expected no change to pathBuffer, got %s\n", pathBuffer);
631 /* There should be some content in the listbox */
632 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
633 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
634 itemCount_justFiles = itemCount;
635 ok(res + 1 == itemCount,
636 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
637 itemCount - 1, res);
639 /* Every single item in the control should start with a w and end in .c */
640 for (i = 0; i < itemCount; i++) {
641 memset(pathBuffer, 0, MAX_PATH);
642 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
643 p = pathBuffer + strlen(pathBuffer);
644 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
645 (*(p-1) == 'c' || *(p-1) == 'C') &&
646 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
649 /* Test DDL_DIRECTORY */
650 strcpy(pathBuffer, "*");
651 SendMessage(hList, LB_RESETCONTENT, 0, 0);
652 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
653 if (res == -1) /* "*" wildcard doesn't work on win9x */
655 strcpy(pathBuffer, "*.*");
656 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
658 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
660 /* There should be some content in the listbox.
661 * All files plus "[..]"
663 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
664 itemCount_allDirs = itemCount - itemCount_allFiles;
665 ok (itemCount > itemCount_allFiles,
666 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
667 itemCount, itemCount_allFiles);
668 ok(res + 1 == itemCount,
669 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
670 itemCount - 1, res);
672 /* This tests behavior when no files match the wildcard */
673 strcpy(pathBuffer, BAD_EXTENSION);
674 SendMessage(hList, LB_RESETCONTENT, 0, 0);
675 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
676 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
678 /* There should be NO content in the listbox */
679 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
680 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
683 /* Test DDL_DIRECTORY */
684 strcpy(pathBuffer, "w*.c");
685 SendMessage(hList, LB_RESETCONTENT, 0, 0);
686 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
687 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
689 /* There should be some content in the listbox. Since the parent directory does not
690 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
692 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
693 ok (itemCount == itemCount_justFiles,
694 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
695 itemCount, itemCount_justFiles);
696 ok(res + 1 == itemCount,
697 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
698 itemCount - 1, res);
700 /* Every single item in the control should start with a w and end in .c. */
701 for (i = 0; i < itemCount; i++) {
702 memset(pathBuffer, 0, MAX_PATH);
703 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
704 p = pathBuffer + strlen(pathBuffer);
706 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
707 (*(p-1) == 'c' || *(p-1) == 'C') &&
708 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
712 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
713 strcpy(pathBuffer, "*");
714 SendMessage(hList, LB_RESETCONTENT, 0, 0);
715 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
716 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
718 /* There should be some content in the listbox. In particular, there should
719 * be at least one element before, since the string "[-c-]" should
720 * have been added. Depending on the user setting, more drives might have
721 * been added.
723 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
724 ok (itemCount >= 1,
725 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
726 itemCount, 1);
727 itemCount_justDrives = itemCount;
728 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
730 /* Every single item in the control should fit the format [-c-] */
731 for (i = 0; i < itemCount; i++) {
732 memset(pathBuffer, 0, MAX_PATH);
733 driveletter = '\0';
734 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
735 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
736 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
737 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
738 if (!(driveletter >= 'a' && driveletter <= 'z')) {
739 /* Correct after invalid entry is found */
740 trace("removing count of invalid entry %s\n", pathBuffer);
741 itemCount_justDrives--;
745 /* This tests behavior when no files match the wildcard */
746 strcpy(pathBuffer, BAD_EXTENSION);
747 SendMessage(hList, LB_RESETCONTENT, 0, 0);
748 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
749 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
750 BAD_EXTENSION, res, itemCount_justDrives -1);
752 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
753 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
754 itemCount, itemCount_justDrives);
756 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
757 itemCount_justFiles, itemCount_justDrives);
759 /* Test DDL_DRIVES. */
760 strcpy(pathBuffer, "*");
761 SendMessage(hList, LB_RESETCONTENT, 0, 0);
762 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
763 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
765 /* There should be some content in the listbox. In particular, there should
766 * be at least one element before, since the string "[-c-]" should
767 * have been added. Depending on the user setting, more drives might have
768 * been added.
770 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
771 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
772 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
773 itemCount, itemCount_justDrives + itemCount_allFiles);
774 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
776 /* This tests behavior when no files match the wildcard */
777 strcpy(pathBuffer, BAD_EXTENSION);
778 SendMessage(hList, LB_RESETCONTENT, 0, 0);
779 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
780 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
781 BAD_EXTENSION, res, itemCount_justDrives -1);
783 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
784 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
787 /* Test DDL_DRIVES. */
788 strcpy(pathBuffer, "w*.c");
789 SendMessage(hList, LB_RESETCONTENT, 0, 0);
790 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
791 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
793 /* There should be some content in the listbox. In particular, there should
794 * be at least one element before, since the string "[-c-]" should
795 * have been added. Depending on the user setting, more drives might have
796 * been added.
798 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
799 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
800 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
801 itemCount, itemCount_justDrives + itemCount_justFiles);
802 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
804 /* Every single item in the control should fit the format [-c-], or w*.c */
805 for (i = 0; i < itemCount; i++) {
806 memset(pathBuffer, 0, MAX_PATH);
807 driveletter = '\0';
808 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
809 p = pathBuffer + strlen(pathBuffer);
810 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
811 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
812 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
813 } else {
815 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
816 (*(p-1) == 'c' || *(p-1) == 'C') &&
817 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
822 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
823 strcpy(pathBuffer, "*");
824 SendMessage(hList, LB_RESETCONTENT, 0, 0);
825 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
826 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
828 /* There should be some content in the listbox. In particular, there should
829 * be exactly the number of plain files, plus the number of mapped drives.
831 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
832 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
833 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
834 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
835 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
837 /* Every single item in the control should start with a w and end in .c,
838 * except for the "[..]" string, which should appear exactly as it is,
839 * and the mapped drives in the format "[-X-]".
841 for (i = 0; i < itemCount; i++) {
842 memset(pathBuffer, 0, MAX_PATH);
843 driveletter = '\0';
844 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
845 p = pathBuffer + strlen(pathBuffer);
846 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
847 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
851 /* This tests behavior when no files match the wildcard */
852 strcpy(pathBuffer, BAD_EXTENSION);
853 SendMessage(hList, LB_RESETCONTENT, 0, 0);
854 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
855 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
856 BAD_EXTENSION, res, itemCount_justDrives -1);
858 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
859 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
863 /* Test DDL_DIRECTORY|DDL_DRIVES. */
864 strcpy(pathBuffer, "w*.c");
865 SendMessage(hList, LB_RESETCONTENT, 0, 0);
866 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
867 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
869 /* There should be some content in the listbox. In particular, there should
870 * be exactly the number of plain files, plus the number of mapped drives.
872 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
873 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
874 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
875 itemCount, itemCount_justFiles + itemCount_justDrives);
876 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
878 /* Every single item in the control should start with a w and end in .c,
879 * except the mapped drives in the format "[-X-]". The "[..]" directory
880 * should not appear.
882 for (i = 0; i < itemCount; i++) {
883 memset(pathBuffer, 0, MAX_PATH);
884 driveletter = '\0';
885 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
886 p = pathBuffer + strlen(pathBuffer);
887 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
888 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
889 } else {
891 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
892 (*(p-1) == 'c' || *(p-1) == 'C') &&
893 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
897 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
898 strcpy(pathBuffer, "*");
899 SendMessage(hList, LB_RESETCONTENT, 0, 0);
900 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
901 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError());
903 /* There should be exactly one element: "[..]" */
904 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
905 ok (itemCount == itemCount_allDirs,
906 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
907 itemCount, itemCount_allDirs);
908 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
910 memset(pathBuffer, 0, MAX_PATH);
911 SendMessage(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
912 ok( !strcmp(pathBuffer, "[..]"), "First (and only) 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, "*");
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 memset(pathBuffer, 0, MAX_PATH);
1292 SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1293 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1296 /* Test behavior when no files match the wildcard */
1297 strcpy(pathBuffer, BAD_EXTENSION);
1298 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1299 DDL_DIRECTORY|DDL_EXCLUSIVE);
1300 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1302 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1303 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1306 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1307 strcpy(pathBuffer, "w*.c");
1308 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1309 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1310 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1312 /* There should be no plain files on the listbox */
1313 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1314 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1315 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1316 itemCount, itemCount_justDrives + itemCount_allDirs);
1318 for (i = 0; i < itemCount; i++) {
1319 memset(pathBuffer, 0, MAX_PATH);
1320 driveletter = '\0';
1321 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1322 p = pathBuffer + strlen(pathBuffer);
1323 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1324 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1325 } else {
1326 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1327 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1331 /* Test behavior when no files match the wildcard */
1332 strcpy(pathBuffer, BAD_EXTENSION);
1333 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1334 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1335 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1337 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1338 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1339 "DlgDirList() incorrectly filled the listbox!\n");
1342 /* Now test DlgDirSelectEx() in normal operation */
1343 /* Fill with everything - drives, directory and all plain files. */
1344 strcpy(pathBuffer, "*");
1345 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1346 DDL_DIRECTORY|DDL_DRIVES);
1347 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1349 SendMessage(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1350 memset(pathBuffer, 0, MAX_PATH);
1351 SetLastError(0xdeadbeef);
1352 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1353 ok (GetLastError() == 0xdeadbeef,
1354 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1355 GetLastError());
1356 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1357 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1359 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1361 /* Test proper drive/dir/file recognition */
1362 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1363 for (i = 0; i < itemCount; i++) {
1364 memset(itemBuffer, 0, MAX_PATH);
1365 memset(pathBuffer, 0, MAX_PATH);
1366 memset(tempBuffer, 0, MAX_PATH);
1367 driveletter = '\0';
1368 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1369 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1370 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1371 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1372 /* Current item is a drive letter */
1373 SetLastError(0xdeadbeef);
1374 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1375 ok (GetLastError() == 0xdeadbeef,
1376 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1377 i, GetLastError());
1378 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1380 /* For drive letters, DlgDirSelectEx tacks on a colon */
1381 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1382 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1383 } else if (itemBuffer[0] == '[') {
1384 /* Current item is the parent directory */
1385 SetLastError(0xdeadbeef);
1386 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1387 ok (GetLastError() == 0xdeadbeef,
1388 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1389 i, GetLastError());
1390 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1392 /* For directories, DlgDirSelectEx tacks on a backslash */
1393 p = pathBuffer + strlen(pathBuffer);
1394 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1396 tempBuffer[0] = '[';
1397 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1398 strcat(tempBuffer, "]");
1399 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1400 } else {
1401 /* Current item is a plain file */
1402 SetLastError(0xdeadbeef);
1403 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1404 ok (GetLastError() == 0xdeadbeef,
1405 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1406 i, GetLastError());
1407 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1409 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1410 * for example, "Makefile", which gets reported as "Makefile."
1412 strcpy(tempBuffer, itemBuffer);
1413 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1414 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1418 /* Now test DlgDirSelectEx() in abnormal operation */
1419 /* Fill list with bogus entries, that look somewhat valid */
1420 SendMessage(g_listBox, LB_RESETCONTENT, 0, 0);
1421 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1422 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1423 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1424 for (i = 0; i < itemCount; i++) {
1425 memset(itemBuffer, 0, MAX_PATH);
1426 memset(pathBuffer, 0, MAX_PATH);
1427 memset(tempBuffer, 0, MAX_PATH);
1428 driveletter = '\0';
1429 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1430 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1431 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1432 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1433 /* Current item is a drive letter */
1434 SetLastError(0xdeadbeef);
1435 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1436 ok (GetLastError() == 0xdeadbeef,
1437 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1438 i, GetLastError());
1439 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1441 /* For drive letters, DlgDirSelectEx tacks on a colon */
1442 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1443 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1444 } else if (itemBuffer[0] == '[') {
1445 /* Current item is the parent directory */
1446 SetLastError(0xdeadbeef);
1447 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1448 ok (GetLastError() == 0xdeadbeef,
1449 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1450 i, GetLastError());
1451 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1453 /* For directories, DlgDirSelectEx tacks on a backslash */
1454 p = pathBuffer + strlen(pathBuffer);
1455 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1457 tempBuffer[0] = '[';
1458 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1459 strcat(tempBuffer, "]");
1460 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1461 } else {
1462 /* Current item is a plain file */
1463 SetLastError(0xdeadbeef);
1464 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1465 ok (GetLastError() == 0xdeadbeef,
1466 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1467 i, GetLastError());
1468 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1470 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1471 * This affects for example, "Makefile", which gets reported as "Makefile."
1473 strcpy(tempBuffer, itemBuffer);
1474 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1475 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1478 DestroyWindow(hWnd);
1480 DeleteFileA( "wtest1.tmp.c" );
1483 START_TEST(listbox)
1485 const struct listbox_test SS =
1486 /* {add_style} */
1487 {{0},
1488 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1489 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1490 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1491 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1492 /* {selected, anchor, caret, selcount}{TODO fields} */
1493 const struct listbox_test SS_NS =
1494 {{LBS_NOSEL},
1495 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1496 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1497 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1498 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1499 const struct listbox_test MS =
1500 {{LBS_MULTIPLESEL},
1501 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1502 { 1, 1, 1, 1}, {0,0,0,0},
1503 { 2, 1, 2, 1}, {0,0,0,0},
1504 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1505 const struct listbox_test MS_NS =
1506 {{LBS_MULTIPLESEL | LBS_NOSEL},
1507 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1508 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1509 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1510 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1511 const struct listbox_test ES =
1512 {{LBS_EXTENDEDSEL},
1513 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1514 { 1, 1, 1, 1}, {0,0,0,0},
1515 { 2, 2, 2, 1}, {0,0,0,0},
1516 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1517 const struct listbox_test ES_NS =
1518 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1519 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1520 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1521 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1522 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1523 const struct listbox_test EMS =
1524 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1525 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1526 { 1, 1, 1, 1}, {0,0,0,0},
1527 { 2, 2, 2, 1}, {0,0,0,0},
1528 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1529 const struct listbox_test EMS_NS =
1530 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1531 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1532 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1533 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1534 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1536 trace (" Testing single selection...\n");
1537 check (SS);
1538 trace (" ... with NOSEL\n");
1539 check (SS_NS);
1540 trace (" Testing multiple selection...\n");
1541 check (MS);
1542 trace (" ... with NOSEL\n");
1543 check (MS_NS);
1544 trace (" Testing extended selection...\n");
1545 check (ES);
1546 trace (" ... with NOSEL\n");
1547 check (ES_NS);
1548 trace (" Testing extended and multiple selection...\n");
1549 check (EMS);
1550 trace (" ... with NOSEL\n");
1551 check (EMS_NS);
1553 check_item_height();
1554 test_ownerdraw();
1555 test_selection();
1556 test_listbox_height();
1557 test_itemfrompoint();
1558 test_listbox_item_data();
1559 test_listbox_LB_DIR();
1560 test_listbox_dlgdir();