user32: Don't wait for other threads to process WM_NCDESTROY.
[wine.git] / dlls / user32 / tests / listbox.c
blob88d3adb728e71734e91c53b137c81fff3a6ce7bd
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 int strcmp_aw(LPCWSTR strw, const char *stra)
51 WCHAR buf[1024];
53 if (!stra) return 1;
54 MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
55 return lstrcmpW(strw, buf);
58 static HWND
59 create_listbox (DWORD add_style, HWND parent)
61 HWND handle;
62 INT_PTR ctl_id=0;
63 if (parent)
64 ctl_id=1;
65 handle=CreateWindowA("LISTBOX", "TestList",
66 (LBS_STANDARD & ~LBS_SORT) | add_style,
67 0, 0, 100, 100,
68 parent, (HMENU)ctl_id, NULL, 0);
70 assert (handle);
71 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[0]);
72 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[1]);
73 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[2]);
74 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[3]);
76 #ifdef VISIBLE
77 ShowWindow (handle, SW_SHOW);
78 #endif
79 REDRAW;
81 return handle;
84 struct listbox_prop {
85 DWORD add_style;
88 struct listbox_stat {
89 int selected, anchor, caret, selcount;
92 struct listbox_test {
93 struct listbox_prop prop;
94 struct listbox_stat init, init_todo;
95 struct listbox_stat click, click_todo;
96 struct listbox_stat step, step_todo;
97 struct listbox_stat sel, sel_todo;
100 static void
101 listbox_query (HWND handle, struct listbox_stat *results)
103 results->selected = SendMessageA(handle, LB_GETCURSEL, 0, 0);
104 results->anchor = SendMessageA(handle, LB_GETANCHORINDEX, 0, 0);
105 results->caret = SendMessageA(handle, LB_GETCARETINDEX, 0, 0);
106 results->selcount = SendMessageA(handle, LB_GETSELCOUNT, 0, 0);
109 static void
110 buttonpress (HWND handle, WORD x, WORD y)
112 LPARAM lp=x+(y<<16);
114 WAIT;
115 SendMessageA(handle, WM_LBUTTONDOWN, MK_LBUTTON, lp);
116 SendMessageA(handle, WM_LBUTTONUP, 0, lp);
117 REDRAW;
120 static void
121 keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
123 LPARAM lp=1+(scancode<<16)+(extended?KEYEVENTF_EXTENDEDKEY:0);
125 WAIT;
126 SendMessageA(handle, WM_KEYDOWN, keycode, lp);
127 SendMessageA(handle, WM_KEYUP , keycode, lp | 0xc000000);
128 REDRAW;
131 #define listbox_field_ok(t, s, f, got) \
132 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
133 ": expected %d, got %d\n", (unsigned int)t.prop.add_style, \
134 t.s.f, got.f)
136 #define listbox_todo_field_ok(t, s, f, got) \
137 todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
139 #define listbox_ok(t, s, got) \
140 listbox_todo_field_ok(t, s, selected, got); \
141 listbox_todo_field_ok(t, s, anchor, got); \
142 listbox_todo_field_ok(t, s, caret, got); \
143 listbox_todo_field_ok(t, s, selcount, got)
145 static void
146 check (const struct listbox_test test)
148 struct listbox_stat answer;
149 HWND hLB=create_listbox (test.prop.add_style, 0);
150 RECT second_item;
151 int i;
152 int res;
154 listbox_query (hLB, &answer);
155 listbox_ok (test, init, answer);
157 SendMessageA(hLB, LB_GETITEMRECT, 1, (LPARAM) &second_item);
158 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
160 listbox_query (hLB, &answer);
161 listbox_ok (test, click, answer);
163 keypress (hLB, VK_DOWN, 0x50, TRUE);
165 listbox_query (hLB, &answer);
166 listbox_ok (test, step, answer);
168 DestroyWindow (hLB);
169 hLB=create_listbox (test.prop.add_style, 0);
171 SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
172 listbox_query (hLB, &answer);
173 listbox_ok (test, sel, answer);
175 for (i=0;i<4;i++) {
176 DWORD size = SendMessageA(hLB, LB_GETTEXTLEN, i, 0);
177 CHAR *txt;
178 WCHAR *txtw;
179 int resA, resW;
181 txt = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, size+1);
182 resA=SendMessageA(hLB, LB_GETTEXT, i, (LPARAM)txt);
183 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
185 txtw = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, 2*size+2);
186 resW=SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
187 if (resA != resW) {
188 trace("SendMessageW(LB_GETTEXT) not supported on this platform (resA=%d resW=%d), skipping...\n",
189 resA, resW);
190 } else {
191 WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL );
192 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
195 HeapFree (GetProcessHeap(), 0, txtw);
196 HeapFree (GetProcessHeap(), 0, txt);
199 /* Confirm the count of items, and that an invalid delete does not remove anything */
200 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
201 ok((res==4), "Expected 4 items, got %d\n", res);
202 res = SendMessageA(hLB, LB_DELETESTRING, -1, 0);
203 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
204 res = SendMessageA(hLB, LB_DELETESTRING, 4, 0);
205 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
206 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
207 ok((res==4), "Expected 4 items, got %d\n", res);
209 WAIT;
210 DestroyWindow (hLB);
213 static void check_item_height(void)
215 HWND hLB;
216 HDC hdc;
217 HFONT font;
218 TEXTMETRICA tm;
219 INT itemHeight;
221 hLB = create_listbox (0, 0);
222 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n");
223 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n");
224 ok (GetTextMetricsA( hdc, &tm ), "Can't read font metrics\n");
225 ReleaseDC( hLB, hdc);
227 ok (SendMessageA(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
229 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
230 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight);
232 DestroyWindow (hLB);
234 hLB = CreateWindowA("LISTBOX", "TestList", LBS_OWNERDRAWVARIABLE,
235 0, 0, 100, 100, NULL, NULL, NULL, 0);
236 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
237 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
238 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 5, 0);
239 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
240 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, -5, 0);
241 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
242 DestroyWindow (hLB);
245 static int got_selchange;
247 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
249 switch (msg)
251 case WM_MEASUREITEM:
253 DWORD style = GetWindowLongA(GetWindow(hwnd, GW_CHILD), GWL_STYLE);
254 MEASUREITEMSTRUCT *mi = (void*)lparam;
256 ok(wparam == mi->CtlID, "got wParam=%08lx, expected %08x\n", wparam, mi->CtlID);
257 ok(mi->CtlType == ODT_LISTBOX, "mi->CtlType = %u\n", mi->CtlType);
258 ok(mi->CtlID == 1, "mi->CtlID = %u\n", mi->CtlID);
259 ok(mi->itemHeight, "mi->itemHeight = 0\n");
261 if (mi->itemID > 4 || style & LBS_OWNERDRAWFIXED)
262 break;
264 if (style & LBS_HASSTRINGS)
266 ok(!strcmp_aw((WCHAR*)mi->itemData, strings[mi->itemID]),
267 "mi->itemData = %s (%d)\n", wine_dbgstr_w((WCHAR*)mi->itemData), mi->itemID);
269 else
271 ok((void*)mi->itemData == strings[mi->itemID],
272 "mi->itemData = %08lx, expected %p\n", mi->itemData, strings[mi->itemID]);
274 break;
276 case WM_DRAWITEM:
278 RECT rc_item, rc_client, rc_clip;
279 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
281 trace("%p WM_DRAWITEM %08lx %08lx\n", hwnd, wparam, lparam);
283 ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
284 wparam, dis->CtlID);
285 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
287 GetClientRect(dis->hwndItem, &rc_client);
288 trace("hwndItem %p client rect %s\n", dis->hwndItem, wine_dbgstr_rect(&rc_client));
289 GetClipBox(dis->hDC, &rc_clip);
290 trace("clip rect %s\n", wine_dbgstr_rect(&rc_clip));
291 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip),
292 "client rect of the listbox should be equal to the clip box,"
293 "or the clip box should be empty\n");
295 trace("rcItem %s\n", wine_dbgstr_rect(&dis->rcItem));
296 SendMessageA(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
297 trace("item rect %s\n", wine_dbgstr_rect(&rc_item));
298 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
300 break;
303 case WM_COMMAND:
304 if (HIWORD( wparam ) == LBN_SELCHANGE) got_selchange++;
305 break;
307 default:
308 break;
311 return DefWindowProcA(hwnd, msg, wparam, lparam);
314 static HWND create_parent( void )
316 WNDCLASSA cls;
317 HWND parent;
318 static ATOM class;
320 if (!class)
322 cls.style = 0;
323 cls.lpfnWndProc = main_window_proc;
324 cls.cbClsExtra = 0;
325 cls.cbWndExtra = 0;
326 cls.hInstance = GetModuleHandleA(NULL);
327 cls.hIcon = 0;
328 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
329 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
330 cls.lpszMenuName = NULL;
331 cls.lpszClassName = "main_window_class";
332 class = RegisterClassA( &cls );
335 parent = CreateWindowExA(0, "main_window_class", NULL,
336 WS_POPUP | WS_VISIBLE,
337 100, 100, 400, 400,
338 GetDesktopWindow(), 0,
339 GetModuleHandleA(NULL), NULL);
340 return parent;
343 static void test_ownerdraw(void)
345 HWND parent, hLB;
346 INT ret;
347 RECT rc;
349 parent = create_parent();
350 assert(parent);
352 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
353 assert(hLB);
355 SetForegroundWindow(hLB);
356 UpdateWindow(hLB);
358 /* make height short enough */
359 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
360 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
361 SWP_NOZORDER | SWP_NOMOVE);
363 /* make 0 item invisible */
364 SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
365 ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
366 ok(ret == 1, "wrong top index %d\n", ret);
368 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
369 trace("item 0 rect %s\n", wine_dbgstr_rect(&rc));
370 ok(!IsRectEmpty(&rc), "empty item rect\n");
371 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
373 DestroyWindow(hLB);
374 DestroyWindow(parent);
377 #define listbox_test_query(exp, got) \
378 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
379 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
380 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
381 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
383 static void test_LB_SELITEMRANGE(void)
385 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
386 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
387 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
388 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
389 HWND hLB;
390 struct listbox_stat answer;
391 INT ret;
393 trace("testing LB_SELITEMRANGE\n");
395 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
396 assert(hLB);
398 listbox_query(hLB, &answer);
399 listbox_test_query(test_nosel, answer);
401 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
402 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
403 listbox_query(hLB, &answer);
404 listbox_test_query(test_1, answer);
406 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
407 listbox_query(hLB, &answer);
408 listbox_test_query(test_nosel, answer);
410 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
411 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
412 listbox_query(hLB, &answer);
413 listbox_test_query(test_3, answer);
415 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
416 listbox_query(hLB, &answer);
417 listbox_test_query(test_nosel, answer);
419 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
420 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
421 listbox_query(hLB, &answer);
422 listbox_test_query(test_nosel, answer);
424 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
425 listbox_query(hLB, &answer);
426 listbox_test_query(test_nosel, answer);
428 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
429 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
430 listbox_query(hLB, &answer);
431 listbox_test_query(test_1, answer);
433 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
434 listbox_query(hLB, &answer);
435 listbox_test_query(test_nosel, answer);
437 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
438 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
439 listbox_query(hLB, &answer);
440 listbox_test_query(test_nosel, answer);
442 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
443 listbox_query(hLB, &answer);
444 listbox_test_query(test_nosel, answer);
446 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
447 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
448 listbox_query(hLB, &answer);
449 listbox_test_query(test_2, answer);
451 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
452 listbox_query(hLB, &answer);
453 listbox_test_query(test_nosel, answer);
455 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
456 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
457 listbox_query(hLB, &answer);
458 listbox_test_query(test_2, answer);
460 DestroyWindow(hLB);
463 static void test_LB_SETCURSEL(void)
465 HWND parent, hLB;
466 INT ret;
468 trace("testing LB_SETCURSEL\n");
470 parent = create_parent();
471 assert(parent);
473 hLB = create_listbox(LBS_NOINTEGRALHEIGHT | WS_CHILD, parent);
474 assert(hLB);
476 SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32);
478 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
479 ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret);
480 ret = GetScrollPos(hLB, SB_VERT);
481 ok(ret == 0, "expected vscroll 0, got %d\n", ret);
483 ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0);
484 ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret);
485 ret = GetScrollPos(hLB, SB_VERT);
486 ok(ret == 1, "expected vscroll 1, got %d\n", ret);
488 DestroyWindow(hLB);
491 static void test_listbox_height(void)
493 HWND hList;
494 int r, id;
496 hList = CreateWindowA( "ListBox", "list test", 0,
497 1, 1, 600, 100, NULL, NULL, NULL, NULL );
498 ok( hList != NULL, "failed to create listbox\n");
500 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
501 ok( id == 0, "item id wrong\n");
503 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
504 ok( r == 0, "send message failed\n");
506 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
507 ok( r == 20, "height wrong\n");
509 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
510 ok( r == -1, "send message failed\n");
512 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
513 ok( r == 20, "height wrong\n");
515 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
516 ok( r == -1, "send message failed\n");
518 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
519 ok( r == 20, "height wrong\n");
521 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
522 ok( r == 0, "send message failed\n");
524 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
525 ok( r == 0xff, "height wrong\n");
527 DestroyWindow( hList );
530 static void test_itemfrompoint(void)
532 /* WS_POPUP is required in order to have a more accurate size calculation (
533 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
534 behavior of partially-displayed item.
536 HWND hList = CreateWindowA( "ListBox", "list test",
537 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
538 1, 1, 600, 100, NULL, NULL, NULL, NULL );
539 ULONG r, id;
540 RECT rc;
542 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000, nt4 returns 0xffffffff */
543 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
544 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
546 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
547 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
549 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
550 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
552 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
553 ok( id == 0, "item id wrong\n");
554 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
555 ok( id == 1, "item id wrong\n");
557 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
558 ok( r == 0x1, "ret %x\n", r );
560 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
561 ok( r == 0x10001 || broken(r == 1), /* nt4 */
562 "ret %x\n", r );
564 /* Resize control so that below assertions about sizes are valid */
565 r = SendMessageA( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
566 ok( r == 1, "ret %x\n", r);
567 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
568 ok( r != 0, "ret %x\n", r);
570 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
571 ok( id == 2, "item id wrong\n");
572 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
573 ok( id == 3, "item id wrong\n");
574 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
575 ok( id == 4, "item id wrong\n");
576 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
577 ok( id == 5, "item id wrong\n");
578 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
579 ok( id == 6, "item id wrong\n");
580 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
581 ok( id == 7, "item id wrong\n");
583 /* Set the listbox up so that id 1 is at the top, this leaves 5
584 partially visible at the bottom and 6, 7 are invisible */
586 SendMessageA( hList, LB_SETTOPINDEX, 1, 0);
587 r = SendMessageA( hList, LB_GETTOPINDEX, 0, 0);
588 ok( r == 1, "top %d\n", r);
590 r = SendMessageA( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
591 ok( r == 1, "ret %x\n", r);
592 r = SendMessageA( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
593 ok( r == 0, "ret %x\n", r);
595 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
596 ok( r == 1, "ret %x\n", r);
598 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
599 ok( r == 0x10001 || broken(r == 1), /* nt4 */
600 "ret %x\n", r );
602 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
603 ok( r == 0x10001 || broken(r == 1), /* nt4 */
604 "ret %x\n", r );
606 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
607 ok( r == 0x10005 || broken(r == 5), /* nt4 */
608 "item %x\n", r );
610 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
611 ok( r == 0x10005 || broken(r == 5), /* nt4 */
612 "item %x\n", r );
614 DestroyWindow( hList );
617 static void test_listbox_item_data(void)
619 HWND hList;
620 int r, id;
622 hList = CreateWindowA( "ListBox", "list test", 0,
623 1, 1, 600, 100, NULL, NULL, NULL, NULL );
624 ok( hList != NULL, "failed to create listbox\n");
626 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
627 ok( id == 0, "item id wrong\n");
629 r = SendMessageA( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
630 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
632 r = SendMessageA( hList, LB_GETITEMDATA, 0, 0);
633 ok( r == 20, "get item data failed\n");
635 DestroyWindow( hList );
638 static void test_listbox_LB_DIR(void)
640 HWND hList;
641 int res, itemCount;
642 int itemCount_justFiles;
643 int itemCount_justDrives;
644 int itemCount_allFiles;
645 int itemCount_allDirs;
646 int i;
647 char pathBuffer[MAX_PATH];
648 char * p;
649 char driveletter;
650 const char *wildcard = "*";
651 HANDLE file;
653 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
654 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
655 CloseHandle( file );
657 /* NOTE: for this test to succeed, there must be no subdirectories
658 under the current directory. In addition, there must be at least
659 one file that fits the wildcard w*.c . Normally, the test
660 directory itself satisfies both conditions.
662 hList = CreateWindowA( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
663 1, 1, 600, 100, NULL, NULL, NULL, NULL );
664 assert(hList);
666 /* Test for standard usage */
668 /* This should list all the files in the test directory. */
669 strcpy(pathBuffer, wildcard);
670 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
671 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
672 if (res == -1) /* "*" wildcard doesn't work on win9x */
674 wildcard = "*.*";
675 strcpy(pathBuffer, wildcard);
676 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
678 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
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_allFiles = itemCount;
684 ok(res + 1 == itemCount,
685 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
686 itemCount - 1, res);
688 /* This tests behavior when no files match the wildcard */
689 strcpy(pathBuffer, BAD_EXTENSION);
690 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
691 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
692 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
694 /* There should be NO content in the listbox */
695 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
696 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
699 /* This should list all the w*.c files in the test directory
700 * As of this writing, this includes win.c, winstation.c, wsprintf.c
702 strcpy(pathBuffer, "w*.c");
703 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
704 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
705 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
707 /* Path specification does NOT converted to uppercase */
708 ok (!strcmp(pathBuffer, "w*.c"),
709 "expected no change to pathBuffer, got %s\n", pathBuffer);
711 /* There should be some content in the listbox */
712 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
713 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
714 itemCount_justFiles = itemCount;
715 ok(res + 1 == itemCount,
716 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
717 itemCount - 1, res);
719 /* Every single item in the control should start with a w and end in .c */
720 for (i = 0; i < itemCount; i++) {
721 memset(pathBuffer, 0, MAX_PATH);
722 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
723 p = pathBuffer + strlen(pathBuffer);
724 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
725 (*(p-1) == 'c' || *(p-1) == 'C') &&
726 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
729 /* Test DDL_DIRECTORY */
730 strcpy(pathBuffer, wildcard);
731 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
732 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
733 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
735 /* There should be some content in the listbox.
736 * All files plus "[..]"
738 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
739 itemCount_allDirs = itemCount - itemCount_allFiles;
740 ok (itemCount > itemCount_allFiles,
741 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
742 itemCount, itemCount_allFiles);
743 ok(res + 1 == itemCount,
744 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
745 itemCount - 1, res);
747 /* This tests behavior when no files match the wildcard */
748 strcpy(pathBuffer, BAD_EXTENSION);
749 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
750 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
751 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
753 /* There should be NO content in the listbox */
754 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
755 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
758 /* Test DDL_DIRECTORY */
759 strcpy(pathBuffer, "w*.c");
760 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
761 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
762 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
764 /* There should be some content in the listbox. Since the parent directory does not
765 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
767 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
768 ok (itemCount == itemCount_justFiles,
769 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
770 itemCount, itemCount_justFiles);
771 ok(res + 1 == itemCount,
772 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
773 itemCount - 1, res);
775 /* Every single item in the control should start with a w and end in .c. */
776 for (i = 0; i < itemCount; i++) {
777 memset(pathBuffer, 0, MAX_PATH);
778 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
779 p = pathBuffer + strlen(pathBuffer);
781 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
782 (*(p-1) == 'c' || *(p-1) == 'C') &&
783 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
787 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
788 strcpy(pathBuffer, wildcard);
789 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
790 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
791 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
793 /* There should be some content in the listbox. In particular, there should
794 * be at least one element before, since the string "[-c-]" should
795 * have been added. Depending on the user setting, more drives might have
796 * been added.
798 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
799 ok (itemCount >= 1,
800 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
801 itemCount, 1);
802 itemCount_justDrives = itemCount;
803 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
805 /* Every single item in the control should fit the format [-c-] */
806 for (i = 0; i < itemCount; i++) {
807 memset(pathBuffer, 0, MAX_PATH);
808 driveletter = '\0';
809 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
810 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
811 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
812 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
813 if (!(driveletter >= 'a' && driveletter <= 'z')) {
814 /* Correct after invalid entry is found */
815 trace("removing count of invalid entry %s\n", pathBuffer);
816 itemCount_justDrives--;
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|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
824 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
825 BAD_EXTENSION, res, itemCount_justDrives -1);
827 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
828 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
829 itemCount, itemCount_justDrives);
831 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
832 itemCount_justFiles, itemCount_justDrives);
834 /* Test DDL_DRIVES. */
835 strcpy(pathBuffer, wildcard);
836 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
837 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
838 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
840 /* There should be some content in the listbox. In particular, there should
841 * be at least one element before, since the string "[-c-]" should
842 * have been added. Depending on the user setting, more drives might have
843 * been added.
845 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
846 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
847 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
848 itemCount, itemCount_justDrives + itemCount_allFiles);
849 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
851 /* This tests behavior when no files match the wildcard */
852 strcpy(pathBuffer, BAD_EXTENSION);
853 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
854 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
855 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
856 BAD_EXTENSION, res, itemCount_justDrives -1);
858 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
859 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
862 /* Test DDL_DRIVES. */
863 strcpy(pathBuffer, "w*.c");
864 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
865 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
866 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
868 /* There should be some content in the listbox. In particular, there should
869 * be at least one element before, since the string "[-c-]" should
870 * have been added. Depending on the user setting, more drives might have
871 * been added.
873 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
874 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
875 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
876 itemCount, itemCount_justDrives + itemCount_justFiles);
877 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
879 /* Every single item in the control should fit the format [-c-], or w*.c */
880 for (i = 0; i < itemCount; i++) {
881 memset(pathBuffer, 0, MAX_PATH);
882 driveletter = '\0';
883 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
884 p = pathBuffer + strlen(pathBuffer);
885 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
886 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
887 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
888 } else {
890 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
891 (*(p-1) == 'c' || *(p-1) == 'C') &&
892 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
897 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
898 strcpy(pathBuffer, wildcard);
899 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
900 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
901 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
903 /* There should be some content in the listbox. In particular, there should
904 * be exactly the number of plain files, plus the number of mapped drives.
906 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
907 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
908 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
909 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
910 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
912 /* Every single item in the control should start with a w and end in .c,
913 * except for the "[..]" string, which should appear exactly as it is,
914 * and the mapped drives in the format "[-X-]".
916 for (i = 0; i < itemCount; i++) {
917 memset(pathBuffer, 0, MAX_PATH);
918 driveletter = '\0';
919 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
920 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
921 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
925 /* This tests behavior when no files match the wildcard */
926 strcpy(pathBuffer, BAD_EXTENSION);
927 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
928 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
929 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
930 BAD_EXTENSION, res, itemCount_justDrives -1);
932 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
933 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
937 /* Test DDL_DIRECTORY|DDL_DRIVES. */
938 strcpy(pathBuffer, "w*.c");
939 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
940 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
941 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
943 /* There should be some content in the listbox. In particular, there should
944 * be exactly the number of plain files, plus the number of mapped drives.
946 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
947 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
948 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
949 itemCount, itemCount_justFiles + itemCount_justDrives);
950 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
952 /* Every single item in the control should start with a w and end in .c,
953 * except the mapped drives in the format "[-X-]". The "[..]" directory
954 * should not appear.
956 for (i = 0; i < itemCount; i++) {
957 memset(pathBuffer, 0, MAX_PATH);
958 driveletter = '\0';
959 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
960 p = pathBuffer + strlen(pathBuffer);
961 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
962 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
963 } else {
965 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
966 (*(p-1) == 'c' || *(p-1) == 'C') &&
967 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
971 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
972 strcpy(pathBuffer, wildcard);
973 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
974 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
975 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError());
977 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
978 ok (itemCount == itemCount_allDirs,
979 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
980 itemCount, itemCount_allDirs);
981 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
983 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
985 memset(pathBuffer, 0, MAX_PATH);
986 SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
987 ok( !strcmp(pathBuffer, "[..]"), "First element is not [..]\n");
990 /* This tests behavior when no files match the wildcard */
991 strcpy(pathBuffer, BAD_EXTENSION);
992 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
993 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
994 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
995 BAD_EXTENSION, res, -1);
997 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
998 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1001 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1002 strcpy(pathBuffer, "w*.c");
1003 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1004 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1005 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
1007 /* There should be no elements, since "[..]" does not fit w*.c */
1008 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1009 ok (itemCount == 0,
1010 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1011 itemCount, 0);
1013 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1014 strcpy(pathBuffer, wildcard);
1015 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1016 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1017 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1019 /* There should be no plain files on the listbox */
1020 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1021 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1022 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1023 itemCount, itemCount_justDrives + itemCount_allDirs);
1024 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1026 for (i = 0; i < itemCount; i++) {
1027 memset(pathBuffer, 0, MAX_PATH);
1028 driveletter = '\0';
1029 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1030 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1031 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1032 } else {
1033 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1034 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1038 /* This tests behavior when no files match the wildcard */
1039 strcpy(pathBuffer, BAD_EXTENSION);
1040 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1041 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1042 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1043 BAD_EXTENSION, res, itemCount_justDrives -1);
1045 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1046 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1048 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1049 strcpy(pathBuffer, "w*.c");
1050 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1051 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1052 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1054 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
1055 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1056 ok (itemCount == itemCount_justDrives,
1057 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1058 itemCount, itemCount_justDrives);
1059 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1061 for (i = 0; i < itemCount; i++) {
1062 memset(pathBuffer, 0, MAX_PATH);
1063 driveletter = '\0';
1064 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1065 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1066 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1068 DestroyWindow(hList);
1070 DeleteFileA( "wtest1.tmp.c" );
1073 static HWND g_listBox;
1074 static HWND g_label;
1076 #define ID_TEST_LABEL 1001
1077 #define ID_TEST_LISTBOX 1002
1079 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCTA lpcs)
1081 g_label = CreateWindowA(
1082 "Static",
1083 "Contents of static control before DlgDirList.",
1084 WS_CHILD | WS_VISIBLE,
1085 10, 10, 512, 32,
1086 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1087 if (!g_label) return FALSE;
1088 g_listBox = CreateWindowA(
1089 "ListBox",
1090 "DlgDirList test",
1091 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1092 10, 60, 256, 256,
1093 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1094 if (!g_listBox) return FALSE;
1096 return TRUE;
1099 static LRESULT CALLBACK listbox_container_window_procA (
1100 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1102 LRESULT result = 0;
1104 switch (uiMsg) {
1105 case WM_DESTROY:
1106 PostQuitMessage(0);
1107 break;
1108 case WM_CREATE:
1109 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1110 ? 0 : (LRESULT)-1;
1111 break;
1112 default:
1113 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1114 break;
1116 return result;
1119 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1121 WNDCLASSA cls;
1123 cls.style = 0;
1124 cls.cbClsExtra = 0;
1125 cls.cbWndExtra = 0;
1126 cls.hInstance = hInst;
1127 cls.hIcon = NULL;
1128 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
1129 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1130 cls.lpszMenuName = NULL;
1131 cls.lpfnWndProc = listbox_container_window_procA;
1132 cls.lpszClassName = "ListboxContainerClass";
1133 if (!RegisterClassA (&cls)) return FALSE;
1135 return TRUE;
1138 static void test_listbox_dlgdir(void)
1140 HINSTANCE hInst;
1141 HWND hWnd;
1142 int res, itemCount;
1143 int itemCount_allDirs;
1144 int itemCount_justFiles;
1145 int itemCount_justDrives;
1146 int i;
1147 char pathBuffer[MAX_PATH];
1148 char itemBuffer[MAX_PATH];
1149 char tempBuffer[MAX_PATH];
1150 char * p;
1151 char driveletter;
1152 HANDLE file;
1154 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1155 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1156 CloseHandle( file );
1158 /* NOTE: for this test to succeed, there must be no subdirectories
1159 under the current directory. In addition, there must be at least
1160 one file that fits the wildcard w*.c . Normally, the test
1161 directory itself satisfies both conditions.
1164 hInst = GetModuleHandleA(0);
1165 if (!RegisterListboxWindowClass(hInst)) assert(0);
1166 hWnd = CreateWindowA("ListboxContainerClass", "ListboxContainerClass",
1167 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1168 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1169 NULL, NULL, hInst, 0);
1170 assert(hWnd);
1172 /* Test for standard usage */
1174 /* The following should be overwritten by the directory path */
1175 SendMessageA(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1177 /* This should list all the w*.c files in the test directory
1178 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1180 strcpy(pathBuffer, "w*.c");
1181 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1182 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1184 /* Path specification gets converted to uppercase */
1185 ok (!strcmp(pathBuffer, "W*.C"),
1186 "expected conversion to uppercase, got %s\n", pathBuffer);
1188 /* Loaded path should have overwritten the label text */
1189 SendMessageA(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer);
1190 trace("Static control after DlgDirList: %s\n", pathBuffer);
1191 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1193 /* There should be some content in the listbox */
1194 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1195 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1196 itemCount_justFiles = itemCount;
1198 /* Every single item in the control should start with a w and end in .c */
1199 for (i = 0; i < itemCount; i++) {
1200 memset(pathBuffer, 0, MAX_PATH);
1201 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1202 p = pathBuffer + strlen(pathBuffer);
1203 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1204 (*(p-1) == 'c' || *(p-1) == 'C') &&
1205 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1208 /* Test behavior when no files match the wildcard */
1209 strcpy(pathBuffer, BAD_EXTENSION);
1210 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1211 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1213 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1214 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1216 /* Test DDL_DIRECTORY */
1217 strcpy(pathBuffer, "w*.c");
1218 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1219 DDL_DIRECTORY);
1220 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1222 /* There should be some content in the listbox. In particular, there should
1223 * be exactly more elements than before, since the directories should
1224 * have been added.
1226 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1227 itemCount_allDirs = itemCount - itemCount_justFiles;
1228 ok (itemCount >= itemCount_justFiles,
1229 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1230 itemCount, itemCount_justFiles);
1232 /* Every single item in the control should start with a w and end in .c,
1233 * except for the "[..]" string, which should appear exactly as it is.
1235 for (i = 0; i < itemCount; i++) {
1236 memset(pathBuffer, 0, MAX_PATH);
1237 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1238 p = pathBuffer + strlen(pathBuffer);
1239 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1240 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1241 (*(p-1) == 'c' || *(p-1) == 'C') &&
1242 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1245 /* Test behavior when no files match the wildcard */
1246 strcpy(pathBuffer, BAD_EXTENSION);
1247 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1248 DDL_DIRECTORY);
1249 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1251 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1252 ok (itemCount == itemCount_allDirs,
1253 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1254 itemCount_allDirs, itemCount);
1255 for (i = 0; i < itemCount; i++) {
1256 memset(pathBuffer, 0, MAX_PATH);
1257 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1258 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1259 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1263 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1264 strcpy(pathBuffer, "w*.c");
1265 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1266 DDL_DRIVES);
1267 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1269 /* There should be some content in the listbox. In particular, there should
1270 * be at least one element before, since the string "[-c-]" should
1271 * have been added. Depending on the user setting, more drives might have
1272 * been added.
1274 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1275 ok (itemCount >= 1,
1276 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1277 itemCount, 1);
1278 itemCount_justDrives = itemCount;
1280 /* Every single item in the control should fit the format [-c-] */
1281 for (i = 0; i < itemCount; i++) {
1282 memset(pathBuffer, 0, MAX_PATH);
1283 driveletter = '\0';
1284 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1285 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1286 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1287 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1288 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1289 /* Correct after invalid entry is found */
1290 trace("removing count of invalid entry %s\n", pathBuffer);
1291 itemCount_justDrives--;
1295 /* Test behavior when no files match the wildcard */
1296 strcpy(pathBuffer, BAD_EXTENSION);
1297 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1298 DDL_DRIVES);
1299 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1301 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1302 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1305 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1306 strcpy(pathBuffer, "w*.c");
1307 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1308 DDL_DIRECTORY|DDL_DRIVES);
1309 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1311 /* There should be some content in the listbox. In particular, there should
1312 * be exactly the number of plain files, plus the number of mapped drives,
1313 * plus one "[..]"
1315 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1316 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1317 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1318 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1320 /* Every single item in the control should start with a w and end in .c,
1321 * except for the "[..]" string, which should appear exactly as it is,
1322 * and the mapped drives in the format "[-X-]".
1324 for (i = 0; i < itemCount; i++) {
1325 memset(pathBuffer, 0, MAX_PATH);
1326 driveletter = '\0';
1327 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1328 p = pathBuffer + strlen(pathBuffer);
1329 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1330 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1331 } else {
1332 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1333 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1334 (*(p-1) == 'c' || *(p-1) == 'C') &&
1335 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1339 /* Test behavior when no files match the wildcard */
1340 strcpy(pathBuffer, BAD_EXTENSION);
1341 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1342 DDL_DIRECTORY|DDL_DRIVES);
1343 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1345 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1346 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1347 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1348 itemCount_justDrives + itemCount_allDirs, itemCount);
1352 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1353 strcpy(pathBuffer, "w*.c");
1354 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1355 DDL_DIRECTORY|DDL_EXCLUSIVE);
1356 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1358 /* There should be exactly one element: "[..]" */
1359 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1360 ok (itemCount == itemCount_allDirs,
1361 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1362 itemCount, itemCount_allDirs);
1364 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1366 memset(pathBuffer, 0, MAX_PATH);
1367 SendMessageA(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1368 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1371 /* Test behavior when no files match the wildcard */
1372 strcpy(pathBuffer, BAD_EXTENSION);
1373 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1374 DDL_DIRECTORY|DDL_EXCLUSIVE);
1375 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1377 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1378 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1381 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1382 strcpy(pathBuffer, "w*.c");
1383 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1384 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1385 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1387 /* There should be no plain files on the listbox */
1388 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1389 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1390 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1391 itemCount, itemCount_justDrives + itemCount_allDirs);
1393 for (i = 0; i < itemCount; i++) {
1394 memset(pathBuffer, 0, MAX_PATH);
1395 driveletter = '\0';
1396 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1397 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1398 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1399 } else {
1400 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1401 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1405 /* Test behavior when no files match the wildcard */
1406 strcpy(pathBuffer, BAD_EXTENSION);
1407 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1408 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1409 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1411 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1412 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1413 "DlgDirList() incorrectly filled the listbox!\n");
1415 /* Now test DlgDirSelectEx() in normal operation */
1416 /* Fill with everything - drives, directory and all plain files. */
1417 strcpy(pathBuffer, "*");
1418 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1419 DDL_DIRECTORY|DDL_DRIVES);
1420 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1422 SendMessageA(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1423 memset(pathBuffer, 0, MAX_PATH);
1424 SetLastError(0xdeadbeef);
1425 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1426 ok (GetLastError() == 0xdeadbeef,
1427 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1428 GetLastError());
1429 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1430 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1432 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1434 /* Test proper drive/dir/file recognition */
1435 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1436 for (i = 0; i < itemCount; i++) {
1437 memset(itemBuffer, 0, MAX_PATH);
1438 memset(pathBuffer, 0, MAX_PATH);
1439 memset(tempBuffer, 0, MAX_PATH);
1440 driveletter = '\0';
1441 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1442 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1443 ok (res == i, "SendMessageA(LB_SETCURSEL, %d) failed\n", i);
1444 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1445 /* Current item is a drive letter */
1446 SetLastError(0xdeadbeef);
1447 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1448 ok (GetLastError() == 0xdeadbeef,
1449 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1450 i, GetLastError());
1451 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1453 /* For drive letters, DlgDirSelectEx tacks on a colon */
1454 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1455 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1456 } else if (itemBuffer[0] == '[') {
1457 /* Current item is the parent directory */
1458 SetLastError(0xdeadbeef);
1459 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1460 ok (GetLastError() == 0xdeadbeef,
1461 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1462 i, GetLastError());
1463 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1465 /* For directories, DlgDirSelectEx tacks on a backslash */
1466 p = pathBuffer + strlen(pathBuffer);
1467 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1469 tempBuffer[0] = '[';
1470 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1471 strcat(tempBuffer, "]");
1472 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1473 } else {
1474 /* Current item is a plain file */
1475 SetLastError(0xdeadbeef);
1476 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1477 ok (GetLastError() == 0xdeadbeef,
1478 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1479 i, GetLastError());
1480 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1482 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1483 * for example, "Makefile", which gets reported as "Makefile."
1485 strcpy(tempBuffer, itemBuffer);
1486 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1487 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1491 DeleteFileA( "wtest1.tmp.c" );
1493 /* Now test DlgDirSelectEx() in abnormal operation */
1494 /* Fill list with bogus entries, that look somewhat valid */
1495 SendMessageA(g_listBox, LB_RESETCONTENT, 0, 0);
1496 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1497 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1498 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1499 for (i = 0; i < itemCount; i++) {
1500 memset(itemBuffer, 0, MAX_PATH);
1501 memset(pathBuffer, 0, MAX_PATH);
1502 memset(tempBuffer, 0, MAX_PATH);
1503 driveletter = '\0';
1504 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1505 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1506 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1507 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1508 /* Current item is a drive letter */
1509 SetLastError(0xdeadbeef);
1510 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1511 ok (GetLastError() == 0xdeadbeef,
1512 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1513 i, GetLastError());
1514 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1516 /* For drive letters, DlgDirSelectEx tacks on a colon */
1517 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1518 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1519 } else if (itemBuffer[0] == '[') {
1520 /* Current item is the parent directory */
1521 SetLastError(0xdeadbeef);
1522 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1523 ok (GetLastError() == 0xdeadbeef,
1524 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1525 i, GetLastError());
1526 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1528 /* For directories, DlgDirSelectEx tacks on a backslash */
1529 p = pathBuffer + strlen(pathBuffer);
1530 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1532 tempBuffer[0] = '[';
1533 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1534 strcat(tempBuffer, "]");
1535 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1536 } else {
1537 /* Current item is a plain file */
1538 SetLastError(0xdeadbeef);
1539 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1540 ok (GetLastError() == 0xdeadbeef,
1541 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1542 i, GetLastError());
1543 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1545 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1546 * This affects for example, "Makefile", which gets reported as "Makefile."
1548 strcpy(tempBuffer, itemBuffer);
1549 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1550 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1554 /* Test behavior when loading folders from root with and without wildcard */
1555 strcpy(pathBuffer, "C:\\");
1556 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1557 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\ folders\n");
1558 todo_wine ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1559 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1561 strcpy(pathBuffer, "C:\\*");
1562 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1563 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\* folders\n");
1564 ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1565 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1567 /* Try loading files from an invalid folder */
1568 SetLastError(0xdeadbeef);
1569 strcpy(pathBuffer, "C:\\INVALID$$DIR");
1570 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1571 todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
1572 todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
1573 "GetLastError should return 0x589, got 0x%X\n",GetLastError());
1575 DestroyWindow(hWnd);
1578 static void test_set_count( void )
1580 HWND parent, listbox;
1581 LONG ret;
1582 RECT r;
1584 parent = create_parent();
1585 listbox = create_listbox( LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VISIBLE, parent );
1587 UpdateWindow( listbox );
1588 GetUpdateRect( listbox, &r, TRUE );
1589 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1591 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
1592 ok( ret == 0, "got %d\n", ret );
1593 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
1594 ok( ret == 100, "got %d\n", ret );
1596 GetUpdateRect( listbox, &r, TRUE );
1597 ok( !IsRectEmpty( &r ), "got empty rect\n");
1599 ValidateRect( listbox, NULL );
1600 GetUpdateRect( listbox, &r, TRUE );
1601 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1603 ret = SendMessageA( listbox, LB_SETCOUNT, 99, 0 );
1604 ok( ret == 0, "got %d\n", ret );
1606 GetUpdateRect( listbox, &r, TRUE );
1607 ok( !IsRectEmpty( &r ), "got empty rect\n");
1609 DestroyWindow( listbox );
1610 DestroyWindow( parent );
1613 static DWORD (WINAPI *pGetListBoxInfo)(HWND);
1614 static int lb_getlistboxinfo;
1616 static LRESULT WINAPI listbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1618 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
1620 if (message == LB_GETLISTBOXINFO)
1621 lb_getlistboxinfo++;
1623 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
1626 static void test_GetListBoxInfo(void)
1628 HWND listbox, parent;
1629 WNDPROC oldproc;
1630 DWORD ret;
1632 pGetListBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetListBoxInfo");
1634 if (!pGetListBoxInfo)
1636 win_skip("GetListBoxInfo() not available\n");
1637 return;
1640 parent = create_parent();
1641 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1643 oldproc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (LONG_PTR)listbox_subclass_proc);
1644 SetWindowLongPtrA(listbox, GWLP_USERDATA, (LONG_PTR)oldproc);
1646 lb_getlistboxinfo = 0;
1647 ret = pGetListBoxInfo(listbox);
1648 ok(ret > 0, "got %d\n", ret);
1649 todo_wine
1650 ok(lb_getlistboxinfo == 0, "got %d\n", lb_getlistboxinfo);
1652 DestroyWindow(listbox);
1653 DestroyWindow(parent);
1656 static void test_missing_lbuttonup( void )
1658 HWND listbox, parent, capture;
1660 parent = create_parent();
1661 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1663 /* Send button down without a corresponding button up */
1664 SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(10,10));
1665 capture = GetCapture();
1666 ok(capture == listbox, "got %p expected %p\n", capture, listbox);
1668 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */
1669 got_selchange = 0;
1670 SetFocus(NULL);
1671 capture = GetCapture();
1672 ok(capture == NULL, "got %p\n", capture);
1673 ok(got_selchange, "got %d\n", got_selchange);
1675 DestroyWindow(listbox);
1676 DestroyWindow(parent);
1679 static void test_extents(void)
1681 HWND listbox, parent;
1682 DWORD res;
1683 SCROLLINFO sinfo;
1684 BOOL br;
1686 parent = create_parent();
1688 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1690 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1691 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1693 sinfo.cbSize = sizeof(sinfo);
1694 sinfo.fMask = SIF_RANGE;
1695 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1696 ok(br == TRUE, "GetScrollInfo failed\n");
1697 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1698 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1699 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1700 "List box should not have a horizontal scroll bar\n");
1702 /* horizontal extent < width */
1703 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1705 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1706 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1708 sinfo.cbSize = sizeof(sinfo);
1709 sinfo.fMask = SIF_RANGE;
1710 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1711 ok(br == TRUE, "GetScrollInfo failed\n");
1712 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1713 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1714 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1715 "List box should not have a horizontal scroll bar\n");
1717 /* horizontal extent > width */
1718 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1720 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1721 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1723 sinfo.cbSize = sizeof(sinfo);
1724 sinfo.fMask = SIF_RANGE;
1725 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1726 ok(br == TRUE, "GetScrollInfo failed\n");
1727 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1728 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1729 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1730 "List box should not have a horizontal scroll bar\n");
1732 DestroyWindow(listbox);
1735 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL, parent);
1737 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1738 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1740 sinfo.cbSize = sizeof(sinfo);
1741 sinfo.fMask = SIF_RANGE;
1742 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1743 ok(br == TRUE, "GetScrollInfo failed\n");
1744 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1745 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1746 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1747 "List box should not have a horizontal scroll bar\n");
1749 /* horizontal extent < width */
1750 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1752 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1753 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1755 sinfo.cbSize = sizeof(sinfo);
1756 sinfo.fMask = SIF_RANGE;
1757 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1758 ok(br == TRUE, "GetScrollInfo failed\n");
1759 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1760 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
1761 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1762 "List box should not have a horizontal scroll bar\n");
1764 /* horizontal extent > width */
1765 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1767 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1768 ok(res == 184, "Got wrong 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 == 183, "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 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
1781 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1782 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
1784 sinfo.cbSize = sizeof(sinfo);
1785 sinfo.fMask = SIF_RANGE;
1786 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1787 ok(br == TRUE, "GetScrollInfo failed\n");
1788 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1789 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1790 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1791 "List box should not have a horizontal scroll bar\n");
1793 DestroyWindow(listbox);
1796 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL | LBS_DISABLENOSCROLL, parent);
1798 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1799 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1801 sinfo.cbSize = sizeof(sinfo);
1802 sinfo.fMask = SIF_RANGE;
1803 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1804 ok(br == TRUE, "GetScrollInfo failed\n");
1805 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1806 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1807 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1808 "List box should have a horizontal scroll bar\n");
1810 /* horizontal extent < width */
1811 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1813 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1814 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1816 sinfo.cbSize = sizeof(sinfo);
1817 sinfo.fMask = SIF_RANGE;
1818 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1819 ok(br == TRUE, "GetScrollInfo failed\n");
1820 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1821 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
1822 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1823 "List box should have a horizontal scroll bar\n");
1825 /* horizontal extent > width */
1826 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1828 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1829 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1831 sinfo.cbSize = sizeof(sinfo);
1832 sinfo.fMask = SIF_RANGE;
1833 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1834 ok(br == TRUE, "GetScrollInfo failed\n");
1835 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1836 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
1837 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1838 "List box should have a horizontal scroll bar\n");
1840 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
1842 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1843 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
1845 sinfo.cbSize = sizeof(sinfo);
1846 sinfo.fMask = SIF_RANGE;
1847 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1848 ok(br == TRUE, "GetScrollInfo failed\n");
1849 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1850 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1851 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1852 "List box should have a horizontal scroll bar\n");
1854 DestroyWindow(listbox);
1856 DestroyWindow(parent);
1859 static void test_WM_MEASUREITEM(void)
1861 HWND parent, listbox;
1862 LRESULT data;
1864 parent = create_parent();
1865 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE, parent);
1867 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
1868 ok(data == (LRESULT)strings[0], "data = %08lx, expected %p\n", data, strings[0]);
1869 DestroyWindow(parent);
1871 parent = create_parent();
1872 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS, parent);
1874 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
1875 ok(!data, "data = %08lx\n", data);
1876 DestroyWindow(parent);
1879 START_TEST(listbox)
1881 const struct listbox_test SS =
1882 /* {add_style} */
1883 {{0},
1884 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1885 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1886 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1887 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1888 /* {selected, anchor, caret, selcount}{TODO fields} */
1889 const struct listbox_test SS_NS =
1890 {{LBS_NOSEL},
1891 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1892 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1893 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1894 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1895 const struct listbox_test MS =
1896 {{LBS_MULTIPLESEL},
1897 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1898 { 1, 1, 1, 1}, {0,0,0,0},
1899 { 2, 1, 2, 1}, {0,0,0,0},
1900 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1901 const struct listbox_test MS_NS =
1902 {{LBS_MULTIPLESEL | LBS_NOSEL},
1903 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1904 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1905 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1906 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1907 const struct listbox_test ES =
1908 {{LBS_EXTENDEDSEL},
1909 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1910 { 1, 1, 1, 1}, {0,0,0,0},
1911 { 2, 2, 2, 1}, {0,0,0,0},
1912 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1913 const struct listbox_test ES_NS =
1914 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1915 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1916 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1917 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1918 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1919 const struct listbox_test EMS =
1920 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1921 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1922 { 1, 1, 1, 1}, {0,0,0,0},
1923 { 2, 2, 2, 1}, {0,0,0,0},
1924 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1925 const struct listbox_test EMS_NS =
1926 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1927 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1928 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1929 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1930 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1932 trace (" Testing single selection...\n");
1933 check (SS);
1934 trace (" ... with NOSEL\n");
1935 check (SS_NS);
1936 trace (" Testing multiple selection...\n");
1937 check (MS);
1938 trace (" ... with NOSEL\n");
1939 check (MS_NS);
1940 trace (" Testing extended selection...\n");
1941 check (ES);
1942 trace (" ... with NOSEL\n");
1943 check (ES_NS);
1944 trace (" Testing extended and multiple selection...\n");
1945 check (EMS);
1946 trace (" ... with NOSEL\n");
1947 check (EMS_NS);
1949 check_item_height();
1950 test_ownerdraw();
1951 test_LB_SELITEMRANGE();
1952 test_LB_SETCURSEL();
1953 test_listbox_height();
1954 test_itemfrompoint();
1955 test_listbox_item_data();
1956 test_listbox_LB_DIR();
1957 test_listbox_dlgdir();
1958 test_set_count();
1959 test_GetListBoxInfo();
1960 test_missing_lbuttonup();
1961 test_extents();
1962 test_WM_MEASUREITEM();