TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / user32 / tests / listbox.c
blob9380457ea1f8f4a3f5e51106fc489121d1778fab
1 /* Unit test suite for list boxes.
3 * Copyright 2003 Ferenc Wagner
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winnls.h"
30 #include "wine/test.h"
32 #ifdef VISIBLE
33 #define WAIT Sleep (1000)
34 #define REDRAW RedrawWindow (handle, NULL, 0, RDW_UPDATENOW)
35 #else
36 #define WAIT
37 #define REDRAW
38 #endif
40 static const char * const strings[4] = {
41 "First added",
42 "Second added",
43 "Third added",
44 "Fourth added which is very long because at some time we only had a 256 byte character buffer and that was overflowing in one of those applications that had a common dialog file open box and tried to add a 300 characters long custom filter string which of course the code did not like and crashed. Just make sure this string is longer than 256 characters."
47 static const char BAD_EXTENSION[] = "*.badtxt";
49 static HWND
50 create_listbox (DWORD add_style, HWND parent)
52 HWND handle;
53 INT_PTR ctl_id=0;
54 if (parent)
55 ctl_id=1;
56 handle=CreateWindowA("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 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[0]);
63 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[1]);
64 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[2]);
65 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[3]);
67 #ifdef VISIBLE
68 ShowWindow (handle, SW_SHOW);
69 #endif
70 REDRAW;
72 return handle;
75 struct listbox_prop {
76 DWORD add_style;
79 struct listbox_stat {
80 int selected, anchor, caret, selcount;
83 struct listbox_test {
84 struct listbox_prop prop;
85 struct listbox_stat init, init_todo;
86 struct listbox_stat click, click_todo;
87 struct listbox_stat step, step_todo;
88 struct listbox_stat sel, sel_todo;
91 static void
92 listbox_query (HWND handle, struct listbox_stat *results)
94 results->selected = SendMessageA(handle, LB_GETCURSEL, 0, 0);
95 results->anchor = SendMessageA(handle, LB_GETANCHORINDEX, 0, 0);
96 results->caret = SendMessageA(handle, LB_GETCARETINDEX, 0, 0);
97 results->selcount = SendMessageA(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 SendMessageA(handle, WM_LBUTTONDOWN, MK_LBUTTON, lp);
107 SendMessageA(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 SendMessageA(handle, WM_KEYDOWN, keycode, lp);
118 SendMessageA(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 SendMessageA(hLB, LB_GETITEMRECT, 1, (LPARAM) &second_item);
150 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
152 listbox_query (hLB, &answer);
153 listbox_ok (test, click, answer);
155 keypress (hLB, VK_DOWN, 0x50, TRUE);
157 listbox_query (hLB, &answer);
158 listbox_ok (test, step, answer);
160 DestroyWindow (hLB);
161 hLB=create_listbox (test.prop.add_style, 0);
163 SendMessageA(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 = SendMessageA(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 = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
193 ok((res==4), "Expected 4 items, got %d\n", res);
194 res = SendMessageA(hLB, LB_DELETESTRING, -1, 0);
195 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
196 res = SendMessageA(hLB, LB_DELETESTRING, 4, 0);
197 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
198 res = SendMessageA(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 TEXTMETRICA 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 (GetTextMetricsA( hdc, &tm ), "Can't read font metrics\n");
217 ReleaseDC( hLB, hdc);
219 ok (SendMessageA(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
221 itemHeight = SendMessageA(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 = CreateWindowA("LISTBOX", "TestList", LBS_OWNERDRAWVARIABLE,
227 0, 0, 100, 100, NULL, NULL, NULL, 0);
228 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
229 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
230 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 5, 0);
231 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
232 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, -5, 0);
233 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
234 DestroyWindow (hLB);
237 static int got_selchange;
239 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
241 switch (msg)
243 case WM_DRAWITEM:
245 RECT rc_item, rc_client, rc_clip;
246 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
248 trace("%p WM_DRAWITEM %08lx %08lx\n", hwnd, wparam, lparam);
250 ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
251 wparam, dis->CtlID);
252 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
254 GetClientRect(dis->hwndItem, &rc_client);
255 trace("hwndItem %p client rect (%d,%d-%d,%d)\n", dis->hwndItem,
256 rc_client.left, rc_client.top, rc_client.right, rc_client.bottom);
257 GetClipBox(dis->hDC, &rc_clip);
258 trace("clip rect (%d,%d-%d,%d)\n", rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
259 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip),
260 "client rect of the listbox should be equal to the clip box,"
261 "or the clip box should be empty\n");
263 trace("rcItem (%d,%d-%d,%d)\n", dis->rcItem.left, dis->rcItem.top,
264 dis->rcItem.right, dis->rcItem.bottom);
265 SendMessageA(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
266 trace("item rect (%d,%d-%d,%d)\n", rc_item.left, rc_item.top, rc_item.right, rc_item.bottom);
267 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
269 break;
272 case WM_COMMAND:
273 if (HIWORD( wparam ) == LBN_SELCHANGE) got_selchange++;
274 break;
276 default:
277 break;
280 return DefWindowProcA(hwnd, msg, wparam, lparam);
283 static HWND create_parent( void )
285 WNDCLASSA cls;
286 HWND parent;
287 static ATOM class;
289 if (!class)
291 cls.style = 0;
292 cls.lpfnWndProc = main_window_proc;
293 cls.cbClsExtra = 0;
294 cls.cbWndExtra = 0;
295 cls.hInstance = GetModuleHandleA(NULL);
296 cls.hIcon = 0;
297 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
298 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
299 cls.lpszMenuName = NULL;
300 cls.lpszClassName = "main_window_class";
301 class = RegisterClassA( &cls );
304 parent = CreateWindowExA(0, "main_window_class", NULL,
305 WS_POPUP | WS_VISIBLE,
306 100, 100, 400, 400,
307 GetDesktopWindow(), 0,
308 GetModuleHandleA(NULL), NULL);
309 return parent;
312 static void test_ownerdraw(void)
314 HWND parent, hLB;
315 INT ret;
316 RECT rc;
318 parent = create_parent();
319 assert(parent);
321 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
322 assert(hLB);
324 SetForegroundWindow(hLB);
325 UpdateWindow(hLB);
327 /* make height short enough */
328 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
329 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
330 SWP_NOZORDER | SWP_NOMOVE);
332 /* make 0 item invisible */
333 SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
334 ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
335 ok(ret == 1, "wrong top index %d\n", ret);
337 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
338 trace("item 0 rect (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom);
339 ok(!IsRectEmpty(&rc), "empty item rect\n");
340 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
342 DestroyWindow(hLB);
343 DestroyWindow(parent);
346 #define listbox_test_query(exp, got) \
347 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
348 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
349 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
350 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
352 static void test_LB_SELITEMRANGE(void)
354 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
355 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
356 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
357 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
358 HWND hLB;
359 struct listbox_stat answer;
360 INT ret;
362 trace("testing LB_SELITEMRANGE\n");
364 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
365 assert(hLB);
367 listbox_query(hLB, &answer);
368 listbox_test_query(test_nosel, answer);
370 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
371 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
372 listbox_query(hLB, &answer);
373 listbox_test_query(test_1, answer);
375 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
376 listbox_query(hLB, &answer);
377 listbox_test_query(test_nosel, answer);
379 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
380 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
381 listbox_query(hLB, &answer);
382 listbox_test_query(test_3, answer);
384 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
385 listbox_query(hLB, &answer);
386 listbox_test_query(test_nosel, answer);
388 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
389 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
390 listbox_query(hLB, &answer);
391 listbox_test_query(test_nosel, answer);
393 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
394 listbox_query(hLB, &answer);
395 listbox_test_query(test_nosel, answer);
397 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
398 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
399 listbox_query(hLB, &answer);
400 listbox_test_query(test_1, answer);
402 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
403 listbox_query(hLB, &answer);
404 listbox_test_query(test_nosel, answer);
406 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
407 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
408 listbox_query(hLB, &answer);
409 listbox_test_query(test_nosel, answer);
411 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
412 listbox_query(hLB, &answer);
413 listbox_test_query(test_nosel, answer);
415 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
416 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
417 listbox_query(hLB, &answer);
418 listbox_test_query(test_2, answer);
420 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
421 listbox_query(hLB, &answer);
422 listbox_test_query(test_nosel, answer);
424 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
425 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
426 listbox_query(hLB, &answer);
427 listbox_test_query(test_2, answer);
429 DestroyWindow(hLB);
432 static void test_LB_SETCURSEL(void)
434 HWND parent, hLB;
435 INT ret;
437 trace("testing LB_SETCURSEL\n");
439 parent = create_parent();
440 assert(parent);
442 hLB = create_listbox(LBS_NOINTEGRALHEIGHT | WS_CHILD, parent);
443 assert(hLB);
445 SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32);
447 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
448 ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret);
449 ret = GetScrollPos(hLB, SB_VERT);
450 ok(ret == 0, "expected vscroll 0, got %d\n", ret);
452 ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0);
453 ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret);
454 ret = GetScrollPos(hLB, SB_VERT);
455 ok(ret == 1, "expected vscroll 1, got %d\n", ret);
457 DestroyWindow(hLB);
460 static void test_listbox_height(void)
462 HWND hList;
463 int r, id;
465 hList = CreateWindowA( "ListBox", "list test", 0,
466 1, 1, 600, 100, NULL, NULL, NULL, NULL );
467 ok( hList != NULL, "failed to create listbox\n");
469 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
470 ok( id == 0, "item id wrong\n");
472 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
473 ok( r == 0, "send message failed\n");
475 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
476 ok( r == 20, "height wrong\n");
478 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
479 ok( r == -1, "send message failed\n");
481 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
482 ok( r == 20, "height wrong\n");
484 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
485 ok( r == -1, "send message failed\n");
487 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
488 ok( r == 20, "height wrong\n");
490 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
491 ok( r == 0, "send message failed\n");
493 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
494 ok( r == 0xff, "height wrong\n");
496 DestroyWindow( hList );
499 static void test_itemfrompoint(void)
501 /* WS_POPUP is required in order to have a more accurate size calculation (
502 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
503 behavior of partially-displayed item.
505 HWND hList = CreateWindowA( "ListBox", "list test",
506 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
507 1, 1, 600, 100, NULL, NULL, NULL, NULL );
508 ULONG r, id;
509 RECT rc;
511 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000, nt4 returns 0xffffffff */
512 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
513 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
515 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
516 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
518 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
519 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
521 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
522 ok( id == 0, "item id wrong\n");
523 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
524 ok( id == 1, "item id wrong\n");
526 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
527 ok( r == 0x1, "ret %x\n", r );
529 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
530 ok( r == 0x10001 || broken(r == 1), /* nt4 */
531 "ret %x\n", r );
533 /* Resize control so that below assertions about sizes are valid */
534 r = SendMessageA( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
535 ok( r == 1, "ret %x\n", r);
536 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
537 ok( r != 0, "ret %x\n", r);
539 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
540 ok( id == 2, "item id wrong\n");
541 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
542 ok( id == 3, "item id wrong\n");
543 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
544 ok( id == 4, "item id wrong\n");
545 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
546 ok( id == 5, "item id wrong\n");
547 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
548 ok( id == 6, "item id wrong\n");
549 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
550 ok( id == 7, "item id wrong\n");
552 /* Set the listbox up so that id 1 is at the top, this leaves 5
553 partially visible at the bottom and 6, 7 are invisible */
555 SendMessageA( hList, LB_SETTOPINDEX, 1, 0);
556 r = SendMessageA( hList, LB_GETTOPINDEX, 0, 0);
557 ok( r == 1, "top %d\n", r);
559 r = SendMessageA( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
560 ok( r == 1, "ret %x\n", r);
561 r = SendMessageA( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
562 ok( r == 0, "ret %x\n", r);
564 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
565 ok( r == 1, "ret %x\n", r);
567 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
568 ok( r == 0x10001 || broken(r == 1), /* nt4 */
569 "ret %x\n", r );
571 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
572 ok( r == 0x10001 || broken(r == 1), /* nt4 */
573 "ret %x\n", r );
575 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
576 ok( r == 0x10005 || broken(r == 5), /* nt4 */
577 "item %x\n", r );
579 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
580 ok( r == 0x10005 || broken(r == 5), /* nt4 */
581 "item %x\n", r );
583 DestroyWindow( hList );
586 static void test_listbox_item_data(void)
588 HWND hList;
589 int r, id;
591 hList = CreateWindowA( "ListBox", "list test", 0,
592 1, 1, 600, 100, NULL, NULL, NULL, NULL );
593 ok( hList != NULL, "failed to create listbox\n");
595 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
596 ok( id == 0, "item id wrong\n");
598 r = SendMessageA( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
599 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
601 r = SendMessageA( hList, LB_GETITEMDATA, 0, 0);
602 ok( r == 20, "get item data failed\n");
604 DestroyWindow( hList );
607 static void test_listbox_LB_DIR(void)
609 HWND hList;
610 int res, itemCount;
611 int itemCount_justFiles;
612 int itemCount_justDrives;
613 int itemCount_allFiles;
614 int itemCount_allDirs;
615 int i;
616 char pathBuffer[MAX_PATH];
617 char * p;
618 char driveletter;
619 const char *wildcard = "*";
620 HANDLE file;
622 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
623 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
624 CloseHandle( file );
626 /* NOTE: for this test to succeed, there must be no subdirectories
627 under the current directory. In addition, there must be at least
628 one file that fits the wildcard w*.c . Normally, the test
629 directory itself satisfies both conditions.
631 hList = CreateWindowA( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
632 1, 1, 600, 100, NULL, NULL, NULL, NULL );
633 assert(hList);
635 /* Test for standard usage */
637 /* This should list all the files in the test directory. */
638 strcpy(pathBuffer, wildcard);
639 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
640 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
641 if (res == -1) /* "*" wildcard doesn't work on win9x */
643 wildcard = "*.*";
644 strcpy(pathBuffer, wildcard);
645 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
647 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
649 /* There should be some content in the listbox */
650 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
651 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
652 itemCount_allFiles = itemCount;
653 ok(res + 1 == itemCount,
654 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
655 itemCount - 1, res);
657 /* This tests behavior when no files match the wildcard */
658 strcpy(pathBuffer, BAD_EXTENSION);
659 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
660 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
661 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
663 /* There should be NO content in the listbox */
664 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
665 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
668 /* This should list all the w*.c files in the test directory
669 * As of this writing, this includes win.c, winstation.c, wsprintf.c
671 strcpy(pathBuffer, "w*.c");
672 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
673 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
674 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
676 /* Path specification does NOT converted to uppercase */
677 ok (!strcmp(pathBuffer, "w*.c"),
678 "expected no change to pathBuffer, got %s\n", pathBuffer);
680 /* There should be some content in the listbox */
681 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
682 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
683 itemCount_justFiles = itemCount;
684 ok(res + 1 == itemCount,
685 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
686 itemCount - 1, res);
688 /* Every single item in the control should start with a w and end in .c */
689 for (i = 0; i < itemCount; i++) {
690 memset(pathBuffer, 0, MAX_PATH);
691 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
692 p = pathBuffer + strlen(pathBuffer);
693 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
694 (*(p-1) == 'c' || *(p-1) == 'C') &&
695 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
698 /* Test DDL_DIRECTORY */
699 strcpy(pathBuffer, wildcard);
700 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
701 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
702 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
704 /* There should be some content in the listbox.
705 * All files plus "[..]"
707 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
708 itemCount_allDirs = itemCount - itemCount_allFiles;
709 ok (itemCount > itemCount_allFiles,
710 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
711 itemCount, itemCount_allFiles);
712 ok(res + 1 == itemCount,
713 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
714 itemCount - 1, res);
716 /* This tests behavior when no files match the wildcard */
717 strcpy(pathBuffer, BAD_EXTENSION);
718 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
719 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
720 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
722 /* There should be NO content in the listbox */
723 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
724 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
727 /* Test DDL_DIRECTORY */
728 strcpy(pathBuffer, "w*.c");
729 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
730 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
731 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
733 /* There should be some content in the listbox. Since the parent directory does not
734 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
736 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
737 ok (itemCount == itemCount_justFiles,
738 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
739 itemCount, itemCount_justFiles);
740 ok(res + 1 == itemCount,
741 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
742 itemCount - 1, res);
744 /* Every single item in the control should start with a w and end in .c. */
745 for (i = 0; i < itemCount; i++) {
746 memset(pathBuffer, 0, MAX_PATH);
747 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
748 p = pathBuffer + strlen(pathBuffer);
750 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
751 (*(p-1) == 'c' || *(p-1) == 'C') &&
752 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
756 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
757 strcpy(pathBuffer, wildcard);
758 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
759 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
760 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
762 /* There should be some content in the listbox. In particular, there should
763 * be at least one element before, since the string "[-c-]" should
764 * have been added. Depending on the user setting, more drives might have
765 * been added.
767 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
768 ok (itemCount >= 1,
769 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
770 itemCount, 1);
771 itemCount_justDrives = itemCount;
772 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
774 /* Every single item in the control should fit the format [-c-] */
775 for (i = 0; i < itemCount; i++) {
776 memset(pathBuffer, 0, MAX_PATH);
777 driveletter = '\0';
778 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
779 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
780 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
781 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
782 if (!(driveletter >= 'a' && driveletter <= 'z')) {
783 /* Correct after invalid entry is found */
784 trace("removing count of invalid entry %s\n", pathBuffer);
785 itemCount_justDrives--;
789 /* This tests behavior when no files match the wildcard */
790 strcpy(pathBuffer, BAD_EXTENSION);
791 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
792 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
793 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
794 BAD_EXTENSION, res, itemCount_justDrives -1);
796 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
797 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
798 itemCount, itemCount_justDrives);
800 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
801 itemCount_justFiles, itemCount_justDrives);
803 /* Test DDL_DRIVES. */
804 strcpy(pathBuffer, wildcard);
805 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
806 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
807 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
809 /* There should be some content in the listbox. In particular, there should
810 * be at least one element before, since the string "[-c-]" should
811 * have been added. Depending on the user setting, more drives might have
812 * been added.
814 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
815 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
816 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
817 itemCount, itemCount_justDrives + itemCount_allFiles);
818 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
820 /* This tests behavior when no files match the wildcard */
821 strcpy(pathBuffer, BAD_EXTENSION);
822 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
823 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
824 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
825 BAD_EXTENSION, res, itemCount_justDrives -1);
827 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
828 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
831 /* Test DDL_DRIVES. */
832 strcpy(pathBuffer, "w*.c");
833 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
834 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
835 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
837 /* There should be some content in the listbox. In particular, there should
838 * be at least one element before, since the string "[-c-]" should
839 * have been added. Depending on the user setting, more drives might have
840 * been added.
842 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
843 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
844 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
845 itemCount, itemCount_justDrives + itemCount_justFiles);
846 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
848 /* Every single item in the control should fit the format [-c-], or w*.c */
849 for (i = 0; i < itemCount; i++) {
850 memset(pathBuffer, 0, MAX_PATH);
851 driveletter = '\0';
852 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
853 p = pathBuffer + strlen(pathBuffer);
854 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
855 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
856 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
857 } else {
859 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
860 (*(p-1) == 'c' || *(p-1) == 'C') &&
861 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
866 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
867 strcpy(pathBuffer, wildcard);
868 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
869 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
870 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) 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 = SendMessageA(hList, LB_GETCOUNT, 0, 0);
876 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
877 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
878 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
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 for the "[..]" string, which should appear exactly as it is,
883 * and the mapped drives in the format "[-X-]".
885 for (i = 0; i < itemCount; i++) {
886 memset(pathBuffer, 0, MAX_PATH);
887 driveletter = '\0';
888 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
889 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
890 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
894 /* This tests behavior when no files match the wildcard */
895 strcpy(pathBuffer, BAD_EXTENSION);
896 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
897 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
898 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
899 BAD_EXTENSION, res, itemCount_justDrives -1);
901 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
902 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
906 /* Test DDL_DIRECTORY|DDL_DRIVES. */
907 strcpy(pathBuffer, "w*.c");
908 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
909 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
910 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
912 /* There should be some content in the listbox. In particular, there should
913 * be exactly the number of plain files, plus the number of mapped drives.
915 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
916 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
917 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
918 itemCount, itemCount_justFiles + itemCount_justDrives);
919 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
921 /* Every single item in the control should start with a w and end in .c,
922 * except the mapped drives in the format "[-X-]". The "[..]" directory
923 * should not appear.
925 for (i = 0; i < itemCount; i++) {
926 memset(pathBuffer, 0, MAX_PATH);
927 driveletter = '\0';
928 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
929 p = pathBuffer + strlen(pathBuffer);
930 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
931 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
932 } else {
934 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
935 (*(p-1) == 'c' || *(p-1) == 'C') &&
936 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
940 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
941 strcpy(pathBuffer, wildcard);
942 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
943 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
944 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError());
946 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
947 ok (itemCount == itemCount_allDirs,
948 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
949 itemCount, itemCount_allDirs);
950 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
952 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
954 memset(pathBuffer, 0, MAX_PATH);
955 SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
956 ok( !strcmp(pathBuffer, "[..]"), "First element is not [..]\n");
959 /* This tests behavior when no files match the wildcard */
960 strcpy(pathBuffer, BAD_EXTENSION);
961 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
962 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
963 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
964 BAD_EXTENSION, res, -1);
966 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
967 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
970 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
971 strcpy(pathBuffer, "w*.c");
972 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
973 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
974 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
976 /* There should be no elements, since "[..]" does not fit w*.c */
977 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
978 ok (itemCount == 0,
979 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
980 itemCount, 0);
982 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
983 strcpy(pathBuffer, wildcard);
984 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
985 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
986 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
988 /* There should be no plain files on the listbox */
989 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
990 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
991 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
992 itemCount, itemCount_justDrives + itemCount_allDirs);
993 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
995 for (i = 0; i < itemCount; i++) {
996 memset(pathBuffer, 0, MAX_PATH);
997 driveletter = '\0';
998 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
999 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1000 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1001 } else {
1002 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1003 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1007 /* This tests behavior when no files match the wildcard */
1008 strcpy(pathBuffer, BAD_EXTENSION);
1009 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1010 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1011 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1012 BAD_EXTENSION, res, itemCount_justDrives -1);
1014 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1015 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1017 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1018 strcpy(pathBuffer, "w*.c");
1019 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1020 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1021 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1023 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
1024 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1025 ok (itemCount == itemCount_justDrives,
1026 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1027 itemCount, itemCount_justDrives);
1028 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1030 for (i = 0; i < itemCount; i++) {
1031 memset(pathBuffer, 0, MAX_PATH);
1032 driveletter = '\0';
1033 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1034 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1035 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1037 DestroyWindow(hList);
1039 DeleteFileA( "wtest1.tmp.c" );
1042 static HWND g_listBox;
1043 static HWND g_label;
1045 #define ID_TEST_LABEL 1001
1046 #define ID_TEST_LISTBOX 1002
1048 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCTA lpcs)
1050 g_label = CreateWindowA(
1051 "Static",
1052 "Contents of static control before DlgDirList.",
1053 WS_CHILD | WS_VISIBLE,
1054 10, 10, 512, 32,
1055 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1056 if (!g_label) return FALSE;
1057 g_listBox = CreateWindowA(
1058 "ListBox",
1059 "DlgDirList test",
1060 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1061 10, 60, 256, 256,
1062 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1063 if (!g_listBox) return FALSE;
1065 return TRUE;
1068 static LRESULT CALLBACK listbox_container_window_procA (
1069 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1071 LRESULT result = 0;
1073 switch (uiMsg) {
1074 case WM_DESTROY:
1075 PostQuitMessage(0);
1076 break;
1077 case WM_CREATE:
1078 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1079 ? 0 : (LRESULT)-1;
1080 break;
1081 default:
1082 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1083 break;
1085 return result;
1088 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1090 WNDCLASSA cls;
1092 cls.style = 0;
1093 cls.cbClsExtra = 0;
1094 cls.cbWndExtra = 0;
1095 cls.hInstance = hInst;
1096 cls.hIcon = NULL;
1097 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
1098 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1099 cls.lpszMenuName = NULL;
1100 cls.lpfnWndProc = listbox_container_window_procA;
1101 cls.lpszClassName = "ListboxContainerClass";
1102 if (!RegisterClassA (&cls)) return FALSE;
1104 return TRUE;
1107 static void test_listbox_dlgdir(void)
1109 HINSTANCE hInst;
1110 HWND hWnd;
1111 int res, itemCount;
1112 int itemCount_allDirs;
1113 int itemCount_justFiles;
1114 int itemCount_justDrives;
1115 int i;
1116 char pathBuffer[MAX_PATH];
1117 char itemBuffer[MAX_PATH];
1118 char tempBuffer[MAX_PATH];
1119 char * p;
1120 char driveletter;
1121 HANDLE file;
1123 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1124 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1125 CloseHandle( file );
1127 /* NOTE: for this test to succeed, there must be no subdirectories
1128 under the current directory. In addition, there must be at least
1129 one file that fits the wildcard w*.c . Normally, the test
1130 directory itself satisfies both conditions.
1133 hInst = GetModuleHandleA(0);
1134 if (!RegisterListboxWindowClass(hInst)) assert(0);
1135 hWnd = CreateWindowA("ListboxContainerClass", "ListboxContainerClass",
1136 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1137 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1138 NULL, NULL, hInst, 0);
1139 assert(hWnd);
1141 /* Test for standard usage */
1143 /* The following should be overwritten by the directory path */
1144 SendMessageA(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1146 /* This should list all the w*.c files in the test directory
1147 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1149 strcpy(pathBuffer, "w*.c");
1150 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1151 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1153 /* Path specification gets converted to uppercase */
1154 ok (!strcmp(pathBuffer, "W*.C"),
1155 "expected conversion to uppercase, got %s\n", pathBuffer);
1157 /* Loaded path should have overwritten the label text */
1158 SendMessageA(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer);
1159 trace("Static control after DlgDirList: %s\n", pathBuffer);
1160 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1162 /* There should be some content in the listbox */
1163 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1164 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1165 itemCount_justFiles = itemCount;
1167 /* Every single item in the control should start with a w and end in .c */
1168 for (i = 0; i < itemCount; i++) {
1169 memset(pathBuffer, 0, MAX_PATH);
1170 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1171 p = pathBuffer + strlen(pathBuffer);
1172 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1173 (*(p-1) == 'c' || *(p-1) == 'C') &&
1174 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1177 /* Test behavior when no files match the wildcard */
1178 strcpy(pathBuffer, BAD_EXTENSION);
1179 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1180 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1182 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1183 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1185 /* Test DDL_DIRECTORY */
1186 strcpy(pathBuffer, "w*.c");
1187 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1188 DDL_DIRECTORY);
1189 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1191 /* There should be some content in the listbox. In particular, there should
1192 * be exactly more elements than before, since the directories should
1193 * have been added.
1195 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1196 itemCount_allDirs = itemCount - itemCount_justFiles;
1197 ok (itemCount >= itemCount_justFiles,
1198 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1199 itemCount, itemCount_justFiles);
1201 /* Every single item in the control should start with a w and end in .c,
1202 * except for the "[..]" string, which should appear exactly as it is.
1204 for (i = 0; i < itemCount; i++) {
1205 memset(pathBuffer, 0, MAX_PATH);
1206 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1207 p = pathBuffer + strlen(pathBuffer);
1208 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1209 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1210 (*(p-1) == 'c' || *(p-1) == 'C') &&
1211 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1214 /* Test behavior when no files match the wildcard */
1215 strcpy(pathBuffer, BAD_EXTENSION);
1216 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1217 DDL_DIRECTORY);
1218 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1220 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1221 ok (itemCount == itemCount_allDirs,
1222 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1223 itemCount_allDirs, itemCount);
1224 for (i = 0; i < itemCount; i++) {
1225 memset(pathBuffer, 0, MAX_PATH);
1226 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1227 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1228 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1232 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1233 strcpy(pathBuffer, "w*.c");
1234 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1235 DDL_DRIVES);
1236 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1238 /* There should be some content in the listbox. In particular, there should
1239 * be at least one element before, since the string "[-c-]" should
1240 * have been added. Depending on the user setting, more drives might have
1241 * been added.
1243 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1244 ok (itemCount >= 1,
1245 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1246 itemCount, 1);
1247 itemCount_justDrives = itemCount;
1249 /* Every single item in the control should fit the format [-c-] */
1250 for (i = 0; i < itemCount; i++) {
1251 memset(pathBuffer, 0, MAX_PATH);
1252 driveletter = '\0';
1253 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1254 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1255 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1256 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1257 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1258 /* Correct after invalid entry is found */
1259 trace("removing count of invalid entry %s\n", pathBuffer);
1260 itemCount_justDrives--;
1264 /* Test behavior when no files match the wildcard */
1265 strcpy(pathBuffer, BAD_EXTENSION);
1266 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1267 DDL_DRIVES);
1268 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1270 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1271 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1274 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1275 strcpy(pathBuffer, "w*.c");
1276 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1277 DDL_DIRECTORY|DDL_DRIVES);
1278 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1280 /* There should be some content in the listbox. In particular, there should
1281 * be exactly the number of plain files, plus the number of mapped drives,
1282 * plus one "[..]"
1284 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1285 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1286 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1287 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1289 /* Every single item in the control should start with a w and end in .c,
1290 * except for the "[..]" string, which should appear exactly as it is,
1291 * and the mapped drives in the format "[-X-]".
1293 for (i = 0; i < itemCount; i++) {
1294 memset(pathBuffer, 0, MAX_PATH);
1295 driveletter = '\0';
1296 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1297 p = pathBuffer + strlen(pathBuffer);
1298 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1299 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1300 } else {
1301 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1302 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1303 (*(p-1) == 'c' || *(p-1) == 'C') &&
1304 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1308 /* Test behavior when no files match the wildcard */
1309 strcpy(pathBuffer, BAD_EXTENSION);
1310 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1311 DDL_DIRECTORY|DDL_DRIVES);
1312 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1314 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1315 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1316 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1317 itemCount_justDrives + itemCount_allDirs, itemCount);
1321 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1322 strcpy(pathBuffer, "w*.c");
1323 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1324 DDL_DIRECTORY|DDL_EXCLUSIVE);
1325 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1327 /* There should be exactly one element: "[..]" */
1328 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1329 ok (itemCount == itemCount_allDirs,
1330 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1331 itemCount, itemCount_allDirs);
1333 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1335 memset(pathBuffer, 0, MAX_PATH);
1336 SendMessageA(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1337 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1340 /* Test behavior when no files match the wildcard */
1341 strcpy(pathBuffer, BAD_EXTENSION);
1342 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1343 DDL_DIRECTORY|DDL_EXCLUSIVE);
1344 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1346 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1347 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1350 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1351 strcpy(pathBuffer, "w*.c");
1352 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1353 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1354 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1356 /* There should be no plain files on the listbox */
1357 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1358 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1359 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1360 itemCount, itemCount_justDrives + itemCount_allDirs);
1362 for (i = 0; i < itemCount; i++) {
1363 memset(pathBuffer, 0, MAX_PATH);
1364 driveletter = '\0';
1365 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1366 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1367 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1368 } else {
1369 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1370 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1374 /* Test behavior when no files match the wildcard */
1375 strcpy(pathBuffer, BAD_EXTENSION);
1376 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1377 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1378 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1380 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1381 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1382 "DlgDirList() incorrectly filled the listbox!\n");
1384 /* Now test DlgDirSelectEx() in normal operation */
1385 /* Fill with everything - drives, directory and all plain files. */
1386 strcpy(pathBuffer, "*");
1387 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1388 DDL_DIRECTORY|DDL_DRIVES);
1389 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1391 SendMessageA(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1392 memset(pathBuffer, 0, MAX_PATH);
1393 SetLastError(0xdeadbeef);
1394 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1395 ok (GetLastError() == 0xdeadbeef,
1396 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1397 GetLastError());
1398 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1399 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1401 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1403 /* Test proper drive/dir/file recognition */
1404 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1405 for (i = 0; i < itemCount; i++) {
1406 memset(itemBuffer, 0, MAX_PATH);
1407 memset(pathBuffer, 0, MAX_PATH);
1408 memset(tempBuffer, 0, MAX_PATH);
1409 driveletter = '\0';
1410 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1411 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1412 ok (res == i, "SendMessageA(LB_SETCURSEL, %d) failed\n", i);
1413 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1414 /* Current item is a drive letter */
1415 SetLastError(0xdeadbeef);
1416 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1417 ok (GetLastError() == 0xdeadbeef,
1418 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1419 i, GetLastError());
1420 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1422 /* For drive letters, DlgDirSelectEx tacks on a colon */
1423 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1424 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1425 } else if (itemBuffer[0] == '[') {
1426 /* Current item is the parent directory */
1427 SetLastError(0xdeadbeef);
1428 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1429 ok (GetLastError() == 0xdeadbeef,
1430 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1431 i, GetLastError());
1432 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1434 /* For directories, DlgDirSelectEx tacks on a backslash */
1435 p = pathBuffer + strlen(pathBuffer);
1436 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1438 tempBuffer[0] = '[';
1439 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1440 strcat(tempBuffer, "]");
1441 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1442 } else {
1443 /* Current item is a plain file */
1444 SetLastError(0xdeadbeef);
1445 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1446 ok (GetLastError() == 0xdeadbeef,
1447 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1448 i, GetLastError());
1449 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1451 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1452 * for example, "Makefile", which gets reported as "Makefile."
1454 strcpy(tempBuffer, itemBuffer);
1455 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1456 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1460 DeleteFileA( "wtest1.tmp.c" );
1462 /* Now test DlgDirSelectEx() in abnormal operation */
1463 /* Fill list with bogus entries, that look somewhat valid */
1464 SendMessageA(g_listBox, LB_RESETCONTENT, 0, 0);
1465 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1466 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1467 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1468 for (i = 0; i < itemCount; i++) {
1469 memset(itemBuffer, 0, MAX_PATH);
1470 memset(pathBuffer, 0, MAX_PATH);
1471 memset(tempBuffer, 0, MAX_PATH);
1472 driveletter = '\0';
1473 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1474 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1475 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1476 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1477 /* Current item is a drive letter */
1478 SetLastError(0xdeadbeef);
1479 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1480 ok (GetLastError() == 0xdeadbeef,
1481 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1482 i, GetLastError());
1483 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1485 /* For drive letters, DlgDirSelectEx tacks on a colon */
1486 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1487 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1488 } else if (itemBuffer[0] == '[') {
1489 /* Current item is the parent directory */
1490 SetLastError(0xdeadbeef);
1491 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1492 ok (GetLastError() == 0xdeadbeef,
1493 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1494 i, GetLastError());
1495 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1497 /* For directories, DlgDirSelectEx tacks on a backslash */
1498 p = pathBuffer + strlen(pathBuffer);
1499 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1501 tempBuffer[0] = '[';
1502 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1503 strcat(tempBuffer, "]");
1504 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1505 } else {
1506 /* Current item is a plain file */
1507 SetLastError(0xdeadbeef);
1508 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1509 ok (GetLastError() == 0xdeadbeef,
1510 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1511 i, GetLastError());
1512 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1514 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1515 * This affects for example, "Makefile", which gets reported as "Makefile."
1517 strcpy(tempBuffer, itemBuffer);
1518 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1519 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1523 /* Test behavior when loading folders from root with and without wildcard */
1524 strcpy(pathBuffer, "C:\\");
1525 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1526 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\ folders\n");
1527 todo_wine ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1528 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1530 strcpy(pathBuffer, "C:\\*");
1531 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1532 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\* folders\n");
1533 ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1534 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1536 /* Try loading files from an invalid folder */
1537 SetLastError(0xdeadbeef);
1538 strcpy(pathBuffer, "C:\\INVALID$$DIR");
1539 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1540 todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
1541 todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
1542 "GetLastError should return 0x589, got 0x%X\n",GetLastError());
1544 DestroyWindow(hWnd);
1547 static void test_set_count( void )
1549 HWND parent, listbox;
1550 LONG ret;
1551 RECT r;
1553 parent = create_parent();
1554 listbox = create_listbox( LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VISIBLE, parent );
1556 UpdateWindow( listbox );
1557 GetUpdateRect( listbox, &r, TRUE );
1558 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1560 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
1561 ok( ret == 0, "got %d\n", ret );
1562 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
1563 ok( ret == 100, "got %d\n", ret );
1565 GetUpdateRect( listbox, &r, TRUE );
1566 ok( !IsRectEmpty( &r ), "got empty rect\n");
1568 ValidateRect( listbox, NULL );
1569 GetUpdateRect( listbox, &r, TRUE );
1570 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1572 ret = SendMessageA( listbox, LB_SETCOUNT, 99, 0 );
1573 ok( ret == 0, "got %d\n", ret );
1575 GetUpdateRect( listbox, &r, TRUE );
1576 ok( !IsRectEmpty( &r ), "got empty rect\n");
1578 DestroyWindow( listbox );
1579 DestroyWindow( parent );
1582 static DWORD (WINAPI *pGetListBoxInfo)(HWND);
1583 static int lb_getlistboxinfo;
1585 static LRESULT WINAPI listbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1587 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
1589 if (message == LB_GETLISTBOXINFO)
1590 lb_getlistboxinfo++;
1592 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
1595 static void test_GetListBoxInfo(void)
1597 HWND listbox, parent;
1598 WNDPROC oldproc;
1599 DWORD ret;
1601 pGetListBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetListBoxInfo");
1603 if (!pGetListBoxInfo)
1605 win_skip("GetListBoxInfo() not available\n");
1606 return;
1609 parent = create_parent();
1610 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1612 oldproc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (LONG_PTR)listbox_subclass_proc);
1613 SetWindowLongPtrA(listbox, GWLP_USERDATA, (LONG_PTR)oldproc);
1615 lb_getlistboxinfo = 0;
1616 ret = pGetListBoxInfo(listbox);
1617 ok(ret > 0, "got %d\n", ret);
1618 todo_wine
1619 ok(lb_getlistboxinfo == 0, "got %d\n", lb_getlistboxinfo);
1621 DestroyWindow(listbox);
1622 DestroyWindow(parent);
1625 static void test_missing_lbuttonup( void )
1627 HWND listbox, parent, capture;
1629 parent = create_parent();
1630 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1632 /* Send button down without a corresponding button up */
1633 SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(10,10));
1634 capture = GetCapture();
1635 ok(capture == listbox, "got %p expected %p\n", capture, listbox);
1637 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */
1638 got_selchange = 0;
1639 SetFocus(NULL);
1640 capture = GetCapture();
1641 ok(capture == NULL, "got %p\n", capture);
1642 ok(got_selchange, "got %d\n", got_selchange);
1644 DestroyWindow(listbox);
1645 DestroyWindow(parent);
1648 static void test_extents(void)
1650 HWND listbox, parent;
1651 DWORD res;
1652 SCROLLINFO sinfo;
1653 BOOL br;
1655 parent = create_parent();
1657 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1659 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1660 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1662 sinfo.cbSize = sizeof(sinfo);
1663 sinfo.fMask = SIF_RANGE;
1664 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1665 ok(br == TRUE, "GetScrollInfo failed\n");
1666 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1667 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1668 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1669 "List box should not have a horizontal scroll bar\n");
1671 /* horizontal extent < width */
1672 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1674 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1675 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1677 sinfo.cbSize = sizeof(sinfo);
1678 sinfo.fMask = SIF_RANGE;
1679 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1680 ok(br == TRUE, "GetScrollInfo failed\n");
1681 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1682 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1683 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1684 "List box should not have a horizontal scroll bar\n");
1686 /* horizontal extent > width */
1687 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1689 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1690 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1692 sinfo.cbSize = sizeof(sinfo);
1693 sinfo.fMask = SIF_RANGE;
1694 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1695 ok(br == TRUE, "GetScrollInfo failed\n");
1696 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1697 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1698 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1699 "List box should not have a horizontal scroll bar\n");
1701 DestroyWindow(listbox);
1704 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL, parent);
1706 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1707 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1709 sinfo.cbSize = sizeof(sinfo);
1710 sinfo.fMask = SIF_RANGE;
1711 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1712 ok(br == TRUE, "GetScrollInfo failed\n");
1713 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1714 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1715 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1716 "List box should not have a horizontal scroll bar\n");
1718 /* horizontal extent < width */
1719 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1721 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1722 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1724 sinfo.cbSize = sizeof(sinfo);
1725 sinfo.fMask = SIF_RANGE;
1726 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1727 ok(br == TRUE, "GetScrollInfo failed\n");
1728 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1729 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
1730 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1731 "List box should not have a horizontal scroll bar\n");
1733 /* horizontal extent > width */
1734 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1736 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1737 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1739 sinfo.cbSize = sizeof(sinfo);
1740 sinfo.fMask = SIF_RANGE;
1741 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1742 ok(br == TRUE, "GetScrollInfo failed\n");
1743 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1744 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
1745 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1746 "List box should have a horizontal scroll bar\n");
1748 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
1750 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1751 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
1753 sinfo.cbSize = sizeof(sinfo);
1754 sinfo.fMask = SIF_RANGE;
1755 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1756 ok(br == TRUE, "GetScrollInfo failed\n");
1757 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1758 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1759 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1760 "List box should not have a horizontal scroll bar\n");
1762 DestroyWindow(listbox);
1765 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL | LBS_DISABLENOSCROLL, parent);
1767 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1768 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1770 sinfo.cbSize = sizeof(sinfo);
1771 sinfo.fMask = SIF_RANGE;
1772 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1773 ok(br == TRUE, "GetScrollInfo failed\n");
1774 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1775 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1776 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1777 "List box should have a horizontal scroll bar\n");
1779 /* horizontal extent < width */
1780 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1782 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1783 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1785 sinfo.cbSize = sizeof(sinfo);
1786 sinfo.fMask = SIF_RANGE;
1787 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1788 ok(br == TRUE, "GetScrollInfo failed\n");
1789 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1790 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
1791 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1792 "List box should have a horizontal scroll bar\n");
1794 /* horizontal extent > width */
1795 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1797 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1798 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1800 sinfo.cbSize = sizeof(sinfo);
1801 sinfo.fMask = SIF_RANGE;
1802 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1803 ok(br == TRUE, "GetScrollInfo failed\n");
1804 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1805 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
1806 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1807 "List box should have a horizontal scroll bar\n");
1809 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
1811 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1812 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
1814 sinfo.cbSize = sizeof(sinfo);
1815 sinfo.fMask = SIF_RANGE;
1816 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1817 ok(br == TRUE, "GetScrollInfo failed\n");
1818 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1819 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1820 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1821 "List box should have a horizontal scroll bar\n");
1823 DestroyWindow(listbox);
1825 DestroyWindow(parent);
1828 START_TEST(listbox)
1830 const struct listbox_test SS =
1831 /* {add_style} */
1832 {{0},
1833 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1834 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1835 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1836 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1837 /* {selected, anchor, caret, selcount}{TODO fields} */
1838 const struct listbox_test SS_NS =
1839 {{LBS_NOSEL},
1840 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1841 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1842 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1843 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1844 const struct listbox_test MS =
1845 {{LBS_MULTIPLESEL},
1846 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1847 { 1, 1, 1, 1}, {0,0,0,0},
1848 { 2, 1, 2, 1}, {0,0,0,0},
1849 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1850 const struct listbox_test MS_NS =
1851 {{LBS_MULTIPLESEL | LBS_NOSEL},
1852 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1853 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1854 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1855 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1856 const struct listbox_test ES =
1857 {{LBS_EXTENDEDSEL},
1858 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1859 { 1, 1, 1, 1}, {0,0,0,0},
1860 { 2, 2, 2, 1}, {0,0,0,0},
1861 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1862 const struct listbox_test ES_NS =
1863 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1864 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1865 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1866 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1867 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1868 const struct listbox_test EMS =
1869 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1870 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1871 { 1, 1, 1, 1}, {0,0,0,0},
1872 { 2, 2, 2, 1}, {0,0,0,0},
1873 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1874 const struct listbox_test EMS_NS =
1875 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1876 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1877 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1878 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1879 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1881 trace (" Testing single selection...\n");
1882 check (SS);
1883 trace (" ... with NOSEL\n");
1884 check (SS_NS);
1885 trace (" Testing multiple selection...\n");
1886 check (MS);
1887 trace (" ... with NOSEL\n");
1888 check (MS_NS);
1889 trace (" Testing extended selection...\n");
1890 check (ES);
1891 trace (" ... with NOSEL\n");
1892 check (ES_NS);
1893 trace (" Testing extended and multiple selection...\n");
1894 check (EMS);
1895 trace (" ... with NOSEL\n");
1896 check (EMS_NS);
1898 check_item_height();
1899 test_ownerdraw();
1900 test_LB_SELITEMRANGE();
1901 test_LB_SETCURSEL();
1902 test_listbox_height();
1903 test_itemfrompoint();
1904 test_listbox_item_data();
1905 test_listbox_LB_DIR();
1906 test_listbox_dlgdir();
1907 test_set_count();
1908 test_GetListBoxInfo();
1909 test_missing_lbuttonup();
1910 test_extents();