push 07a2b33f792746135ccf34a3b3e1dfb2a3c1e823
[wine/hacks.git] / dlls / user32 / tests / listbox.c
blobc87235763355853364c4ed7521f6c6b4d58c00d5
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(void)
562 HWND hList;
563 int res, itemCount;
564 int itemCount_justFiles;
565 int itemCount_justDrives;
566 int itemCount_allFiles;
567 int itemCount_allDirs;
568 int i;
569 char pathBuffer[MAX_PATH];
570 char * p;
571 char driveletter;
572 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 || res <= itemCount_allFiles) /* "*" wildcard doesn't work on win9x */
655 strcpy(pathBuffer, "*.*");
656 SendMessage(hList, LB_RESETCONTENT, 0, 0);
657 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
659 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
661 /* There should be some content in the listbox.
662 * All files plus "[..]"
664 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
665 itemCount_allDirs = itemCount - itemCount_allFiles;
666 ok (itemCount > itemCount_allFiles,
667 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
668 itemCount, itemCount_allFiles);
669 ok(res + 1 == itemCount,
670 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
671 itemCount - 1, res);
673 /* This tests behavior when no files match the wildcard */
674 strcpy(pathBuffer, BAD_EXTENSION);
675 SendMessage(hList, LB_RESETCONTENT, 0, 0);
676 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
677 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
679 /* There should be NO content in the listbox */
680 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
681 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
684 /* Test DDL_DIRECTORY */
685 strcpy(pathBuffer, "w*.c");
686 SendMessage(hList, LB_RESETCONTENT, 0, 0);
687 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
688 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
690 /* There should be some content in the listbox. Since the parent directory does not
691 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
693 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
694 ok (itemCount == itemCount_justFiles,
695 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
696 itemCount, itemCount_justFiles);
697 ok(res + 1 == itemCount,
698 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
699 itemCount - 1, res);
701 /* Every single item in the control should start with a w and end in .c. */
702 for (i = 0; i < itemCount; i++) {
703 memset(pathBuffer, 0, MAX_PATH);
704 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
705 p = pathBuffer + strlen(pathBuffer);
707 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
708 (*(p-1) == 'c' || *(p-1) == 'C') &&
709 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
713 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
714 strcpy(pathBuffer, "*");
715 SendMessage(hList, LB_RESETCONTENT, 0, 0);
716 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
717 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
719 /* There should be some content in the listbox. In particular, there should
720 * be at least one element before, since the string "[-c-]" should
721 * have been added. Depending on the user setting, more drives might have
722 * been added.
724 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
725 ok (itemCount >= 1,
726 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
727 itemCount, 1);
728 itemCount_justDrives = itemCount;
729 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
731 /* Every single item in the control should fit the format [-c-] */
732 for (i = 0; i < itemCount; i++) {
733 memset(pathBuffer, 0, MAX_PATH);
734 driveletter = '\0';
735 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
736 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
737 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
738 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
739 if (!(driveletter >= 'a' && driveletter <= 'z')) {
740 /* Correct after invalid entry is found */
741 trace("removing count of invalid entry %s\n", pathBuffer);
742 itemCount_justDrives--;
746 /* This tests behavior when no files match the wildcard */
747 strcpy(pathBuffer, BAD_EXTENSION);
748 SendMessage(hList, LB_RESETCONTENT, 0, 0);
749 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
750 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
751 BAD_EXTENSION, res, itemCount_justDrives -1);
753 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
754 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
755 itemCount, itemCount_justDrives);
757 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
758 itemCount_justFiles, itemCount_justDrives);
760 /* Test DDL_DRIVES. */
761 strcpy(pathBuffer, "*");
762 SendMessage(hList, LB_RESETCONTENT, 0, 0);
763 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
764 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
766 /* There should be some content in the listbox. In particular, there should
767 * be at least one element before, since the string "[-c-]" should
768 * have been added. Depending on the user setting, more drives might have
769 * been added.
771 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
772 ok (itemCount == itemCount_justDrives + itemCount_allFiles ||
773 broken(itemCount == itemCount_justDrives), /* "*" wildcard broken on win9x */
774 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
775 itemCount, itemCount_justDrives + itemCount_allFiles);
776 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
778 /* This tests behavior when no files match the wildcard */
779 strcpy(pathBuffer, BAD_EXTENSION);
780 SendMessage(hList, LB_RESETCONTENT, 0, 0);
781 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
782 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
783 BAD_EXTENSION, res, itemCount_justDrives -1);
785 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
786 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
789 /* Test DDL_DRIVES. */
790 strcpy(pathBuffer, "w*.c");
791 SendMessage(hList, LB_RESETCONTENT, 0, 0);
792 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
793 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
795 /* There should be some content in the listbox. In particular, there should
796 * be at least one element before, since the string "[-c-]" should
797 * have been added. Depending on the user setting, more drives might have
798 * been added.
800 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
801 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
802 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
803 itemCount, itemCount_justDrives + itemCount_justFiles);
804 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
806 /* Every single item in the control should fit the format [-c-], or w*.c */
807 for (i = 0; i < itemCount; i++) {
808 memset(pathBuffer, 0, MAX_PATH);
809 driveletter = '\0';
810 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
811 p = pathBuffer + strlen(pathBuffer);
812 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
813 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
814 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
815 } else {
817 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
818 (*(p-1) == 'c' || *(p-1) == 'C') &&
819 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
824 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
825 strcpy(pathBuffer, "*");
826 SendMessage(hList, LB_RESETCONTENT, 0, 0);
827 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
828 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
830 /* There should be some content in the listbox. In particular, there should
831 * be exactly the number of plain files, plus the number of mapped drives.
833 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
834 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs ||
835 broken(itemCount == itemCount_justDrives + itemCount_allDirs), /* "*" wildcard broken on win9x */
836 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
837 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
838 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
840 /* Every single item in the control should start with a w and end in .c,
841 * except for the "[..]" string, which should appear exactly as it is,
842 * and the mapped drives in the format "[-X-]".
844 for (i = 0; i < itemCount; i++) {
845 memset(pathBuffer, 0, MAX_PATH);
846 driveletter = '\0';
847 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
848 p = pathBuffer + strlen(pathBuffer);
849 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
850 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
854 /* This tests behavior when no files match the wildcard */
855 strcpy(pathBuffer, BAD_EXTENSION);
856 SendMessage(hList, LB_RESETCONTENT, 0, 0);
857 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
858 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
859 BAD_EXTENSION, res, itemCount_justDrives -1);
861 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
862 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
866 /* Test DDL_DIRECTORY|DDL_DRIVES. */
867 strcpy(pathBuffer, "w*.c");
868 SendMessage(hList, LB_RESETCONTENT, 0, 0);
869 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
870 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
872 /* There should be some content in the listbox. In particular, there should
873 * be exactly the number of plain files, plus the number of mapped drives.
875 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
876 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
877 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
878 itemCount, itemCount_justFiles + itemCount_justDrives);
879 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
881 /* Every single item in the control should start with a w and end in .c,
882 * except the mapped drives in the format "[-X-]". The "[..]" directory
883 * should not appear.
885 for (i = 0; i < itemCount; i++) {
886 memset(pathBuffer, 0, MAX_PATH);
887 driveletter = '\0';
888 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
889 p = pathBuffer + strlen(pathBuffer);
890 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
891 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
892 } else {
894 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
895 (*(p-1) == 'c' || *(p-1) == 'C') &&
896 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
900 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
901 strcpy(pathBuffer, "*");
902 SendMessage(hList, LB_RESETCONTENT, 0, 0);
903 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
904 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError());
906 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
907 ok (itemCount == itemCount_allDirs,
908 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
909 itemCount, itemCount_allDirs);
910 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
912 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
914 memset(pathBuffer, 0, MAX_PATH);
915 SendMessage(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
916 ok( !strcmp(pathBuffer, "[..]"), "First element is not [..]\n");
919 /* This tests behavior when no files match the wildcard */
920 strcpy(pathBuffer, BAD_EXTENSION);
921 SendMessage(hList, LB_RESETCONTENT, 0, 0);
922 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
923 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
924 BAD_EXTENSION, res, -1);
926 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
927 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
930 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
931 strcpy(pathBuffer, "w*.c");
932 SendMessage(hList, LB_RESETCONTENT, 0, 0);
933 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
934 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
936 /* There should be no elements, since "[..]" does not fit w*.c */
937 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
938 ok (itemCount == 0,
939 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
940 itemCount, 0);
942 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
943 strcpy(pathBuffer, "*");
944 SendMessage(hList, LB_RESETCONTENT, 0, 0);
945 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
946 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
948 /* There should be no plain files on the listbox */
949 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
950 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
951 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
952 itemCount, itemCount_justDrives + itemCount_allDirs);
953 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
955 for (i = 0; i < itemCount; i++) {
956 memset(pathBuffer, 0, MAX_PATH);
957 driveletter = '\0';
958 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
959 p = pathBuffer + strlen(pathBuffer);
960 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
961 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
962 } else {
963 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
964 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
968 /* This tests behavior when no files match the wildcard */
969 strcpy(pathBuffer, BAD_EXTENSION);
970 SendMessage(hList, LB_RESETCONTENT, 0, 0);
971 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
972 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
973 BAD_EXTENSION, res, itemCount_justDrives -1);
975 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
976 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
978 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
979 strcpy(pathBuffer, "w*.c");
980 SendMessage(hList, LB_RESETCONTENT, 0, 0);
981 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
982 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
984 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
985 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
986 ok (itemCount == itemCount_justDrives,
987 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
988 itemCount, itemCount_justDrives);
989 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
991 for (i = 0; i < itemCount; i++) {
992 memset(pathBuffer, 0, MAX_PATH);
993 driveletter = '\0';
994 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
995 p = pathBuffer + strlen(pathBuffer);
996 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
997 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
999 DestroyWindow(hList);
1001 DeleteFileA( "wtest1.tmp.c" );
1004 HWND g_listBox;
1005 HWND g_label;
1007 #define ID_TEST_LABEL 1001
1008 #define ID_TEST_LISTBOX 1002
1010 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCT lpcs)
1012 g_label = CreateWindow(
1013 "Static",
1014 "Contents of static control before DlgDirList.",
1015 WS_CHILD | WS_VISIBLE,
1016 10, 10, 512, 32,
1017 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1018 if (!g_label) return FALSE;
1019 g_listBox = CreateWindow(
1020 "ListBox",
1021 "DlgDirList test",
1022 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1023 10, 60, 256, 256,
1024 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1025 if (!g_listBox) return FALSE;
1027 return TRUE;
1030 static LRESULT CALLBACK listbox_container_window_procA (
1031 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1033 LRESULT result = 0;
1035 switch (uiMsg) {
1036 case WM_DESTROY:
1037 PostQuitMessage(0);
1038 break;
1039 case WM_CREATE:
1040 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1041 ? 0 : (LRESULT)-1;
1042 break;
1043 default:
1044 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1045 break;
1047 return result;
1050 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1052 WNDCLASSA cls;
1054 cls.style = 0;
1055 cls.cbClsExtra = 0;
1056 cls.cbWndExtra = 0;
1057 cls.hInstance = hInst;
1058 cls.hIcon = NULL;
1059 cls.hCursor = LoadCursorA (NULL, IDC_ARROW);
1060 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1061 cls.lpszMenuName = NULL;
1062 cls.lpfnWndProc = listbox_container_window_procA;
1063 cls.lpszClassName = "ListboxContainerClass";
1064 if (!RegisterClassA (&cls)) return FALSE;
1066 return TRUE;
1069 static void test_listbox_dlgdir(void)
1071 HINSTANCE hInst;
1072 HWND hWnd;
1073 int res, itemCount;
1074 int itemCount_allDirs;
1075 int itemCount_justFiles;
1076 int itemCount_justDrives;
1077 int i;
1078 char pathBuffer[MAX_PATH];
1079 char itemBuffer[MAX_PATH];
1080 char tempBuffer[MAX_PATH];
1081 char * p;
1082 char driveletter;
1083 HANDLE file;
1085 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1086 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1087 CloseHandle( file );
1089 /* NOTE: for this test to succeed, there must be no subdirectories
1090 under the current directory. In addition, there must be at least
1091 one file that fits the wildcard w*.c . Normally, the test
1092 directory itself satisfies both conditions.
1095 hInst = GetModuleHandleA(0);
1096 if (!RegisterListboxWindowClass(hInst)) assert(0);
1097 hWnd = CreateWindow("ListboxContainerClass", "ListboxContainerClass",
1098 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1099 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1100 NULL, NULL, hInst, 0);
1101 assert(hWnd);
1103 /* Test for standard usage */
1105 /* The following should be overwritten by the directory path */
1106 SendMessage(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1108 /* This should list all the w*.c files in the test directory
1109 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1111 strcpy(pathBuffer, "w*.c");
1112 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1113 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1115 /* Path specification gets converted to uppercase */
1116 ok (!strcmp(pathBuffer, "W*.C"),
1117 "expected conversion to uppercase, got %s\n", pathBuffer);
1119 /* Loaded path should have overwritten the label text */
1120 SendMessage(g_label, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)pathBuffer);
1121 trace("Static control after DlgDirList: %s\n", pathBuffer);
1122 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1124 /* There should be some content in the listbox */
1125 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1126 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1127 itemCount_justFiles = itemCount;
1129 /* Every single item in the control should start with a w and end in .c */
1130 for (i = 0; i < itemCount; i++) {
1131 memset(pathBuffer, 0, MAX_PATH);
1132 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1133 p = pathBuffer + strlen(pathBuffer);
1134 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1135 (*(p-1) == 'c' || *(p-1) == 'C') &&
1136 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1139 /* Test behavior when no files match the wildcard */
1140 strcpy(pathBuffer, BAD_EXTENSION);
1141 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1142 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1144 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1145 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1147 /* Test DDL_DIRECTORY */
1148 strcpy(pathBuffer, "w*.c");
1149 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1150 DDL_DIRECTORY);
1151 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1153 /* There should be some content in the listbox. In particular, there should
1154 * be exactly more elements than before, since the directories should
1155 * have been added.
1157 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1158 itemCount_allDirs = itemCount - itemCount_justFiles;
1159 ok (itemCount >= itemCount_justFiles,
1160 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1161 itemCount, itemCount_justFiles);
1163 /* Every single item in the control should start with a w and end in .c,
1164 * except for the "[..]" string, which should appear exactly as it is.
1166 for (i = 0; i < itemCount; i++) {
1167 memset(pathBuffer, 0, MAX_PATH);
1168 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1169 p = pathBuffer + strlen(pathBuffer);
1170 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1171 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1172 (*(p-1) == 'c' || *(p-1) == 'C') &&
1173 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1176 /* Test behavior when no files match the wildcard */
1177 strcpy(pathBuffer, BAD_EXTENSION);
1178 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1179 DDL_DIRECTORY);
1180 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1182 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1183 ok (itemCount == itemCount_allDirs,
1184 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1185 itemCount_allDirs, itemCount);
1186 for (i = 0; i < itemCount; i++) {
1187 memset(pathBuffer, 0, MAX_PATH);
1188 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1189 p = pathBuffer + strlen(pathBuffer);
1190 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1191 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1195 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1196 strcpy(pathBuffer, "w*.c");
1197 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1198 DDL_DRIVES);
1199 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1201 /* There should be some content in the listbox. In particular, there should
1202 * be at least one element before, since the string "[-c-]" should
1203 * have been added. Depending on the user setting, more drives might have
1204 * been added.
1206 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1207 ok (itemCount >= 1,
1208 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1209 itemCount, 1);
1210 itemCount_justDrives = itemCount;
1212 /* Every single item in the control should fit the format [-c-] */
1213 for (i = 0; i < itemCount; i++) {
1214 memset(pathBuffer, 0, MAX_PATH);
1215 driveletter = '\0';
1216 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1217 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1218 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1219 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1220 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1221 /* Correct after invalid entry is found */
1222 trace("removing count of invalid entry %s\n", pathBuffer);
1223 itemCount_justDrives--;
1227 /* Test behavior when no files match the wildcard */
1228 strcpy(pathBuffer, BAD_EXTENSION);
1229 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1230 DDL_DRIVES);
1231 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1233 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1234 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1237 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1238 strcpy(pathBuffer, "w*.c");
1239 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1240 DDL_DIRECTORY|DDL_DRIVES);
1241 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1243 /* There should be some content in the listbox. In particular, there should
1244 * be exactly the number of plain files, plus the number of mapped drives,
1245 * plus one "[..]"
1247 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1248 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1249 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1250 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1252 /* Every single item in the control should start with a w and end in .c,
1253 * except for the "[..]" string, which should appear exactly as it is,
1254 * and the mapped drives in the format "[-X-]".
1256 for (i = 0; i < itemCount; i++) {
1257 memset(pathBuffer, 0, MAX_PATH);
1258 driveletter = '\0';
1259 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1260 p = pathBuffer + strlen(pathBuffer);
1261 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1262 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1263 } else {
1264 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1265 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1266 (*(p-1) == 'c' || *(p-1) == 'C') &&
1267 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1271 /* Test behavior when no files match the wildcard */
1272 strcpy(pathBuffer, BAD_EXTENSION);
1273 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1274 DDL_DIRECTORY|DDL_DRIVES);
1275 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1277 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1278 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1279 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1280 itemCount_justDrives + itemCount_allDirs, itemCount);
1284 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1285 strcpy(pathBuffer, "w*.c");
1286 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1287 DDL_DIRECTORY|DDL_EXCLUSIVE);
1288 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1290 /* There should be exactly one element: "[..]" */
1291 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1292 ok (itemCount == itemCount_allDirs,
1293 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1294 itemCount, itemCount_allDirs);
1296 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1298 memset(pathBuffer, 0, MAX_PATH);
1299 SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1300 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1303 /* Test behavior when no files match the wildcard */
1304 strcpy(pathBuffer, BAD_EXTENSION);
1305 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1306 DDL_DIRECTORY|DDL_EXCLUSIVE);
1307 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1309 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1310 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1313 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1314 strcpy(pathBuffer, "w*.c");
1315 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1316 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1317 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1319 /* There should be no plain files on the listbox */
1320 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1321 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1322 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1323 itemCount, itemCount_justDrives + itemCount_allDirs);
1325 for (i = 0; i < itemCount; i++) {
1326 memset(pathBuffer, 0, MAX_PATH);
1327 driveletter = '\0';
1328 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1329 p = pathBuffer + strlen(pathBuffer);
1330 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1331 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1332 } else {
1333 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1334 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1338 /* Test behavior when no files match the wildcard */
1339 strcpy(pathBuffer, BAD_EXTENSION);
1340 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1341 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1342 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1344 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1345 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1346 "DlgDirList() incorrectly filled the listbox!\n");
1349 /* Now test DlgDirSelectEx() in normal operation */
1350 /* Fill with everything - drives, directory and all plain files. */
1351 strcpy(pathBuffer, "*");
1352 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1353 DDL_DIRECTORY|DDL_DRIVES);
1354 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1356 SendMessage(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1357 memset(pathBuffer, 0, MAX_PATH);
1358 SetLastError(0xdeadbeef);
1359 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1360 ok (GetLastError() == 0xdeadbeef,
1361 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1362 GetLastError());
1363 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1364 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1366 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1368 /* Test proper drive/dir/file recognition */
1369 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1370 for (i = 0; i < itemCount; i++) {
1371 memset(itemBuffer, 0, MAX_PATH);
1372 memset(pathBuffer, 0, MAX_PATH);
1373 memset(tempBuffer, 0, MAX_PATH);
1374 driveletter = '\0';
1375 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1376 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1377 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1378 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1379 /* Current item is a drive letter */
1380 SetLastError(0xdeadbeef);
1381 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1382 ok (GetLastError() == 0xdeadbeef,
1383 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1384 i, GetLastError());
1385 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1387 /* For drive letters, DlgDirSelectEx tacks on a colon */
1388 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1389 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1390 } else if (itemBuffer[0] == '[') {
1391 /* Current item is the parent directory */
1392 SetLastError(0xdeadbeef);
1393 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1394 ok (GetLastError() == 0xdeadbeef,
1395 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1396 i, GetLastError());
1397 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1399 /* For directories, DlgDirSelectEx tacks on a backslash */
1400 p = pathBuffer + strlen(pathBuffer);
1401 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1403 tempBuffer[0] = '[';
1404 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1405 strcat(tempBuffer, "]");
1406 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1407 } else {
1408 /* Current item is a plain file */
1409 SetLastError(0xdeadbeef);
1410 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1411 ok (GetLastError() == 0xdeadbeef,
1412 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1413 i, GetLastError());
1414 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1416 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1417 * for example, "Makefile", which gets reported as "Makefile."
1419 strcpy(tempBuffer, itemBuffer);
1420 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1421 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1425 /* Now test DlgDirSelectEx() in abnormal operation */
1426 /* Fill list with bogus entries, that look somewhat valid */
1427 SendMessage(g_listBox, LB_RESETCONTENT, 0, 0);
1428 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1429 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1430 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1431 for (i = 0; i < itemCount; i++) {
1432 memset(itemBuffer, 0, MAX_PATH);
1433 memset(pathBuffer, 0, MAX_PATH);
1434 memset(tempBuffer, 0, MAX_PATH);
1435 driveletter = '\0';
1436 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1437 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1438 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1439 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1440 /* Current item is a drive letter */
1441 SetLastError(0xdeadbeef);
1442 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1443 ok (GetLastError() == 0xdeadbeef,
1444 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1445 i, GetLastError());
1446 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1448 /* For drive letters, DlgDirSelectEx tacks on a colon */
1449 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1450 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1451 } else if (itemBuffer[0] == '[') {
1452 /* Current item is the parent directory */
1453 SetLastError(0xdeadbeef);
1454 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1455 ok (GetLastError() == 0xdeadbeef,
1456 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1457 i, GetLastError());
1458 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1460 /* For directories, DlgDirSelectEx tacks on a backslash */
1461 p = pathBuffer + strlen(pathBuffer);
1462 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1464 tempBuffer[0] = '[';
1465 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1466 strcat(tempBuffer, "]");
1467 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1468 } else {
1469 /* Current item is a plain file */
1470 SetLastError(0xdeadbeef);
1471 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1472 ok (GetLastError() == 0xdeadbeef,
1473 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1474 i, GetLastError());
1475 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1477 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1478 * This affects for example, "Makefile", which gets reported as "Makefile."
1480 strcpy(tempBuffer, itemBuffer);
1481 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1482 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1485 DestroyWindow(hWnd);
1487 DeleteFileA( "wtest1.tmp.c" );
1490 START_TEST(listbox)
1492 const struct listbox_test SS =
1493 /* {add_style} */
1494 {{0},
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 /* {selected, anchor, caret, selcount}{TODO fields} */
1500 const struct listbox_test SS_NS =
1501 {{LBS_NOSEL},
1502 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1503 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1504 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1505 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1506 const struct listbox_test MS =
1507 {{LBS_MULTIPLESEL},
1508 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1509 { 1, 1, 1, 1}, {0,0,0,0},
1510 { 2, 1, 2, 1}, {0,0,0,0},
1511 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1512 const struct listbox_test MS_NS =
1513 {{LBS_MULTIPLESEL | LBS_NOSEL},
1514 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1515 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1516 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1517 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1518 const struct listbox_test ES =
1519 {{LBS_EXTENDEDSEL},
1520 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1521 { 1, 1, 1, 1}, {0,0,0,0},
1522 { 2, 2, 2, 1}, {0,0,0,0},
1523 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1524 const struct listbox_test ES_NS =
1525 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1526 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1527 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1528 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1529 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1530 const struct listbox_test EMS =
1531 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1532 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1533 { 1, 1, 1, 1}, {0,0,0,0},
1534 { 2, 2, 2, 1}, {0,0,0,0},
1535 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1536 const struct listbox_test EMS_NS =
1537 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1538 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1539 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1540 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1541 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1543 trace (" Testing single selection...\n");
1544 check (SS);
1545 trace (" ... with NOSEL\n");
1546 check (SS_NS);
1547 trace (" Testing multiple selection...\n");
1548 check (MS);
1549 trace (" ... with NOSEL\n");
1550 check (MS_NS);
1551 trace (" Testing extended selection...\n");
1552 check (ES);
1553 trace (" ... with NOSEL\n");
1554 check (ES_NS);
1555 trace (" Testing extended and multiple selection...\n");
1556 check (EMS);
1557 trace (" ... with NOSEL\n");
1558 check (EMS_NS);
1560 check_item_height();
1561 test_ownerdraw();
1562 test_selection();
1563 test_listbox_height();
1564 test_itemfrompoint();
1565 test_listbox_item_data();
1566 test_listbox_LB_DIR();
1567 test_listbox_dlgdir();