wined3d: Correctly destroy the adapter on format initialization failure in no3d mode.
[wine/zf.git] / dlls / user32 / tests / listbox.c
blobcd372f8ac59bffc116a23cbe959ac809e2f9e1e9
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, ARRAY_SIZE(buf));
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_stat init, init_todo;
94 struct listbox_stat click, click_todo;
95 struct listbox_stat step, step_todo;
96 struct listbox_stat sel, sel_todo;
99 static void
100 listbox_query (HWND handle, struct listbox_stat *results)
102 results->selected = SendMessageA(handle, LB_GETCURSEL, 0, 0);
103 results->anchor = SendMessageA(handle, LB_GETANCHORINDEX, 0, 0);
104 results->caret = SendMessageA(handle, LB_GETCARETINDEX, 0, 0);
105 results->selcount = SendMessageA(handle, LB_GETSELCOUNT, 0, 0);
108 static void
109 buttonpress (HWND handle, WORD x, WORD y)
111 LPARAM lp=x+(y<<16);
113 WAIT;
114 SendMessageA(handle, WM_LBUTTONDOWN, MK_LBUTTON, lp);
115 SendMessageA(handle, WM_LBUTTONUP, 0, lp);
116 REDRAW;
119 static void
120 keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
122 LPARAM lp=1+(scancode<<16)+(extended?KEYEVENTF_EXTENDEDKEY:0);
124 WAIT;
125 SendMessageA(handle, WM_KEYDOWN, keycode, lp);
126 SendMessageA(handle, WM_KEYUP , keycode, lp | 0xc000000);
127 REDRAW;
130 #define listbox_field_ok(t, s, f, got) \
131 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
132 ": expected %d, got %d\n", style, t.s.f, got.f)
134 #define listbox_todo_field_ok(t, s, f, got) \
135 todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
137 #define listbox_ok(t, s, got) \
138 listbox_todo_field_ok(t, s, selected, got); \
139 listbox_todo_field_ok(t, s, anchor, got); \
140 listbox_todo_field_ok(t, s, caret, got); \
141 listbox_todo_field_ok(t, s, selcount, got)
143 static void
144 check (DWORD style, const struct listbox_test test)
146 struct listbox_stat answer;
147 RECT second_item;
148 int i;
149 int res;
150 HWND hLB;
152 hLB = create_listbox (style, 0);
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(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 && !(style & LBS_NODATA); 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 ok(resA == resW, "Unexpected text length.\n");
188 WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL );
189 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
191 HeapFree (GetProcessHeap(), 0, txtw);
192 HeapFree (GetProcessHeap(), 0, txt);
195 /* Confirm the count of items, and that an invalid delete does not remove anything */
196 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
197 ok((res==4), "Expected 4 items, got %d\n", res);
198 res = SendMessageA(hLB, LB_DELETESTRING, -1, 0);
199 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
200 res = SendMessageA(hLB, LB_DELETESTRING, 4, 0);
201 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
202 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
203 ok((res==4), "Expected 4 items, got %d\n", res);
205 WAIT;
206 DestroyWindow (hLB);
209 static void check_item_height(void)
211 HWND hLB;
212 HDC hdc;
213 HFONT font;
214 TEXTMETRICA tm;
215 INT itemHeight;
217 hLB = create_listbox (0, 0);
218 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n");
219 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n");
220 ok (GetTextMetricsA( hdc, &tm ), "Can't read font metrics\n");
221 ReleaseDC( hLB, hdc);
223 ok (SendMessageA(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
225 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
226 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight);
228 DestroyWindow (hLB);
230 hLB = CreateWindowA("LISTBOX", "TestList", LBS_OWNERDRAWVARIABLE,
231 0, 0, 100, 100, NULL, NULL, NULL, 0);
232 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
233 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
234 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 5, 0);
235 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
236 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, -5, 0);
237 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
238 DestroyWindow (hLB);
241 static int got_selchange;
243 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
245 switch (msg)
247 case WM_MEASUREITEM:
249 DWORD style = GetWindowLongA(GetWindow(hwnd, GW_CHILD), GWL_STYLE);
250 MEASUREITEMSTRUCT *mi = (void*)lparam;
252 ok(wparam == mi->CtlID, "got wParam=%08lx, expected %08x\n", wparam, mi->CtlID);
253 ok(mi->CtlType == ODT_LISTBOX, "mi->CtlType = %u\n", mi->CtlType);
254 ok(mi->CtlID == 1, "mi->CtlID = %u\n", mi->CtlID);
255 ok(mi->itemHeight, "mi->itemHeight = 0\n");
257 if (mi->itemID > 4 || style & LBS_OWNERDRAWFIXED)
258 break;
260 if (style & LBS_HASSTRINGS)
262 ok(!strcmp_aw((WCHAR*)mi->itemData, strings[mi->itemID]),
263 "mi->itemData = %s (%d)\n", wine_dbgstr_w((WCHAR*)mi->itemData), mi->itemID);
265 else
267 ok((void*)mi->itemData == strings[mi->itemID],
268 "mi->itemData = %08lx, expected %p\n", mi->itemData, strings[mi->itemID]);
270 break;
272 case WM_DRAWITEM:
274 RECT rc_item, rc_client, rc_clip;
275 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
277 trace("%p WM_DRAWITEM %08lx %08lx\n", hwnd, wparam, lparam);
279 ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
280 wparam, dis->CtlID);
281 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
283 GetClientRect(dis->hwndItem, &rc_client);
284 trace("hwndItem %p client rect %s\n", dis->hwndItem, wine_dbgstr_rect(&rc_client));
285 GetClipBox(dis->hDC, &rc_clip);
286 trace("clip rect %s\n", wine_dbgstr_rect(&rc_clip));
287 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip),
288 "client rect of the listbox should be equal to the clip box,"
289 "or the clip box should be empty\n");
291 trace("rcItem %s\n", wine_dbgstr_rect(&dis->rcItem));
292 SendMessageA(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
293 trace("item rect %s\n", wine_dbgstr_rect(&rc_item));
294 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
296 break;
299 case WM_COMMAND:
300 if (HIWORD( wparam ) == LBN_SELCHANGE) got_selchange++;
301 break;
303 default:
304 break;
307 return DefWindowProcA(hwnd, msg, wparam, lparam);
310 static HWND create_parent( void )
312 WNDCLASSA cls;
313 HWND parent;
314 static ATOM class;
316 if (!class)
318 cls.style = 0;
319 cls.lpfnWndProc = main_window_proc;
320 cls.cbClsExtra = 0;
321 cls.cbWndExtra = 0;
322 cls.hInstance = GetModuleHandleA(NULL);
323 cls.hIcon = 0;
324 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
325 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
326 cls.lpszMenuName = NULL;
327 cls.lpszClassName = "main_window_class";
328 class = RegisterClassA( &cls );
331 parent = CreateWindowExA(0, "main_window_class", NULL,
332 WS_POPUP | WS_VISIBLE,
333 100, 100, 400, 400,
334 GetDesktopWindow(), 0,
335 GetModuleHandleA(NULL), NULL);
336 return parent;
339 static void test_ownerdraw(void)
341 static const DWORD styles[] =
344 LBS_NODATA
346 HWND parent, hLB;
347 INT ret;
348 RECT rc;
349 UINT i;
351 parent = create_parent();
352 assert(parent);
354 for (i = 0; i < ARRAY_SIZE(styles); i++)
356 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE | styles[i], parent);
357 assert(hLB);
359 SetForegroundWindow(hLB);
360 UpdateWindow(hLB);
362 /* make height short enough */
363 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
364 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
365 SWP_NOZORDER | SWP_NOMOVE);
367 /* make 0 item invisible */
368 SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
369 ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
370 ok(ret == 1, "wrong top index %d\n", ret);
372 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
373 trace("item 0 rect %s\n", wine_dbgstr_rect(&rc));
374 ok(!IsRectEmpty(&rc), "empty item rect\n");
375 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
377 DestroyWindow(hLB);
379 /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
380 hLB = CreateWindowA("listbox", "TestList", LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE | styles[i],
381 0, 0, 100, 100, NULL, NULL, NULL, 0);
382 ok(hLB != NULL, "last error 0x%08x\n", GetLastError());
384 ok(GetWindowLongA(hLB, GWL_STYLE) & LBS_OWNERDRAWVARIABLE, "Unexpected window style.\n");
386 ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
387 ok(ret == 0, "Unexpected return value %d.\n", ret);
388 ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
389 ok(ret == 1, "Unexpected return value %d.\n", ret);
391 ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 13);
392 ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
394 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
395 ok(ret == 13, "Unexpected item height %d.\n", ret);
397 ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 1, 42);
398 ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
400 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
401 ok(ret == 42, "Unexpected item height %d.\n", ret);
403 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 1, 0);
404 ok(ret == 42, "Unexpected item height %d.\n", ret);
406 DestroyWindow (hLB);
408 DestroyWindow(parent);
411 #define listbox_test_query(exp, got) \
412 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
413 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
414 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
415 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
417 static void test_LB_SELITEMRANGE(void)
419 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
420 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
421 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
422 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
423 HWND hLB;
424 struct listbox_stat answer;
425 INT ret;
427 trace("testing LB_SELITEMRANGE\n");
429 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
430 assert(hLB);
432 listbox_query(hLB, &answer);
433 listbox_test_query(test_nosel, answer);
435 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
436 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
437 listbox_query(hLB, &answer);
438 listbox_test_query(test_1, answer);
440 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
441 listbox_query(hLB, &answer);
442 listbox_test_query(test_nosel, answer);
444 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
445 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
446 listbox_query(hLB, &answer);
447 listbox_test_query(test_3, answer);
449 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
450 listbox_query(hLB, &answer);
451 listbox_test_query(test_nosel, answer);
453 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
454 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
455 listbox_query(hLB, &answer);
456 listbox_test_query(test_nosel, answer);
458 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
459 listbox_query(hLB, &answer);
460 listbox_test_query(test_nosel, answer);
462 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
463 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
464 listbox_query(hLB, &answer);
465 listbox_test_query(test_1, answer);
467 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
468 listbox_query(hLB, &answer);
469 listbox_test_query(test_nosel, answer);
471 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
472 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
473 listbox_query(hLB, &answer);
474 listbox_test_query(test_nosel, answer);
476 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
477 listbox_query(hLB, &answer);
478 listbox_test_query(test_nosel, answer);
480 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
481 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
482 listbox_query(hLB, &answer);
483 listbox_test_query(test_2, answer);
485 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
486 listbox_query(hLB, &answer);
487 listbox_test_query(test_nosel, answer);
489 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
490 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
491 listbox_query(hLB, &answer);
492 listbox_test_query(test_2, answer);
494 DestroyWindow(hLB);
497 static void test_LB_SETCURSEL(void)
499 HWND parent, hLB;
500 INT ret;
502 trace("testing LB_SETCURSEL\n");
504 parent = create_parent();
505 assert(parent);
507 hLB = create_listbox(LBS_NOINTEGRALHEIGHT | WS_CHILD, parent);
508 assert(hLB);
510 SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32);
512 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
513 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
515 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
516 ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret);
517 ret = GetScrollPos(hLB, SB_VERT);
518 ok(ret == 0, "expected vscroll 0, got %d\n", ret);
520 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
521 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
523 ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0);
524 ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret);
525 ret = GetScrollPos(hLB, SB_VERT);
526 ok(ret == 1, "expected vscroll 1, got %d\n", ret);
528 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
529 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
531 DestroyWindow(hLB);
533 hLB = create_listbox(0, 0);
534 ok(hLB != NULL, "Failed to create ListBox window.\n");
536 ret = SendMessageA(hLB, LB_SETCURSEL, 1, 0);
537 ok(ret == 1, "Unexpected return value %d.\n", ret);
539 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
540 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
542 DestroyWindow(hLB);
544 /* LBS_EXTENDEDSEL */
545 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
546 ok(hLB != NULL, "Failed to create ListBox window.\n");
548 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
549 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
551 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
552 ok(ret == -1, "Unexpected return value %d.\n", ret);
554 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
555 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
557 DestroyWindow(hLB);
559 /* LBS_MULTIPLESEL */
560 hLB = create_listbox(LBS_MULTIPLESEL, 0);
561 ok(hLB != NULL, "Failed to create ListBox window.\n");
563 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
564 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
566 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
567 ok(ret == -1, "Unexpected return value %d.\n", ret);
569 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
570 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
572 DestroyWindow(hLB);
575 static void test_LB_SETSEL(void)
577 HWND list;
578 int ret;
580 /* LBS_EXTENDEDSEL */
581 list = create_listbox(LBS_EXTENDEDSEL, 0);
582 ok(list != NULL, "Failed to create ListBox window.\n");
584 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
585 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
586 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
587 ok(ret == 0, "Unexpected caret index %d.\n", ret);
589 ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
590 ok(ret == 0, "Unexpected return value %d.\n", ret);
591 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
592 ok(ret == 0, "Unexpected anchor index %d.\n", ret);
593 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
594 ok(ret == 0, "Unexpected caret index %d.\n", ret);
596 ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
597 ok(ret == 0, "Unexpected return value %d.\n", ret);
598 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
599 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
600 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
601 ok(ret == 1, "Unexpected caret index %d.\n", ret);
603 ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
604 ok(ret == 0, "Unexpected return value %d.\n", ret);
605 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
606 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
607 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
608 ok(ret == 1, "Unexpected caret index %d.\n", ret);
610 DestroyWindow(list);
612 /* LBS_MULTIPLESEL */
613 list = create_listbox(LBS_MULTIPLESEL, 0);
614 ok(list != NULL, "Failed to create ListBox window.\n");
616 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
617 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
618 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
619 ok(ret == 0, "Unexpected caret index %d.\n", ret);
621 ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
622 ok(ret == 0, "Unexpected return value %d.\n", ret);
623 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
624 ok(ret == 0, "Unexpected anchor index %d.\n", ret);
625 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
626 ok(ret == 0, "Unexpected caret index %d.\n", ret);
628 ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
629 ok(ret == 0, "Unexpected return value %d.\n", ret);
630 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
631 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
632 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
633 ok(ret == 1, "Unexpected caret index %d.\n", ret);
635 ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
636 ok(ret == 0, "Unexpected return value %d.\n", ret);
637 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
638 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
639 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
640 ok(ret == 1, "Unexpected caret index %d.\n", ret);
642 DestroyWindow(list);
645 static void test_listbox_height(void)
647 HWND hList;
648 int r, id;
650 hList = CreateWindowA( "ListBox", "list test", 0,
651 1, 1, 600, 100, NULL, NULL, NULL, NULL );
652 ok( hList != NULL, "failed to create listbox\n");
654 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
655 ok( id == 0, "item id wrong\n");
657 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
658 ok( r == 0, "send message failed\n");
660 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
661 ok( r == 20, "height wrong\n");
663 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
664 ok( r == -1, "send message failed\n");
666 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
667 ok( r == 20, "height wrong\n");
669 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
670 ok( r == -1, "send message failed\n");
672 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
673 ok( r == 20, "height wrong\n");
675 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
676 ok( r == 0, "send message failed\n");
678 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
679 ok( r == 0xff, "height wrong\n");
681 DestroyWindow( hList );
684 static void test_changing_selection_styles(void)
686 static const DWORD styles[] =
689 LBS_NODATA | LBS_OWNERDRAWFIXED
691 static const DWORD selstyles[] =
694 LBS_MULTIPLESEL,
695 LBS_EXTENDEDSEL,
696 LBS_MULTIPLESEL | LBS_EXTENDEDSEL
698 static const LONG selexpect_single[] = { 0, 0, 1 };
699 static const LONG selexpect_single2[] = { 1, 0, 0 };
700 static const LONG selexpect_multi[] = { 1, 0, 1 };
701 static const LONG selexpect_multi2[] = { 1, 1, 0 };
703 HWND parent, listbox;
704 DWORD style;
705 LONG ret;
706 UINT i, j, k;
708 parent = create_parent();
709 ok(parent != NULL, "Failed to create parent window.\n");
710 for (i = 0; i < ARRAY_SIZE(styles); i++)
712 /* Test if changing selection styles affects selection storage */
713 for (j = 0; j < ARRAY_SIZE(selstyles); j++)
715 LONG setcursel_expect, selitemrange_expect, getselcount_expect;
716 const LONG *selexpect;
718 listbox = CreateWindowA("listbox", "TestList", styles[i] | selstyles[j] | WS_CHILD | WS_VISIBLE,
719 0, 0, 100, 100, parent, (HMENU)1, NULL, 0);
720 ok(listbox != NULL, "%u: Failed to create ListBox window.\n", j);
722 if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
724 setcursel_expect = LB_ERR;
725 selitemrange_expect = LB_OKAY;
726 getselcount_expect = 2;
727 selexpect = selexpect_multi;
729 else
731 setcursel_expect = 2;
732 selitemrange_expect = LB_ERR;
733 getselcount_expect = LB_ERR;
734 selexpect = selexpect_single;
737 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
739 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"x");
740 ok(ret == k, "%u: Unexpected return value %d, expected %d.\n", j, ret, k);
742 ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
743 ok(ret == ARRAY_SIZE(selexpect_multi), "%u: Unexpected count %d.\n", j, ret);
745 /* Select items with different methods */
746 ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0);
747 ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
748 ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 0));
749 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
750 ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 2));
751 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
753 /* Verify that the proper items are selected */
754 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
756 ret = SendMessageA(listbox, LB_GETSEL, k, 0);
757 ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
758 j, ret, selexpect[k]);
761 /* Now change the selection style */
762 style = GetWindowLongA(listbox, GWL_STYLE);
763 ok((style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == selstyles[j],
764 "%u: unexpected window styles %#x.\n", j, style);
765 if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
766 style &= ~selstyles[j];
767 else
768 style |= LBS_MULTIPLESEL | LBS_EXTENDEDSEL;
769 SetWindowLongA(listbox, GWL_STYLE, style);
770 style = GetWindowLongA(listbox, GWL_STYLE);
771 ok(!(style & selstyles[j]), "%u: unexpected window styles %#x.\n", j, style);
773 /* Verify that the same items are selected */
774 ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
775 ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
776 j, getselcount_expect, ret);
778 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
780 ret = SendMessageA(listbox, LB_GETSEL, k, 0);
781 ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
782 j, ret, selexpect[k]);
785 /* Lastly see if we can still change the selection as before with old style */
786 if (setcursel_expect != LB_ERR) setcursel_expect = 0;
787 ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0);
788 ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
789 ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 1));
790 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
791 ret = SendMessageA(listbox, LB_SELITEMRANGE, FALSE, MAKELPARAM(2, 2));
792 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
794 /* And verify the selections */
795 selexpect = (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) ? selexpect_multi2 : selexpect_single2;
796 ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
797 ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
798 j, getselcount_expect, ret);
800 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
802 ret = SendMessageA(listbox, LB_GETSEL, k, 0);
803 ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
804 j, ret, selexpect[k]);
807 DestroyWindow(listbox);
810 DestroyWindow(parent);
813 static void test_itemfrompoint(void)
815 /* WS_POPUP is required in order to have a more accurate size calculation (
816 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
817 behavior of partially-displayed item.
819 HWND hList = CreateWindowA( "ListBox", "list test",
820 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
821 1, 1, 600, 100, NULL, NULL, NULL, NULL );
822 ULONG r, id;
823 RECT rc;
825 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000, nt4 returns 0xffffffff */
826 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
827 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
829 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
830 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
832 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
833 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
835 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
836 ok( id == 0, "item id wrong\n");
837 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
838 ok( id == 1, "item id wrong\n");
840 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
841 ok( r == 0x1, "ret %x\n", r );
843 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
844 ok( r == 0x10001 || broken(r == 1), /* nt4 */
845 "ret %x\n", r );
847 /* Resize control so that below assertions about sizes are valid */
848 r = SendMessageA( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
849 ok( r == 1, "ret %x\n", r);
850 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
851 ok( r != 0, "ret %x\n", r);
853 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
854 ok( id == 2, "item id wrong\n");
855 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
856 ok( id == 3, "item id wrong\n");
857 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
858 ok( id == 4, "item id wrong\n");
859 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
860 ok( id == 5, "item id wrong\n");
861 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
862 ok( id == 6, "item id wrong\n");
863 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
864 ok( id == 7, "item id wrong\n");
866 /* Set the listbox up so that id 1 is at the top, this leaves 5
867 partially visible at the bottom and 6, 7 are invisible */
869 SendMessageA( hList, LB_SETTOPINDEX, 1, 0);
870 r = SendMessageA( hList, LB_GETTOPINDEX, 0, 0);
871 ok( r == 1, "top %d\n", r);
873 r = SendMessageA( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
874 ok( r == 1, "ret %x\n", r);
875 r = SendMessageA( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
876 ok( r == 0, "ret %x\n", r);
878 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
879 ok( r == 1, "ret %x\n", r);
881 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
882 ok( r == 0x10001 || broken(r == 1), /* nt4 */
883 "ret %x\n", r );
885 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
886 ok( r == 0x10001 || broken(r == 1), /* nt4 */
887 "ret %x\n", r );
889 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
890 ok( r == 0x10005 || broken(r == 5), /* nt4 */
891 "item %x\n", r );
893 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
894 ok( r == 0x10005 || broken(r == 5), /* nt4 */
895 "item %x\n", r );
897 DestroyWindow( hList );
900 static void test_listbox_item_data(void)
902 HWND hList;
903 int r, id;
905 hList = CreateWindowA( "ListBox", "list test", 0,
906 1, 1, 600, 100, NULL, NULL, NULL, NULL );
907 ok( hList != NULL, "failed to create listbox\n");
909 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
910 ok( id == 0, "item id wrong\n");
912 r = SendMessageA( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
913 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
915 r = SendMessageA( hList, LB_GETITEMDATA, 0, 0);
916 ok( r == 20, "get item data failed\n");
918 DestroyWindow( hList );
921 static void test_listbox_LB_DIR(void)
923 char path[MAX_PATH], curdir[MAX_PATH];
924 HWND hList;
925 int res, itemCount;
926 int itemCount_justFiles;
927 int itemCount_justDrives;
928 int itemCount_allFiles;
929 int itemCount_allDirs;
930 int i;
931 char pathBuffer[MAX_PATH];
932 char * p;
933 char driveletter;
934 const char *wildcard = "*";
935 HANDLE file;
936 BOOL ret;
938 GetCurrentDirectoryA(ARRAY_SIZE(curdir), curdir);
940 GetTempPathA(ARRAY_SIZE(path), path);
941 ret = SetCurrentDirectoryA(path);
942 ok(ret, "Failed to set current directory.\n");
944 ret = CreateDirectoryA("lb_dir_test", NULL);
945 ok(ret, "Failed to create test directory.\n");
947 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
948 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
949 CloseHandle( file );
951 /* NOTE: for this test to succeed, there must be no subdirectories
952 under the current directory. In addition, there must be at least
953 one file that fits the wildcard w*.c . Normally, the test
954 directory itself satisfies both conditions.
956 hList = CreateWindowA( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
957 1, 1, 600, 100, NULL, NULL, NULL, NULL );
958 assert(hList);
960 /* Test for standard usage */
962 /* This should list all the files in the test directory. */
963 strcpy(pathBuffer, wildcard);
964 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
965 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
966 if (res == -1) /* "*" wildcard doesn't work on win9x */
968 wildcard = "*.*";
969 strcpy(pathBuffer, wildcard);
970 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
972 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
974 /* There should be some content in the listbox */
975 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
976 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
977 itemCount_allFiles = itemCount;
978 ok(res + 1 == itemCount,
979 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
980 itemCount - 1, res);
982 /* This tests behavior when no files match the wildcard */
983 strcpy(pathBuffer, BAD_EXTENSION);
984 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
985 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
986 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
988 /* There should be NO content in the listbox */
989 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
990 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
993 /* This should list all the w*.c files in the test directory
994 * As of this writing, this includes win.c, winstation.c, wsprintf.c
996 strcpy(pathBuffer, "w*.c");
997 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
998 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
999 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
1001 /* Path specification does NOT converted to uppercase */
1002 ok (!strcmp(pathBuffer, "w*.c"),
1003 "expected no change to pathBuffer, got %s\n", pathBuffer);
1005 /* There should be some content in the listbox */
1006 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1007 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
1008 itemCount_justFiles = itemCount;
1009 ok(res + 1 == itemCount,
1010 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
1011 itemCount - 1, res);
1013 /* Every single item in the control should start with a w and end in .c */
1014 for (i = 0; i < itemCount; i++) {
1015 memset(pathBuffer, 0, MAX_PATH);
1016 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1017 p = pathBuffer + strlen(pathBuffer);
1018 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1019 (*(p-1) == 'c' || *(p-1) == 'C') &&
1020 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1023 /* Test DDL_DIRECTORY */
1024 strcpy(pathBuffer, wildcard);
1025 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1026 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
1027 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
1029 /* There should be some content in the listbox.
1030 * All files plus "[..]"
1032 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1033 itemCount_allDirs = itemCount - itemCount_allFiles;
1034 ok (itemCount > itemCount_allFiles,
1035 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
1036 itemCount, itemCount_allFiles);
1037 ok(res + 1 == itemCount,
1038 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
1039 itemCount - 1, res);
1041 /* This tests behavior when no files match the wildcard */
1042 strcpy(pathBuffer, BAD_EXTENSION);
1043 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1044 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
1045 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
1047 /* There should be NO content in the listbox */
1048 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1049 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
1052 /* Test DDL_DIRECTORY */
1053 strcpy(pathBuffer, "w*.c");
1054 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1055 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
1056 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
1058 /* There should be some content in the listbox. Since the parent directory does not
1059 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
1061 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1062 ok (itemCount == itemCount_justFiles,
1063 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
1064 itemCount, itemCount_justFiles);
1065 ok(res + 1 == itemCount,
1066 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
1067 itemCount - 1, res);
1069 /* Every single item in the control should start with a w and end in .c. */
1070 for (i = 0; i < itemCount; i++) {
1071 memset(pathBuffer, 0, MAX_PATH);
1072 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1073 p = pathBuffer + strlen(pathBuffer);
1075 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1076 (*(p-1) == 'c' || *(p-1) == 'C') &&
1077 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1081 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
1082 strcpy(pathBuffer, wildcard);
1083 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1084 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1085 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
1087 /* There should be some content in the listbox. In particular, there should
1088 * be at least one element before, since the string "[-c-]" should
1089 * have been added. Depending on the user setting, more drives might have
1090 * been added.
1092 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1093 ok (itemCount >= 1,
1094 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
1095 itemCount, 1);
1096 itemCount_justDrives = itemCount;
1097 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1099 /* Every single item in the control should fit the format [-c-] */
1100 for (i = 0; i < itemCount; i++) {
1101 memset(pathBuffer, 0, MAX_PATH);
1102 driveletter = '\0';
1103 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1104 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1105 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1106 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1107 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1108 /* Correct after invalid entry is found */
1109 trace("removing count of invalid entry %s\n", pathBuffer);
1110 itemCount_justDrives--;
1114 /* This tests behavior when no files match the wildcard */
1115 strcpy(pathBuffer, BAD_EXTENSION);
1116 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1117 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1118 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1119 BAD_EXTENSION, res, itemCount_justDrives -1);
1121 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1122 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
1123 itemCount, itemCount_justDrives);
1125 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
1126 itemCount_justFiles, itemCount_justDrives);
1128 /* Test DDL_DRIVES. */
1129 strcpy(pathBuffer, wildcard);
1130 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1131 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
1132 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
1134 /* There should be some content in the listbox. In particular, there should
1135 * be at least one element before, since the string "[-c-]" should
1136 * have been added. Depending on the user setting, more drives might have
1137 * been added.
1139 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1140 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
1141 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
1142 itemCount, itemCount_justDrives + itemCount_allFiles);
1143 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
1145 /* This tests behavior when no files match the wildcard */
1146 strcpy(pathBuffer, BAD_EXTENSION);
1147 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1148 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
1149 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
1150 BAD_EXTENSION, res, itemCount_justDrives -1);
1152 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1153 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1156 /* Test DDL_DRIVES. */
1157 strcpy(pathBuffer, "w*.c");
1158 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1159 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
1160 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
1162 /* There should be some content in the listbox. In particular, there should
1163 * be at least one element before, since the string "[-c-]" should
1164 * have been added. Depending on the user setting, more drives might have
1165 * been added.
1167 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1168 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
1169 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
1170 itemCount, itemCount_justDrives + itemCount_justFiles);
1171 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
1173 /* Every single item in the control should fit the format [-c-], or w*.c */
1174 for (i = 0; i < itemCount; i++) {
1175 memset(pathBuffer, 0, MAX_PATH);
1176 driveletter = '\0';
1177 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1178 p = pathBuffer + strlen(pathBuffer);
1179 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1180 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1181 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1182 } else {
1184 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1185 (*(p-1) == 'c' || *(p-1) == 'C') &&
1186 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1191 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1192 strcpy(pathBuffer, wildcard);
1193 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1194 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1195 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
1197 /* There should be some content in the listbox. In particular, there should
1198 * be exactly the number of plain files, plus the number of mapped drives.
1200 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1201 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
1202 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1203 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
1204 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1206 /* Every single item in the control should start with a w and end in .c,
1207 * except for the "[..]" string, which should appear exactly as it is,
1208 * and the mapped drives in the format "[-X-]".
1210 for (i = 0; i < itemCount; i++) {
1211 memset(pathBuffer, 0, MAX_PATH);
1212 driveletter = '\0';
1213 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1214 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1215 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1219 /* This tests behavior when no files match the wildcard */
1220 strcpy(pathBuffer, BAD_EXTENSION);
1221 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1222 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1223 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
1224 BAD_EXTENSION, res, itemCount_justDrives -1);
1226 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1227 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1231 /* Test DDL_DIRECTORY|DDL_DRIVES. */
1232 strcpy(pathBuffer, "w*.c");
1233 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1234 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1235 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
1237 /* There should be some content in the listbox. In particular, there should
1238 * be exactly the number of plain files, plus the number of mapped drives.
1240 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1241 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
1242 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1243 itemCount, itemCount_justFiles + itemCount_justDrives);
1244 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1246 /* Every single item in the control should start with a w and end in .c,
1247 * except the mapped drives in the format "[-X-]". The "[..]" directory
1248 * should not appear.
1250 for (i = 0; i < itemCount; i++) {
1251 memset(pathBuffer, 0, MAX_PATH);
1252 driveletter = '\0';
1253 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1254 p = pathBuffer + strlen(pathBuffer);
1255 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1256 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1257 } else {
1259 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1260 (*(p-1) == 'c' || *(p-1) == 'C') &&
1261 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1265 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1266 strcpy(pathBuffer, wildcard);
1267 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1268 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1269 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError());
1271 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1272 ok (itemCount == itemCount_allDirs,
1273 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1274 itemCount, itemCount_allDirs);
1275 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1277 if (itemCount)
1279 memset(pathBuffer, 0, MAX_PATH);
1280 SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1281 ok( !strcmp(pathBuffer, "[..]"), "First element is %s, not [..]\n", pathBuffer);
1284 /* This tests behavior when no files match the wildcard */
1285 strcpy(pathBuffer, BAD_EXTENSION);
1286 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1287 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1288 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1289 BAD_EXTENSION, res, -1);
1291 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1292 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1295 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1296 strcpy(pathBuffer, "w*.c");
1297 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1298 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1299 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
1301 /* There should be no elements, since "[..]" does not fit w*.c */
1302 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1303 ok (itemCount == 0,
1304 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1305 itemCount, 0);
1307 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1308 strcpy(pathBuffer, wildcard);
1309 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1310 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1311 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1313 /* There should be no plain files on the listbox */
1314 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1315 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1316 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1317 itemCount, itemCount_justDrives + itemCount_allDirs);
1318 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1320 for (i = 0; i < itemCount; i++) {
1321 memset(pathBuffer, 0, MAX_PATH);
1322 driveletter = '\0';
1323 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1324 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1325 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1326 } else {
1327 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1328 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1332 /* This tests behavior when no files match the wildcard */
1333 strcpy(pathBuffer, BAD_EXTENSION);
1334 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1335 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1336 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1337 BAD_EXTENSION, res, itemCount_justDrives -1);
1339 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1340 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1342 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1343 strcpy(pathBuffer, "w*.c");
1344 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1345 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1346 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1348 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
1349 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1350 ok (itemCount == itemCount_justDrives,
1351 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1352 itemCount, itemCount_justDrives);
1353 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1355 for (i = 0; i < itemCount; i++) {
1356 memset(pathBuffer, 0, MAX_PATH);
1357 driveletter = '\0';
1358 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1359 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1360 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1362 DestroyWindow(hList);
1364 DeleteFileA( "wtest1.tmp.c" );
1365 RemoveDirectoryA("lb_dir_test");
1367 SetCurrentDirectoryA(curdir);
1370 static HWND g_listBox;
1371 static HWND g_label;
1373 #define ID_TEST_LABEL 1001
1374 #define ID_TEST_LISTBOX 1002
1376 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCTA lpcs)
1378 g_label = CreateWindowA(
1379 "Static",
1380 "Contents of static control before DlgDirList.",
1381 WS_CHILD | WS_VISIBLE,
1382 10, 10, 512, 32,
1383 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1384 if (!g_label) return FALSE;
1385 g_listBox = CreateWindowA(
1386 "ListBox",
1387 "DlgDirList test",
1388 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1389 10, 60, 256, 256,
1390 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1391 if (!g_listBox) return FALSE;
1393 return TRUE;
1396 static LRESULT CALLBACK listbox_container_window_procA (
1397 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1399 LRESULT result = 0;
1401 switch (uiMsg) {
1402 case WM_DESTROY:
1403 PostQuitMessage(0);
1404 break;
1405 case WM_CREATE:
1406 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1407 ? 0 : (LRESULT)-1;
1408 break;
1409 default:
1410 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1411 break;
1413 return result;
1416 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1418 WNDCLASSA cls;
1420 cls.style = 0;
1421 cls.cbClsExtra = 0;
1422 cls.cbWndExtra = 0;
1423 cls.hInstance = hInst;
1424 cls.hIcon = NULL;
1425 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
1426 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1427 cls.lpszMenuName = NULL;
1428 cls.lpfnWndProc = listbox_container_window_procA;
1429 cls.lpszClassName = "ListboxContainerClass";
1430 if (!RegisterClassA (&cls)) return FALSE;
1432 return TRUE;
1435 static void test_listbox_dlgdir(void)
1437 HINSTANCE hInst;
1438 HWND hWnd;
1439 int res, itemCount;
1440 int itemCount_allDirs;
1441 int itemCount_justFiles;
1442 int itemCount_justDrives;
1443 int i;
1444 char pathBuffer[MAX_PATH];
1445 char itemBuffer[MAX_PATH];
1446 char tempBuffer[MAX_PATH];
1447 char * p;
1448 char driveletter;
1449 HANDLE file;
1451 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1452 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1453 CloseHandle( file );
1455 /* NOTE: for this test to succeed, there must be no subdirectories
1456 under the current directory. In addition, there must be at least
1457 one file that fits the wildcard w*.c . Normally, the test
1458 directory itself satisfies both conditions.
1461 hInst = GetModuleHandleA(0);
1462 if (!RegisterListboxWindowClass(hInst)) assert(0);
1463 hWnd = CreateWindowA("ListboxContainerClass", "ListboxContainerClass",
1464 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1465 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1466 NULL, NULL, hInst, 0);
1467 assert(hWnd);
1469 /* Test for standard usage */
1471 /* The following should be overwritten by the directory path */
1472 SendMessageA(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1474 /* This should list all the w*.c files in the test directory
1475 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1477 strcpy(pathBuffer, "w*.c");
1478 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1479 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1481 /* Path specification gets converted to uppercase */
1482 ok (!strcmp(pathBuffer, "W*.C"),
1483 "expected conversion to uppercase, got %s\n", pathBuffer);
1485 /* Loaded path should have overwritten the label text */
1486 SendMessageA(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer);
1487 trace("Static control after DlgDirList: %s\n", pathBuffer);
1488 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1490 /* There should be some content in the listbox */
1491 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1492 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1493 itemCount_justFiles = itemCount;
1495 /* Every single item in the control should start with a w and end in .c */
1496 for (i = 0; i < itemCount; i++) {
1497 memset(pathBuffer, 0, MAX_PATH);
1498 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1499 p = pathBuffer + strlen(pathBuffer);
1500 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1501 (*(p-1) == 'c' || *(p-1) == 'C') &&
1502 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1505 /* Test behavior when no files match the wildcard */
1506 strcpy(pathBuffer, BAD_EXTENSION);
1507 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1508 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1510 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1511 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1513 /* Test DDL_DIRECTORY */
1514 strcpy(pathBuffer, "w*.c");
1515 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1516 DDL_DIRECTORY);
1517 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1519 /* There should be some content in the listbox. In particular, there should
1520 * be exactly more elements than before, since the directories should
1521 * have been added.
1523 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1524 itemCount_allDirs = itemCount - itemCount_justFiles;
1525 ok (itemCount >= itemCount_justFiles,
1526 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1527 itemCount, itemCount_justFiles);
1529 /* Every single item in the control should start with a w and end in .c,
1530 * except for the "[..]" string, which should appear exactly as it is.
1532 for (i = 0; i < itemCount; i++) {
1533 memset(pathBuffer, 0, MAX_PATH);
1534 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1535 p = pathBuffer + strlen(pathBuffer);
1536 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1537 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1538 (*(p-1) == 'c' || *(p-1) == 'C') &&
1539 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1542 /* Test behavior when no files match the wildcard */
1543 strcpy(pathBuffer, BAD_EXTENSION);
1544 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1545 DDL_DIRECTORY);
1546 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1548 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1549 ok (itemCount == itemCount_allDirs,
1550 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1551 itemCount_allDirs, itemCount);
1552 for (i = 0; i < itemCount; i++) {
1553 memset(pathBuffer, 0, MAX_PATH);
1554 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1555 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1556 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1560 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1561 strcpy(pathBuffer, "w*.c");
1562 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1563 DDL_DRIVES);
1564 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1566 /* There should be some content in the listbox. In particular, there should
1567 * be at least one element before, since the string "[-c-]" should
1568 * have been added. Depending on the user setting, more drives might have
1569 * been added.
1571 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1572 ok (itemCount >= 1,
1573 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1574 itemCount, 1);
1575 itemCount_justDrives = itemCount;
1577 /* Every single item in the control should fit the format [-c-] */
1578 for (i = 0; i < itemCount; i++) {
1579 memset(pathBuffer, 0, MAX_PATH);
1580 driveletter = '\0';
1581 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1582 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1583 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1584 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1585 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1586 /* Correct after invalid entry is found */
1587 trace("removing count of invalid entry %s\n", pathBuffer);
1588 itemCount_justDrives--;
1592 /* Test behavior when no files match the wildcard */
1593 strcpy(pathBuffer, BAD_EXTENSION);
1594 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1595 DDL_DRIVES);
1596 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1598 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1599 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1602 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1603 strcpy(pathBuffer, "w*.c");
1604 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1605 DDL_DIRECTORY|DDL_DRIVES);
1606 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1608 /* There should be some content in the listbox. In particular, there should
1609 * be exactly the number of plain files, plus the number of mapped drives,
1610 * plus one "[..]"
1612 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1613 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1614 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1615 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1617 /* Every single item in the control should start with a w and end in .c,
1618 * except for the "[..]" string, which should appear exactly as it is,
1619 * and the mapped drives in the format "[-X-]".
1621 for (i = 0; i < itemCount; i++) {
1622 memset(pathBuffer, 0, MAX_PATH);
1623 driveletter = '\0';
1624 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1625 p = pathBuffer + strlen(pathBuffer);
1626 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1627 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1628 } else {
1629 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1630 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1631 (*(p-1) == 'c' || *(p-1) == 'C') &&
1632 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1636 /* Test behavior when no files match the wildcard */
1637 strcpy(pathBuffer, BAD_EXTENSION);
1638 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1639 DDL_DIRECTORY|DDL_DRIVES);
1640 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1642 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1643 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1644 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1645 itemCount_justDrives + itemCount_allDirs, itemCount);
1649 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1650 strcpy(pathBuffer, "w*.c");
1651 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1652 DDL_DIRECTORY|DDL_EXCLUSIVE);
1653 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1655 /* There should be exactly one element: "[..]" */
1656 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1657 ok (itemCount == itemCount_allDirs,
1658 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1659 itemCount, itemCount_allDirs);
1661 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1663 memset(pathBuffer, 0, MAX_PATH);
1664 SendMessageA(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1665 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1668 /* Test behavior when no files match the wildcard */
1669 strcpy(pathBuffer, BAD_EXTENSION);
1670 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1671 DDL_DIRECTORY|DDL_EXCLUSIVE);
1672 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1674 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1675 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1678 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1679 strcpy(pathBuffer, "w*.c");
1680 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1681 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1682 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1684 /* There should be no plain files on the listbox */
1685 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1686 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1687 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1688 itemCount, itemCount_justDrives + itemCount_allDirs);
1690 for (i = 0; i < itemCount; i++) {
1691 memset(pathBuffer, 0, MAX_PATH);
1692 driveletter = '\0';
1693 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1694 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1695 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1696 } else {
1697 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1698 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1702 /* Test behavior when no files match the wildcard */
1703 strcpy(pathBuffer, BAD_EXTENSION);
1704 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1705 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1706 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1708 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1709 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1710 "DlgDirList() incorrectly filled the listbox!\n");
1712 /* Now test DlgDirSelectEx() in normal operation */
1713 /* Fill with everything - drives, directory and all plain files. */
1714 strcpy(pathBuffer, "*");
1715 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1716 DDL_DIRECTORY|DDL_DRIVES);
1717 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1719 SendMessageA(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1720 memset(pathBuffer, 0, MAX_PATH);
1721 SetLastError(0xdeadbeef);
1722 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1723 ok (GetLastError() == 0xdeadbeef,
1724 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1725 GetLastError());
1726 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1727 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1729 ok (!*pathBuffer, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1731 /* Test proper drive/dir/file recognition */
1732 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1733 for (i = 0; i < itemCount; i++) {
1734 memset(itemBuffer, 0, MAX_PATH);
1735 memset(pathBuffer, 0, MAX_PATH);
1736 memset(tempBuffer, 0, MAX_PATH);
1737 driveletter = '\0';
1738 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1739 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1740 ok (res == i, "SendMessageA(LB_SETCURSEL, %d) failed\n", i);
1741 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1742 /* Current item is a drive letter */
1743 SetLastError(0xdeadbeef);
1744 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1745 ok (GetLastError() == 0xdeadbeef,
1746 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1747 i, GetLastError());
1748 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1750 /* For drive letters, DlgDirSelectEx tacks on a colon */
1751 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1752 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1753 } else if (itemBuffer[0] == '[') {
1754 /* Current item is the parent directory */
1755 SetLastError(0xdeadbeef);
1756 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1757 ok (GetLastError() == 0xdeadbeef,
1758 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1759 i, GetLastError());
1760 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1762 /* For directories, DlgDirSelectEx tacks on a backslash */
1763 p = pathBuffer + strlen(pathBuffer);
1764 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1766 tempBuffer[0] = '[';
1767 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1768 strcat(tempBuffer, "]");
1769 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1770 } else {
1771 /* Current item is a plain file */
1772 SetLastError(0xdeadbeef);
1773 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1774 ok (GetLastError() == 0xdeadbeef,
1775 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1776 i, GetLastError());
1777 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1779 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1780 * for example, "Makefile", which gets reported as "Makefile."
1782 strcpy(tempBuffer, itemBuffer);
1783 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1784 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1788 DeleteFileA( "wtest1.tmp.c" );
1790 /* Now test DlgDirSelectEx() in abnormal operation */
1791 /* Fill list with bogus entries, that look somewhat valid */
1792 SendMessageA(g_listBox, LB_RESETCONTENT, 0, 0);
1793 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1794 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1795 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1796 for (i = 0; i < itemCount; i++) {
1797 memset(itemBuffer, 0, MAX_PATH);
1798 memset(pathBuffer, 0, MAX_PATH);
1799 memset(tempBuffer, 0, MAX_PATH);
1800 driveletter = '\0';
1801 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1802 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1803 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1804 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1805 /* Current item is a drive letter */
1806 SetLastError(0xdeadbeef);
1807 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1808 ok (GetLastError() == 0xdeadbeef,
1809 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1810 i, GetLastError());
1811 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1813 /* For drive letters, DlgDirSelectEx tacks on a colon */
1814 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1815 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1816 } else if (itemBuffer[0] == '[') {
1817 /* Current item is the parent directory */
1818 SetLastError(0xdeadbeef);
1819 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1820 ok (GetLastError() == 0xdeadbeef,
1821 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1822 i, GetLastError());
1823 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1825 /* For directories, DlgDirSelectEx tacks on a backslash */
1826 p = pathBuffer + strlen(pathBuffer);
1827 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1829 tempBuffer[0] = '[';
1830 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1831 strcat(tempBuffer, "]");
1832 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1833 } else {
1834 /* Current item is a plain file */
1835 SetLastError(0xdeadbeef);
1836 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1837 ok (GetLastError() == 0xdeadbeef,
1838 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1839 i, GetLastError());
1840 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1842 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1843 * This affects for example, "Makefile", which gets reported as "Makefile."
1845 strcpy(tempBuffer, itemBuffer);
1846 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1847 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1851 /* Test behavior when loading folders from root with and without wildcard */
1852 strcpy(pathBuffer, "C:\\");
1853 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1854 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\ folders\n");
1855 ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1856 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1858 strcpy(pathBuffer, "C:\\*");
1859 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1860 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\* folders\n");
1861 ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1862 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1864 /* Try loading files from an invalid folder */
1865 SetLastError(0xdeadbeef);
1866 strcpy(pathBuffer, "C:\\INVALID$$DIR");
1867 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1868 ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
1869 ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
1870 "GetLastError should return 0x589, got 0x%X\n",GetLastError());
1872 DestroyWindow(hWnd);
1875 static void test_set_count( void )
1877 static const DWORD styles[] =
1879 LBS_OWNERDRAWFIXED,
1880 LBS_HASSTRINGS,
1882 HWND parent, listbox;
1883 unsigned int i;
1884 LONG ret;
1885 RECT r;
1887 parent = create_parent();
1888 listbox = create_listbox( LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VISIBLE, parent );
1890 UpdateWindow( listbox );
1891 GetUpdateRect( listbox, &r, TRUE );
1892 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1894 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
1895 ok( ret == 0, "got %d\n", ret );
1896 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
1897 ok( ret == 100, "got %d\n", ret );
1899 GetUpdateRect( listbox, &r, TRUE );
1900 ok( !IsRectEmpty( &r ), "got empty rect\n");
1902 ValidateRect( listbox, NULL );
1903 GetUpdateRect( listbox, &r, TRUE );
1904 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1906 ret = SendMessageA( listbox, LB_SETCOUNT, 99, 0 );
1907 ok( ret == 0, "got %d\n", ret );
1909 GetUpdateRect( listbox, &r, TRUE );
1910 ok( !IsRectEmpty( &r ), "got empty rect\n");
1912 ret = SendMessageA( listbox, LB_SETCOUNT, -5, 0 );
1913 ok( ret == 0, "got %d\n", ret );
1914 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
1915 ok( ret == -5, "got %d\n", ret );
1917 DestroyWindow( listbox );
1919 for (i = 0; i < ARRAY_SIZE(styles); ++i)
1921 listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent );
1923 SetLastError( 0xdeadbeef );
1924 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
1925 ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret );
1926 ok( GetLastError() == ERROR_SETCOUNT_ON_BAD_LB, "Unexpected error %d.\n", GetLastError() );
1928 DestroyWindow( listbox );
1931 DestroyWindow( parent );
1934 static DWORD (WINAPI *pGetListBoxInfo)(HWND);
1935 static int lb_getlistboxinfo;
1937 static LRESULT WINAPI listbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1939 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
1941 if (message == LB_GETLISTBOXINFO)
1942 lb_getlistboxinfo++;
1944 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
1947 static void test_GetListBoxInfo(void)
1949 HWND listbox, parent;
1950 WNDPROC oldproc;
1951 DWORD ret;
1953 pGetListBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetListBoxInfo");
1955 if (!pGetListBoxInfo)
1957 win_skip("GetListBoxInfo() not available\n");
1958 return;
1961 parent = create_parent();
1962 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1964 oldproc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (LONG_PTR)listbox_subclass_proc);
1965 SetWindowLongPtrA(listbox, GWLP_USERDATA, (LONG_PTR)oldproc);
1967 lb_getlistboxinfo = 0;
1968 ret = pGetListBoxInfo(listbox);
1969 ok(ret > 0, "got %d\n", ret);
1970 todo_wine
1971 ok(lb_getlistboxinfo == 0, "got %d\n", lb_getlistboxinfo);
1973 DestroyWindow(listbox);
1974 DestroyWindow(parent);
1977 static void test_init_storage( void )
1979 static const DWORD styles[] =
1981 LBS_HASSTRINGS,
1982 LBS_NODATA | LBS_OWNERDRAWFIXED,
1984 HWND parent, listbox;
1985 LONG ret, items_size;
1986 int i, j;
1988 parent = create_parent();
1989 for (i = 0; i < ARRAY_SIZE(styles); i++)
1991 listbox = CreateWindowA("listbox", "TestList", styles[i] | WS_CHILD,
1992 0, 0, 100, 100, parent, (HMENU)1, NULL, 0);
1994 items_size = SendMessageA(listbox, LB_INITSTORAGE, 100, 0);
1995 ok(items_size >= 100, "expected at least 100, got %d\n", items_size);
1997 ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
1998 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2000 /* it doesn't grow since the space was already reserved */
2001 ret = SendMessageA(listbox, LB_INITSTORAGE, items_size, 0);
2002 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2004 /* it doesn't shrink the reserved space */
2005 ret = SendMessageA(listbox, LB_INITSTORAGE, 42, 0);
2006 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2008 /* now populate almost all of it so it's not reserved anymore */
2009 if (styles[i] & LBS_NODATA)
2011 ret = SendMessageA(listbox, LB_SETCOUNT, items_size - 1, 0);
2012 ok(ret == 0, "unexpected return value %d\n", ret);
2014 else
2016 for (j = 0; j < items_size - 1; j++)
2018 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
2019 ok(ret == j, "expected %d, got %d\n", j, ret);
2023 /* we still have one more reserved slot, so it doesn't grow yet */
2024 ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
2025 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2027 /* fill the slot and check again, it should grow this time */
2028 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
2029 ok(ret == items_size - 1, "expected %d, got %d\n", items_size - 1, ret);
2030 ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
2031 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2032 ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
2033 ok(ret > items_size, "expected it to grow past %d, got %d\n", items_size, ret);
2035 DestroyWindow(listbox);
2037 DestroyWindow(parent);
2040 static void test_missing_lbuttonup( void )
2042 HWND listbox, parent, capture;
2044 parent = create_parent();
2045 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
2047 /* Send button down without a corresponding button up */
2048 SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(10,10));
2049 capture = GetCapture();
2050 ok(capture == listbox, "got %p expected %p\n", capture, listbox);
2052 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */
2053 got_selchange = 0;
2054 SetFocus(NULL);
2055 capture = GetCapture();
2056 ok(capture == NULL, "got %p\n", capture);
2057 ok(got_selchange, "got %d\n", got_selchange);
2059 DestroyWindow(listbox);
2060 DestroyWindow(parent);
2063 static void test_extents(void)
2065 HWND listbox, parent;
2066 DWORD res;
2067 SCROLLINFO sinfo;
2068 BOOL br;
2070 parent = create_parent();
2072 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
2074 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2075 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
2077 sinfo.cbSize = sizeof(sinfo);
2078 sinfo.fMask = SIF_RANGE;
2079 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2080 ok(br == TRUE, "GetScrollInfo failed\n");
2081 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2082 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
2083 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2084 "List box should not have a horizontal scroll bar\n");
2086 /* horizontal extent < width */
2087 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
2089 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2090 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
2092 sinfo.cbSize = sizeof(sinfo);
2093 sinfo.fMask = SIF_RANGE;
2094 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2095 ok(br == TRUE, "GetScrollInfo failed\n");
2096 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2097 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
2098 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2099 "List box should not have a horizontal scroll bar\n");
2101 /* horizontal extent > width */
2102 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
2104 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2105 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
2107 sinfo.cbSize = sizeof(sinfo);
2108 sinfo.fMask = SIF_RANGE;
2109 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2110 ok(br == TRUE, "GetScrollInfo failed\n");
2111 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2112 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
2113 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2114 "List box should not have a horizontal scroll bar\n");
2116 DestroyWindow(listbox);
2119 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL, parent);
2121 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2122 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
2124 sinfo.cbSize = sizeof(sinfo);
2125 sinfo.fMask = SIF_RANGE;
2126 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2127 ok(br == TRUE, "GetScrollInfo failed\n");
2128 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2129 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
2130 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2131 "List box should not have a horizontal scroll bar\n");
2133 /* horizontal extent < width */
2134 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
2136 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2137 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
2139 sinfo.cbSize = sizeof(sinfo);
2140 sinfo.fMask = SIF_RANGE;
2141 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2142 ok(br == TRUE, "GetScrollInfo failed\n");
2143 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2144 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
2145 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2146 "List box should not have a horizontal scroll bar\n");
2148 /* horizontal extent > width */
2149 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
2151 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2152 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
2154 sinfo.cbSize = sizeof(sinfo);
2155 sinfo.fMask = SIF_RANGE;
2156 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2157 ok(br == TRUE, "GetScrollInfo failed\n");
2158 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2159 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
2160 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2161 "List box should have a horizontal scroll bar\n");
2163 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
2165 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2166 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
2168 sinfo.cbSize = sizeof(sinfo);
2169 sinfo.fMask = SIF_RANGE;
2170 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2171 ok(br == TRUE, "GetScrollInfo failed\n");
2172 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2173 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
2174 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2175 "List box should not have a horizontal scroll bar\n");
2177 DestroyWindow(listbox);
2180 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL | LBS_DISABLENOSCROLL, parent);
2182 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2183 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
2185 sinfo.cbSize = sizeof(sinfo);
2186 sinfo.fMask = SIF_RANGE;
2187 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2188 ok(br == TRUE, "GetScrollInfo failed\n");
2189 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2190 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
2191 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2192 "List box should have a horizontal scroll bar\n");
2194 /* horizontal extent < width */
2195 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
2197 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2198 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
2200 sinfo.cbSize = sizeof(sinfo);
2201 sinfo.fMask = SIF_RANGE;
2202 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2203 ok(br == TRUE, "GetScrollInfo failed\n");
2204 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2205 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
2206 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2207 "List box should have a horizontal scroll bar\n");
2209 /* horizontal extent > width */
2210 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
2212 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2213 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
2215 sinfo.cbSize = sizeof(sinfo);
2216 sinfo.fMask = SIF_RANGE;
2217 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2218 ok(br == TRUE, "GetScrollInfo failed\n");
2219 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2220 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
2221 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2222 "List box should have a horizontal scroll bar\n");
2224 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
2226 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2227 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
2229 sinfo.cbSize = sizeof(sinfo);
2230 sinfo.fMask = SIF_RANGE;
2231 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2232 ok(br == TRUE, "GetScrollInfo failed\n");
2233 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2234 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
2235 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2236 "List box should have a horizontal scroll bar\n");
2238 DestroyWindow(listbox);
2240 DestroyWindow(parent);
2243 static void test_WM_MEASUREITEM(void)
2245 HWND parent, listbox;
2246 LRESULT data;
2248 parent = create_parent();
2249 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE, parent);
2251 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
2252 ok(data == (LRESULT)strings[0], "data = %08lx, expected %p\n", data, strings[0]);
2253 DestroyWindow(parent);
2255 parent = create_parent();
2256 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS, parent);
2258 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
2259 ok(!data, "data = %08lx\n", data);
2260 DestroyWindow(parent);
2263 static void test_LBS_NODATA(void)
2265 static const DWORD invalid_styles[] =
2268 LBS_OWNERDRAWVARIABLE,
2269 LBS_SORT,
2270 LBS_HASSTRINGS,
2271 LBS_OWNERDRAWFIXED | LBS_SORT,
2272 LBS_OWNERDRAWFIXED | LBS_HASSTRINGS,
2274 static const UINT invalid_idx[] = { -2, 2 };
2275 static const UINT valid_idx[] = { 0, 1 };
2276 static const ULONG_PTR zero_data;
2277 HWND listbox, parent;
2278 unsigned int i;
2279 ULONG_PTR data;
2280 INT ret;
2282 listbox = CreateWindowA("listbox", "TestList", LBS_NODATA | LBS_OWNERDRAWFIXED | WS_VISIBLE,
2283 0, 0, 100, 100, NULL, NULL, NULL, 0);
2284 ok(listbox != NULL, "Failed to create ListBox window.\n");
2286 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
2287 ok(ret == 0, "Unexpected return value %d.\n", ret);
2288 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
2289 ok(ret == 1, "Unexpected return value %d.\n", ret);
2290 ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
2291 ok(ret == 2, "Unexpected return value %d.\n", ret);
2293 /* Invalid indices. */
2294 for (i = 0; i < ARRAY_SIZE(invalid_idx); ++i)
2296 ret = SendMessageA(listbox, LB_SETITEMDATA, invalid_idx[i], 42);
2297 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2298 ret = SendMessageA(listbox, LB_GETTEXTLEN, invalid_idx[i], 0);
2299 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2300 if (ret == LB_ERR)
2302 ret = SendMessageA(listbox, LB_GETTEXT, invalid_idx[i], (LPARAM)&data);
2303 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2305 ret = SendMessageA(listbox, LB_GETITEMDATA, invalid_idx[i], 0);
2306 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2309 /* Valid indices. */
2310 for (i = 0; i < ARRAY_SIZE(valid_idx); ++i)
2312 ret = SendMessageA(listbox, LB_SETITEMDATA, valid_idx[i], 42);
2313 ok(ret == TRUE, "Unexpected return value %d.\n", ret);
2314 ret = SendMessageA(listbox, LB_GETTEXTLEN, valid_idx[i], 0);
2315 ok(ret == sizeof(data), "Unexpected return value %d.\n", ret);
2317 memset(&data, 0xee, sizeof(data));
2318 ret = SendMessageA(listbox, LB_GETTEXT, valid_idx[i], (LPARAM)&data);
2319 ok(ret == sizeof(data), "Unexpected return value %d.\n", ret);
2320 ok(!memcmp(&data, &zero_data, sizeof(data)), "Unexpected item data.\n");
2322 ret = SendMessageA(listbox, LB_GETITEMDATA, valid_idx[i], 0);
2323 ok(ret == 0, "Unexpected return value %d.\n", ret);
2326 /* More messages that don't work with LBS_NODATA. */
2327 SetLastError(0xdeadbeef);
2328 ret = SendMessageA(listbox, LB_FINDSTRING, 1, 0);
2329 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2330 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
2331 SetLastError(0xdeadbeef);
2332 ret = SendMessageA(listbox, LB_FINDSTRING, 1, 42);
2333 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2334 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
2335 SetLastError(0xdeadbeef);
2336 ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 0);
2337 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2338 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
2339 SetLastError(0xdeadbeef);
2340 ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 42);
2341 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2342 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
2343 SetLastError(0xdeadbeef);
2344 ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 0);
2345 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2346 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
2347 SetLastError(0xdeadbeef);
2348 ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 42);
2349 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2350 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError());
2352 DestroyWindow(listbox);
2354 /* Invalid window style combinations. */
2355 parent = create_parent();
2356 ok(parent != NULL, "Failed to create parent window.\n");
2358 for (i = 0; i < ARRAY_SIZE(invalid_styles); ++i)
2360 DWORD style;
2362 listbox = CreateWindowA("listbox", "TestList", LBS_NODATA | WS_CHILD | invalid_styles[i],
2363 0, 0, 100, 100, parent, (HMENU)1, NULL, 0);
2364 ok(listbox != NULL, "Failed to create a listbox.\n");
2366 style = GetWindowLongA(listbox, GWL_STYLE);
2367 ok((style & invalid_styles[i]) == invalid_styles[i], "%u: unexpected window styles %#x.\n", i, style);
2368 ret = SendMessageA(listbox, LB_SETCOUNT, 100, 0);
2369 ok(ret == LB_ERR, "%u: unexpected return value %d.\n", i, ret);
2370 DestroyWindow(listbox);
2373 DestroyWindow(parent);
2376 START_TEST(listbox)
2378 const struct listbox_test SS =
2379 /* {add_style} */
2380 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2381 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2382 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2383 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2384 /* {selected, anchor, caret, selcount}{TODO fields} */
2385 const struct listbox_test SS_NS =
2386 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2387 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2388 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2389 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2390 const struct listbox_test MS =
2391 {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
2392 { 1, 1, 1, 1}, {0,0,0,0},
2393 { 2, 1, 2, 1}, {0,0,0,0},
2394 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2395 const struct listbox_test MS_NS =
2396 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2397 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2398 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2399 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2400 const struct listbox_test ES =
2401 {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
2402 { 1, 1, 1, 1}, {0,0,0,0},
2403 { 2, 2, 2, 1}, {0,0,0,0},
2404 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2405 const struct listbox_test ES_NS =
2406 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2407 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2408 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2409 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2410 const struct listbox_test EMS =
2411 {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
2412 { 1, 1, 1, 1}, {0,0,0,0},
2413 { 2, 2, 2, 1}, {0,0,0,0},
2414 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2415 const struct listbox_test EMS_NS =
2416 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2417 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2418 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2419 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2421 trace (" Testing single selection...\n");
2422 check (0, SS);
2423 trace (" ... with NOSEL\n");
2424 check (LBS_NOSEL, SS_NS);
2425 trace (" ... LBS_NODATA variant ...\n");
2426 check (LBS_NODATA | LBS_OWNERDRAWFIXED, SS);
2427 trace (" ... with NOSEL\n");
2428 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOSEL, SS_NS);
2430 trace (" Testing multiple selection...\n");
2431 check (LBS_MULTIPLESEL, MS);
2432 trace (" ... with NOSEL\n");
2433 check (LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
2434 trace (" ... LBS_NODATA variant ...\n");
2435 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL, MS);
2436 trace (" ... with NOSEL\n");
2437 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
2439 trace (" Testing extended selection...\n");
2440 check (LBS_EXTENDEDSEL, ES);
2441 trace (" ... with NOSEL\n");
2442 check (LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
2443 trace (" ... LBS_NODATA variant ...\n");
2444 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL, ES);
2445 trace (" ... with NOSEL\n");
2446 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
2448 trace (" Testing extended and multiple selection...\n");
2449 check (LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
2450 trace (" ... with NOSEL\n");
2451 check (LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
2452 trace (" ... LBS_NODATA variant ...\n");
2453 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
2454 trace (" ... with NOSEL\n");
2455 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
2457 check_item_height();
2458 test_ownerdraw();
2459 test_LB_SELITEMRANGE();
2460 test_LB_SETCURSEL();
2461 test_listbox_height();
2462 test_changing_selection_styles();
2463 test_itemfrompoint();
2464 test_listbox_item_data();
2465 test_listbox_LB_DIR();
2466 test_listbox_dlgdir();
2467 test_set_count();
2468 test_init_storage();
2469 test_GetListBoxInfo();
2470 test_missing_lbuttonup();
2471 test_extents();
2472 test_WM_MEASUREITEM();
2473 test_LB_SETSEL();
2474 test_LBS_NODATA();