wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / comctl32 / tests / listbox.c
blob4d44137e4d06dfddc02ab5d867dacac7b3cbe9c7
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 <stdarg.h>
21 #include <stdio.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winnls.h"
28 #include "commctrl.h"
30 #include "wine/heap.h"
31 #include "wine/test.h"
32 #include "v6util.h"
33 #include "msg.h"
35 enum seq_index
37 LB_SEQ_INDEX,
38 PARENT_SEQ_INDEX,
39 NUM_MSG_SEQUENCES
42 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
44 /* encoded MEASUREITEMSTRUCT into a WPARAM */
45 typedef struct
47 union
49 struct
51 UINT CtlType : 4;
52 UINT CtlID : 4;
53 UINT itemID : 4;
54 UINT wParam : 20;
55 } item;
56 WPARAM wp;
57 } u;
58 } MEASURE_ITEM_STRUCT;
60 static unsigned hash_Ly_W(const WCHAR *str)
62 unsigned hash = 0;
64 for (; *str; str++)
65 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
67 return hash;
70 static unsigned hash_Ly(const char *str)
72 unsigned hash = 0;
74 for (; *str; str++)
75 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
77 return hash;
80 static const char * const strings[4] = {
81 "First added",
82 "Second added",
83 "Third added",
84 "Fourth added which is very long because at some time we only had a 256 byte character buffer and "
85 "that was overflowing in one of those applications that had a common dialog file open box and tried "
86 "to add a 300 characters long custom filter string which of course the code did not like and crashed. "
87 "Just make sure this string is longer than 256 characters."
90 static const char BAD_EXTENSION[] = "*.badtxt";
92 #define ID_LISTBOX 1
94 static LRESULT WINAPI listbox_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
96 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
97 static LONG defwndproc_counter = 0;
98 struct message msg = { 0 };
99 LRESULT ret;
101 switch (message)
103 case WM_SIZE:
104 case WM_GETTEXT:
105 case WM_PAINT:
106 case WM_ERASEBKGND:
107 case WM_WINDOWPOSCHANGING:
108 case WM_WINDOWPOSCHANGED:
109 case WM_NCCALCSIZE:
110 case WM_NCPAINT:
111 case WM_NCHITTEST:
112 case WM_DEVICECHANGE:
113 break;
115 default:
116 msg.message = message;
117 msg.flags = sent|wparam|lparam;
118 if (defwndproc_counter) msg.flags |= defwinproc;
119 msg.wParam = wParam;
120 msg.lParam = lParam;
121 add_message(sequences, LB_SEQ_INDEX, &msg);
124 defwndproc_counter++;
125 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
126 defwndproc_counter--;
128 return ret;
131 static HWND create_listbox(DWORD add_style, HWND parent)
133 INT_PTR ctl_id = 0;
134 WNDPROC oldproc;
135 HWND handle;
137 if (parent)
138 ctl_id = ID_LISTBOX;
140 handle = CreateWindowA(WC_LISTBOXA, "TestList", (LBS_STANDARD & ~LBS_SORT) | add_style, 0, 0, 100, 100,
141 parent, (HMENU)ctl_id, NULL, 0);
142 ok(handle != NULL, "Failed to create listbox window.\n");
144 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[0]);
145 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[1]);
146 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[2]);
147 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[3]);
149 oldproc = (WNDPROC)SetWindowLongPtrA(handle, GWLP_WNDPROC, (LONG_PTR)listbox_wnd_proc);
150 SetWindowLongPtrA(handle, GWLP_USERDATA, (LONG_PTR)oldproc);
152 return handle;
155 struct listbox_prop
157 DWORD add_style;
160 struct listbox_stat
162 int selected, anchor, caret, selcount;
165 struct listbox_test
167 struct listbox_stat init, init_todo;
168 struct listbox_stat click, click_todo;
169 struct listbox_stat step, step_todo;
170 struct listbox_stat sel, sel_todo;
173 static void listbox_query(HWND handle, struct listbox_stat *results)
175 results->selected = SendMessageA(handle, LB_GETCURSEL, 0, 0);
176 results->anchor = SendMessageA(handle, LB_GETANCHORINDEX, 0, 0);
177 results->caret = SendMessageA(handle, LB_GETCARETINDEX, 0, 0);
178 results->selcount = SendMessageA(handle, LB_GETSELCOUNT, 0, 0);
181 static void buttonpress(HWND handle, WORD x, WORD y)
183 LPARAM lp = x + (y << 16);
185 SendMessageA(handle, WM_LBUTTONDOWN, MK_LBUTTON, lp);
186 SendMessageA(handle, WM_LBUTTONUP, 0, lp);
189 static void keypress(HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
191 LPARAM lp = 1 + (scancode << 16) + (extended ? KEYEVENTF_EXTENDEDKEY : 0);
193 SendMessageA(handle, WM_KEYDOWN, keycode, lp);
194 SendMessageA(handle, WM_KEYUP , keycode, lp | 0xc000000);
197 #define listbox_field_ok(t, s, f, got) \
198 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
199 ": expected %d, got %d\n", style, t.s.f, got.f)
201 #define listbox_todo_field_ok(t, s, f, got) \
202 todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
204 #define listbox_ok(t, s, got) \
205 listbox_todo_field_ok(t, s, selected, got); \
206 listbox_todo_field_ok(t, s, anchor, got); \
207 listbox_todo_field_ok(t, s, caret, got); \
208 listbox_todo_field_ok(t, s, selcount, got)
210 static void run_test(DWORD style, const struct listbox_test test)
212 static const struct message delete_seq[] =
214 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 },
215 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 },
216 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 },
217 { LB_DELETESTRING, sent|wparam|lparam, 0, 0 },
218 { LB_RESETCONTENT, sent|wparam|lparam|defwinproc, 0, 0 },
219 { 0 }
221 struct listbox_stat answer;
222 int i, res, count;
223 RECT second_item;
224 HWND hLB;
226 hLB = create_listbox (style, 0);
228 listbox_query (hLB, &answer);
229 listbox_ok (test, init, answer);
231 SendMessageA(hLB, LB_GETITEMRECT, 1, (LPARAM) &second_item);
232 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
234 listbox_query(hLB, &answer);
235 listbox_ok(test, click, answer);
237 keypress(hLB, VK_DOWN, 0x50, TRUE);
239 listbox_query(hLB, &answer);
240 listbox_ok(test, step, answer);
242 DestroyWindow(hLB);
244 hLB = create_listbox(style, 0);
246 SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
247 listbox_query(hLB, &answer);
248 listbox_ok(test, sel, answer);
250 for (i = 0; i < 4 && !(style & LBS_NODATA); i++)
252 DWORD size = SendMessageA(hLB, LB_GETTEXTLEN, i, 0);
253 int resA, resW;
254 WCHAR *txtw;
255 CHAR *txt;
257 txt = heap_alloc_zero(size + 1);
258 resA = SendMessageA(hLB, LB_GETTEXT, i, (LPARAM)txt);
259 ok(!strcmp(txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
261 txtw = heap_alloc_zero((size + 1) * sizeof(*txtw));
262 resW = SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
263 ok(resA == resW, "Unexpected text length.\n");
264 WideCharToMultiByte(CP_ACP, 0, txtw, -1, txt, size, NULL, NULL);
265 ok(!strcmp (txt, strings[i]), "Unexpected string for item %d, %s vs %s.\n", i, txt, strings[i]);
267 heap_free(txtw);
268 heap_free(txt);
271 /* Confirm the count of items, and that an invalid delete does not remove anything */
272 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
273 ok(res == 4, "Expected 4 items, got %d\n", res);
274 res = SendMessageA(hLB, LB_DELETESTRING, -1, 0);
275 ok(res == LB_ERR, "Expected LB_ERR items, got %d\n", res);
276 res = SendMessageA(hLB, LB_DELETESTRING, 4, 0);
277 ok(res == LB_ERR, "Expected LB_ERR items, got %d\n", res);
278 count = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
279 ok(count == 4, "Unexpected item count %d.\n", count);
281 /* Emptying listbox sends a LB_RESETCONTENT to itself. */
282 flush_sequence(sequences, LB_SEQ_INDEX);
283 for (i = count; i--;)
285 res = SendMessageA(hLB, LB_DELETESTRING, 0, 0);
286 ok(res == i, "Unexpected return value %d.\n", res);
288 ok_sequence(sequences, LB_SEQ_INDEX, delete_seq, "Emptying listbox", FALSE);
290 DestroyWindow(hLB);
293 static void test_item_height(void)
295 INT itemHeight;
296 TEXTMETRICA tm;
297 HFONT font;
298 HWND hLB;
299 HDC hdc;
301 hLB = create_listbox (0, 0);
302 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n");
303 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n");
304 ok (GetTextMetricsA( hdc, &tm ), "Can't read font metrics\n");
305 ReleaseDC( hLB, hdc);
307 ok (SendMessageA(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
309 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
310 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight);
312 DestroyWindow (hLB);
314 hLB = CreateWindowA(WC_LISTBOXA, "TestList", LBS_OWNERDRAWVARIABLE, 0, 0, 100, 100, NULL, NULL, NULL, 0);
316 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
317 ok(itemHeight > 0 && itemHeight <= tm.tmHeight, "Unexpected item height %d, expected %d.\n",
318 itemHeight, tm.tmHeight);
319 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 5, 0);
320 ok(itemHeight > 0 && itemHeight <= tm.tmHeight, "Unexpected item height %d, expected %d.\n",
321 itemHeight, tm.tmHeight);
322 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, -5, 0);
323 ok(itemHeight > 0 && itemHeight <= tm.tmHeight, "Unexpected item height %d, expected %d.\n",
324 itemHeight, tm.tmHeight);
326 DestroyWindow (hLB);
329 static int got_selchange;
331 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
333 static LONG defwndproc_counter = 0;
334 struct message m = { 0 };
335 LRESULT ret;
337 m.message = msg;
338 m.flags = sent|wparam|lparam;
339 if (defwndproc_counter) m.flags |= defwinproc;
340 m.wParam = wParam;
341 m.lParam = lParam;
343 switch (msg)
345 case WM_MEASUREITEM:
347 MEASUREITEMSTRUCT *mis = (void *)lParam;
348 BOOL is_unicode_data = FALSE;
349 MEASURE_ITEM_STRUCT mi;
351 if (mis->CtlType == ODT_LISTBOX)
353 HWND ctrl = GetDlgItem(hwnd, mis->CtlID);
354 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
357 mi.u.wp = 0;
358 mi.u.item.CtlType = mis->CtlType;
359 mi.u.item.CtlID = mis->CtlID;
360 mi.u.item.itemID = mis->itemID;
361 mi.u.item.wParam = wParam;
363 m.wParam = mi.u.wp;
364 if (is_unicode_data)
365 m.lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0;
366 else
367 m.lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0;
368 add_message(sequences, PARENT_SEQ_INDEX, &m);
370 ok(wParam == mis->CtlID, "got wParam=%08lx, expected %08x\n", wParam, mis->CtlID);
371 ok(mis->CtlType == ODT_LISTBOX, "mi->CtlType = %u\n", mis->CtlType);
372 ok(mis->CtlID == 1, "mi->CtlID = %u\n", mis->CtlID);
373 ok(mis->itemHeight, "mi->itemHeight = 0\n");
375 break;
377 case WM_COMPAREITEM:
379 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)lParam;
380 HWND ctrl = GetDlgItem(hwnd, cis->CtlID);
381 BOOL is_unicode_data = TRUE;
383 ok(wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, wParam);
384 ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem);
385 ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1);
386 ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2);
388 if (cis->CtlType == ODT_LISTBOX)
389 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
391 if (is_unicode_data)
393 m.wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0;
394 m.lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0;
396 else
398 m.wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0;
399 m.lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0;
401 add_message(sequences, PARENT_SEQ_INDEX, &m);
402 break;
404 case WM_DRAWITEM:
406 RECT rc_item, rc_client, rc_clip;
407 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam;
409 ok(wParam == dis->CtlID, "got wParam=%08lx instead of %08x\n", wParam, dis->CtlID);
410 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
412 GetClientRect(dis->hwndItem, &rc_client);
413 GetClipBox(dis->hDC, &rc_clip);
414 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip),
415 "client rect of the listbox should be equal to the clip box,"
416 "or the clip box should be empty\n");
418 SendMessageA(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
419 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
421 break;
424 case WM_COMMAND:
425 if (HIWORD( wParam ) == LBN_SELCHANGE) got_selchange++;
426 break;
428 default:
429 break;
432 defwndproc_counter++;
433 ret = DefWindowProcA(hwnd, msg, wParam, lParam);
434 defwndproc_counter--;
436 return msg == WM_COMPAREITEM ? -1 : ret;
439 static HWND create_parent( void )
441 static ATOM class;
442 WNDCLASSA cls;
444 if (!class)
446 cls.style = 0;
447 cls.lpfnWndProc = main_window_proc;
448 cls.cbClsExtra = 0;
449 cls.cbWndExtra = 0;
450 cls.hInstance = GetModuleHandleA(NULL);
451 cls.hIcon = 0;
452 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
453 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
454 cls.lpszMenuName = NULL;
455 cls.lpszClassName = "main_window_class";
456 class = RegisterClassA( &cls );
459 return CreateWindowExA(0, "main_window_class", NULL, WS_POPUP | WS_VISIBLE, 100, 100, 400, 400, GetDesktopWindow(),
460 0, GetModuleHandleA(NULL), NULL);
463 static void test_ownerdraw(void)
465 static const DWORD styles[] =
468 LBS_NODATA
470 HWND parent, hLB;
471 INT ret;
472 RECT rc;
473 UINT i;
475 parent = create_parent();
476 ok(parent != NULL, "Failed to create parent window.\n");
478 for (i = 0; i < ARRAY_SIZE(styles); i++)
480 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE | styles[i], parent);
481 ok(hLB != NULL, "Failed to create listbox window.\n");
483 SetForegroundWindow(hLB);
484 UpdateWindow(hLB);
486 /* make height short enough */
487 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
488 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1, SWP_NOZORDER | SWP_NOMOVE);
490 /* make 0 item invisible */
491 SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
492 ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
493 ok(ret == 1, "wrong top index %d\n", ret);
495 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
496 ok(!IsRectEmpty(&rc), "empty item rect\n");
497 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
499 DestroyWindow(hLB);
501 /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
502 hLB = CreateWindowA(WC_LISTBOXA, "TestList", LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE | styles[i],
503 0, 0, 100, 100, NULL, NULL, NULL, 0);
504 ok(hLB != NULL, "last error 0x%08x\n", GetLastError());
506 ok(GetWindowLongA(hLB, GWL_STYLE) & LBS_OWNERDRAWVARIABLE, "Unexpected window style.\n");
508 ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
509 ok(ret == 0, "Unexpected return value %d.\n", ret);
510 ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
511 ok(ret == 1, "Unexpected return value %d.\n", ret);
513 ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 13);
514 ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
516 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
517 ok(ret == 13, "Unexpected item height %d.\n", ret);
519 ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 1, 42);
520 ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
522 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
523 ok(ret == 42, "Unexpected item height %d.\n", ret);
525 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 1, 0);
526 ok(ret == 42, "Unexpected item height %d.\n", ret);
528 DestroyWindow (hLB);
531 DestroyWindow(parent);
534 #define listbox_test_query(exp, got) \
535 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
536 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
537 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
538 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
540 static void test_LB_SELITEMRANGE(void)
542 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
543 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
544 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
545 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
546 struct listbox_stat answer;
547 HWND hLB;
548 INT ret;
550 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
551 ok(hLB != NULL, "Failed to create listbox window.\n");
553 listbox_query(hLB, &answer);
554 listbox_test_query(test_nosel, answer);
556 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
557 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
558 listbox_query(hLB, &answer);
559 listbox_test_query(test_1, answer);
561 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
562 listbox_query(hLB, &answer);
563 listbox_test_query(test_nosel, answer);
565 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
566 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
567 listbox_query(hLB, &answer);
568 listbox_test_query(test_3, answer);
570 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
571 listbox_query(hLB, &answer);
572 listbox_test_query(test_nosel, answer);
574 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
575 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
576 listbox_query(hLB, &answer);
577 listbox_test_query(test_nosel, answer);
579 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
580 listbox_query(hLB, &answer);
581 listbox_test_query(test_nosel, answer);
583 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
584 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
585 listbox_query(hLB, &answer);
586 listbox_test_query(test_1, answer);
588 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
589 listbox_query(hLB, &answer);
590 listbox_test_query(test_nosel, answer);
592 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
593 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
594 listbox_query(hLB, &answer);
595 listbox_test_query(test_nosel, answer);
597 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
598 listbox_query(hLB, &answer);
599 listbox_test_query(test_nosel, answer);
601 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
602 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
603 listbox_query(hLB, &answer);
604 listbox_test_query(test_2, answer);
606 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
607 listbox_query(hLB, &answer);
608 listbox_test_query(test_nosel, answer);
610 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
611 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
612 listbox_query(hLB, &answer);
613 listbox_test_query(test_2, answer);
615 DestroyWindow(hLB);
618 static void test_LB_SETCURSEL(void)
620 HWND parent, hLB;
621 INT ret;
623 parent = create_parent();
624 ok(parent != NULL, "Failed to create parent window.\n");
626 hLB = create_listbox(LBS_NOINTEGRALHEIGHT | WS_CHILD, parent);
627 ok(hLB != NULL, "Failed to create listbox.\n");
629 SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32);
631 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
632 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
634 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
635 ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret);
636 ret = GetScrollPos(hLB, SB_VERT);
637 ok(ret == 0, "expected vscroll 0, got %d\n", ret);
639 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
640 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
642 ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0);
643 ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret);
644 ret = GetScrollPos(hLB, SB_VERT);
645 ok(ret == 1, "expected vscroll 1, got %d\n", ret);
647 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
648 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
650 DestroyWindow(hLB);
652 hLB = create_listbox(0, 0);
653 ok(hLB != NULL, "Failed to create ListBox window.\n");
655 ret = SendMessageA(hLB, LB_SETCURSEL, 1, 0);
656 ok(ret == 1, "Unexpected return value %d.\n", ret);
658 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
659 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
661 DestroyWindow(hLB);
663 /* LBS_EXTENDEDSEL */
664 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
665 ok(hLB != NULL, "Failed to create listbox.\n");
667 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
668 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
670 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
671 ok(ret == -1, "LB_SETCURSEL returned %d instead of 2\n", ret);
673 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
674 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
676 DestroyWindow(hLB);
678 /* LBS_MULTIPLESEL */
679 hLB = create_listbox(LBS_MULTIPLESEL, 0);
680 ok(hLB != NULL, "Failed to create listbox.\n");
682 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
683 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
685 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
686 ok(ret == -1, "LB_SETCURSEL returned %d instead of 2\n", ret);
688 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
689 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
691 DestroyWindow(hLB);
694 static void test_LB_SETSEL(void)
696 HWND list;
697 int ret;
699 /* LBS_EXTENDEDSEL */
700 list = create_listbox(LBS_EXTENDEDSEL, 0);
701 ok(list != NULL, "Failed to create ListBox window.\n");
703 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
704 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
706 ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
707 ok(ret == 0, "Unexpected return value %d.\n", ret);
708 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
709 ok(ret == 0, "Unexpected anchor index %d.\n", ret);
710 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
711 ok(ret == 0, "Unexpected caret index %d.\n", ret);
713 ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
714 ok(ret == 0, "Unexpected return value %d.\n", ret);
715 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
716 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
717 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
718 ok(ret == 1, "Unexpected caret index %d.\n", ret);
720 ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
721 ok(ret == 0, "Unexpected return value %d.\n", ret);
722 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
723 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
724 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
725 ok(ret == 1, "Unexpected caret index %d.\n", ret);
727 DestroyWindow(list);
729 /* LBS_MULTIPLESEL */
730 list = create_listbox(LBS_MULTIPLESEL, 0);
731 ok(list != NULL, "Failed to create ListBox window.\n");
733 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
734 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
736 ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
737 ok(ret == 0, "Unexpected return value %d.\n", ret);
738 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
739 ok(ret == 0, "Unexpected anchor index %d.\n", ret);
740 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
741 ok(ret == 0, "Unexpected caret index %d.\n", ret);
743 ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
744 ok(ret == 0, "Unexpected return value %d.\n", ret);
745 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
746 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
747 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
748 ok(ret == 1, "Unexpected caret index %d.\n", ret);
750 ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
751 ok(ret == 0, "Unexpected return value %d.\n", ret);
752 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
753 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
754 ret = SendMessageA(list, LB_GETCARETINDEX, 0, 0);
755 ok(ret == 1, "Unexpected caret index %d.\n", ret);
757 DestroyWindow(list);
760 static void test_listbox_height(void)
762 HWND hList;
763 int r, id;
765 hList = CreateWindowA( WC_LISTBOXA, "list test", 0,
766 1, 1, 600, 100, NULL, NULL, NULL, NULL );
767 ok( hList != NULL, "failed to create listbox\n");
769 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
770 ok( id == 0, "item id wrong\n");
772 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
773 ok( r == 0, "send message failed\n");
775 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
776 ok( r == 20, "height wrong\n");
778 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
779 ok( r == -1, "send message failed\n");
781 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
782 ok( r == 20, "height wrong\n");
784 /* Before Windows 10 1709 (or 1703?) the item height was limited to 255.
785 * Since then, with comctl32 V6 the limit is 65535.
787 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 256, 0 ));
788 ok(r == 0 || broken(r == -1), "Failed to set item height, %d.\n", r);
789 if (r == -1)
791 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
792 ok( r == 20, "Unexpected item height %d.\n", r);
794 else
796 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
797 ok( r == 256, "Unexpected item height %d.\n", r);
799 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 65535, 0 ));
800 ok(r == 0, "Failed to set item height, %d.\n", r);
802 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
803 ok( r == 65535, "Unexpected item height %d.\n", r);
806 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
807 ok( r == 0, "send message failed\n");
809 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
810 ok( r == 0xff, "height wrong\n");
812 DestroyWindow( hList );
815 static void test_changing_selection_styles(void)
817 static const DWORD styles[] =
820 LBS_NODATA | LBS_OWNERDRAWFIXED
822 static const DWORD selstyles[] =
825 LBS_MULTIPLESEL,
826 LBS_EXTENDEDSEL,
827 LBS_MULTIPLESEL | LBS_EXTENDEDSEL
829 static const LONG selexpect_single[] = { 0, 0, 1 };
830 static const LONG selexpect_single2[] = { 1, 0, 0 };
831 static const LONG selexpect_multi[] = { 1, 0, 1 };
832 static const LONG selexpect_multi2[] = { 1, 1, 0 };
834 HWND parent, listbox;
835 DWORD style;
836 LONG ret;
837 UINT i, j, k;
839 parent = create_parent();
840 ok(parent != NULL, "Failed to create parent window.\n");
841 for (i = 0; i < ARRAY_SIZE(styles); i++)
843 /* Test if changing selection styles affects selection storage */
844 for (j = 0; j < ARRAY_SIZE(selstyles); j++)
846 LONG setcursel_expect, selitemrange_expect, getselcount_expect;
847 const LONG *selexpect;
849 listbox = CreateWindowA(WC_LISTBOXA, "TestList", styles[i] | selstyles[j] | WS_CHILD | WS_VISIBLE,
850 0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0);
851 ok(listbox != NULL, "%u: Failed to create ListBox window.\n", j);
853 if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
855 setcursel_expect = LB_ERR;
856 selitemrange_expect = LB_OKAY;
857 getselcount_expect = 2;
858 selexpect = selexpect_multi;
860 else
862 setcursel_expect = 2;
863 selitemrange_expect = LB_ERR;
864 getselcount_expect = LB_ERR;
865 selexpect = selexpect_single;
868 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
870 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"x");
871 ok(ret == k, "%u: Unexpected return value %d, expected %d.\n", j, ret, k);
873 ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
874 ok(ret == ARRAY_SIZE(selexpect_multi), "%u: Unexpected count %d.\n", j, ret);
876 /* Select items with different methods */
877 ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0);
878 ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
879 ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 0));
880 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
881 ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 2));
882 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
884 /* Verify that the proper items are selected */
885 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
887 ret = SendMessageA(listbox, LB_GETSEL, k, 0);
888 ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
889 j, ret, selexpect[k]);
892 /* Now change the selection style */
893 style = GetWindowLongA(listbox, GWL_STYLE);
894 ok((style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == selstyles[j],
895 "%u: unexpected window styles %#x.\n", j, style);
896 if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
897 style &= ~selstyles[j];
898 else
899 style |= LBS_MULTIPLESEL | LBS_EXTENDEDSEL;
900 SetWindowLongA(listbox, GWL_STYLE, style);
901 style = GetWindowLongA(listbox, GWL_STYLE);
902 ok(!(style & selstyles[j]), "%u: unexpected window styles %#x.\n", j, style);
904 /* Verify that the same items are selected */
905 ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
906 ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
907 j, getselcount_expect, ret);
909 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
911 ret = SendMessageA(listbox, LB_GETSEL, k, 0);
912 ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
913 j, ret, selexpect[k]);
916 /* Lastly see if we can still change the selection as before with old style */
917 if (setcursel_expect != LB_ERR) setcursel_expect = 0;
918 ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0);
919 ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
920 ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 1));
921 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
922 ret = SendMessageA(listbox, LB_SELITEMRANGE, FALSE, MAKELPARAM(2, 2));
923 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
925 /* And verify the selections */
926 selexpect = (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) ? selexpect_multi2 : selexpect_single2;
927 ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
928 ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
929 j, getselcount_expect, ret);
931 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
933 ret = SendMessageA(listbox, LB_GETSEL, k, 0);
934 ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
935 j, ret, selexpect[k]);
938 DestroyWindow(listbox);
941 DestroyWindow(parent);
944 static void test_itemfrompoint(void)
946 /* WS_POPUP is required in order to have a more accurate size calculation (
947 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
948 behavior of partially-displayed item.
950 HWND hList = CreateWindowA( WC_LISTBOXA, "list test",
951 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
952 1, 1, 600, 100, NULL, NULL, NULL, NULL );
953 ULONG r, id;
954 RECT rc;
956 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
957 ok( r == MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r );
959 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
960 ok( r == MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r );
962 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
963 ok( r == MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r );
965 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
966 ok( id == 0, "item id wrong\n");
967 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
968 ok( id == 1, "item id wrong\n");
970 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
971 ok( r == 0x1, "ret %x\n", r );
973 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
974 ok( r == MAKELPARAM(1, 1), "Unexpected ret value %#x.\n", r );
976 /* Resize control so that below assertions about sizes are valid */
977 r = SendMessageA( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
978 ok( r == 1, "ret %x\n", r);
979 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
980 ok( r != 0, "ret %x\n", r);
982 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
983 ok( id == 2, "item id wrong\n");
984 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
985 ok( id == 3, "item id wrong\n");
986 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
987 ok( id == 4, "item id wrong\n");
988 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
989 ok( id == 5, "item id wrong\n");
990 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
991 ok( id == 6, "item id wrong\n");
992 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
993 ok( id == 7, "item id wrong\n");
995 /* Set the listbox up so that id 1 is at the top, this leaves 5
996 partially visible at the bottom and 6, 7 are invisible */
998 SendMessageA( hList, LB_SETTOPINDEX, 1, 0);
999 r = SendMessageA( hList, LB_GETTOPINDEX, 0, 0);
1000 ok( r == 1, "top %d\n", r);
1002 r = SendMessageA( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
1003 ok( r == 1, "ret %x\n", r);
1004 r = SendMessageA( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
1005 ok( r == 0, "ret %x\n", r);
1007 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
1008 ok( r == 1, "ret %x\n", r);
1010 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
1011 ok( r == 0x10001, "ret %x\n", r );
1013 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
1014 ok( r == 0x10001, "ret %x\n", r );
1016 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
1017 ok( r == 0x10005, "item %x\n", r );
1019 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
1020 ok( r == 0x10005, "item %x\n", r );
1022 DestroyWindow( hList );
1025 static void test_listbox_item_data(void)
1027 HWND hList;
1028 int r, id;
1030 hList = CreateWindowA( WC_LISTBOXA, "list test", 0,
1031 1, 1, 600, 100, NULL, NULL, NULL, NULL );
1032 ok( hList != NULL, "failed to create listbox\n");
1034 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
1035 ok( id == 0, "item id wrong\n");
1037 r = SendMessageA( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
1038 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
1040 r = SendMessageA( hList, LB_GETITEMDATA, 0, 0);
1041 ok( r == 20, "get item data failed\n");
1043 DestroyWindow( hList );
1046 static void test_listbox_LB_DIR(void)
1048 char path[MAX_PATH], curdir[MAX_PATH];
1049 HWND hList;
1050 int res, itemCount;
1051 int itemCount_justFiles;
1052 int itemCount_justDrives;
1053 int itemCount_allFiles;
1054 int itemCount_allDirs;
1055 int i;
1056 char pathBuffer[MAX_PATH];
1057 char * p;
1058 char driveletter;
1059 const char *wildcard = "*";
1060 HANDLE file;
1061 BOOL ret;
1063 GetCurrentDirectoryA(ARRAY_SIZE(curdir), curdir);
1065 GetTempPathA(ARRAY_SIZE(path), path);
1066 ret = SetCurrentDirectoryA(path);
1067 ok(ret, "Failed to set current directory.\n");
1069 ret = CreateDirectoryA("lb_dir_test", NULL);
1070 ok(ret, "Failed to create test directory.\n");
1072 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1073 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1074 CloseHandle( file );
1076 /* NOTE: for this test to succeed, there must be no subdirectories
1077 under the current directory. In addition, there must be at least
1078 one file that fits the wildcard w*.c . Normally, the test
1079 directory itself satisfies both conditions.
1081 hList = CreateWindowA( WC_LISTBOXA, "list test", WS_VISIBLE|WS_POPUP,
1082 1, 1, 600, 100, NULL, NULL, NULL, NULL );
1083 ok(hList != NULL, "Failed to create listbox window.\n");
1085 /* Test for standard usage */
1087 /* This should list all the files in the test directory. */
1088 strcpy(pathBuffer, wildcard);
1089 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1090 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
1091 if (res == -1) /* "*" wildcard doesn't work on win9x */
1093 wildcard = "*.*";
1094 strcpy(pathBuffer, wildcard);
1095 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
1097 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
1099 /* There should be some content in the listbox */
1100 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1101 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
1102 itemCount_allFiles = itemCount;
1103 ok(res + 1 == itemCount,
1104 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
1105 itemCount - 1, res);
1107 /* This tests behavior when no files match the wildcard */
1108 strcpy(pathBuffer, BAD_EXTENSION);
1109 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1110 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
1111 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
1113 /* There should be NO content in the listbox */
1114 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1115 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
1118 /* This should list all the w*.c files in the test directory
1119 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1121 strcpy(pathBuffer, "w*.c");
1122 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1123 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
1124 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
1126 /* Path specification does NOT converted to uppercase */
1127 ok (!strcmp(pathBuffer, "w*.c"),
1128 "expected no change to pathBuffer, got %s\n", pathBuffer);
1130 /* There should be some content in the listbox */
1131 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1132 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
1133 itemCount_justFiles = itemCount;
1134 ok(res + 1 == itemCount,
1135 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
1136 itemCount - 1, res);
1138 /* Every single item in the control should start with a w and end in .c */
1139 for (i = 0; i < itemCount; i++)
1141 memset(pathBuffer, 0, MAX_PATH);
1142 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1143 p = pathBuffer + strlen(pathBuffer);
1144 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1145 (*(p-1) == 'c' || *(p-1) == 'C') &&
1146 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1149 /* Test DDL_DIRECTORY */
1150 strcpy(pathBuffer, wildcard);
1151 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1152 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
1153 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
1155 /* There should be some content in the listbox.
1156 * All files plus "[..]"
1158 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1159 itemCount_allDirs = itemCount - itemCount_allFiles;
1160 ok (itemCount >= itemCount_allFiles,
1161 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
1162 itemCount, itemCount_allFiles);
1163 ok(res + 1 == itemCount,
1164 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
1165 itemCount - 1, res);
1167 /* This tests behavior when no files match the wildcard */
1168 strcpy(pathBuffer, BAD_EXTENSION);
1169 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1170 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
1171 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
1173 /* There should be NO content in the listbox */
1174 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1175 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
1177 /* Test DDL_DIRECTORY */
1178 strcpy(pathBuffer, "w*.c");
1179 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1180 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
1181 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
1183 /* There should be some content in the listbox. Since the parent directory does not
1184 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
1186 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1187 ok (itemCount == itemCount_justFiles,
1188 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
1189 itemCount, itemCount_justFiles);
1190 ok(res + 1 == itemCount,
1191 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
1192 itemCount - 1, res);
1194 /* Every single item in the control should start with a w and end in .c. */
1195 for (i = 0; i < itemCount; i++)
1197 memset(pathBuffer, 0, MAX_PATH);
1198 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1199 p = pathBuffer + strlen(pathBuffer);
1201 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1202 (*(p-1) == 'c' || *(p-1) == 'C') &&
1203 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1206 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
1207 strcpy(pathBuffer, wildcard);
1208 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1209 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1210 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
1212 /* There should be some content in the listbox. In particular, there should
1213 * be at least one element before, since the string "[-c-]" should
1214 * have been added. Depending on the user setting, more drives might have
1215 * been added.
1217 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1218 ok (itemCount >= 1,
1219 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
1220 itemCount, 1);
1221 itemCount_justDrives = itemCount;
1222 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1224 /* Every single item in the control should fit the format [-c-] */
1225 for (i = 0; i < itemCount; i++)
1227 memset(pathBuffer, 0, MAX_PATH);
1228 driveletter = '\0';
1229 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1230 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1231 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1232 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1233 if (!(driveletter >= 'a' && driveletter <= 'z'))
1235 /* Correct after invalid entry is found */
1236 itemCount_justDrives--;
1240 /* This tests behavior when no files match the wildcard */
1241 strcpy(pathBuffer, BAD_EXTENSION);
1242 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1243 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1244 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1245 BAD_EXTENSION, res, itemCount_justDrives -1);
1247 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1248 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
1249 itemCount, itemCount_justDrives);
1251 /* Test DDL_DRIVES. */
1252 strcpy(pathBuffer, wildcard);
1253 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1254 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
1255 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
1257 /* There should be some content in the listbox. In particular, there should
1258 * be at least one element before, since the string "[-c-]" should
1259 * have been added. Depending on the user setting, more drives might have
1260 * been added.
1262 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1263 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
1264 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
1265 itemCount, itemCount_justDrives + itemCount_allFiles);
1266 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
1268 /* This tests behavior when no files match the wildcard */
1269 strcpy(pathBuffer, BAD_EXTENSION);
1270 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1271 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
1272 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
1273 BAD_EXTENSION, res, itemCount_justDrives -1);
1275 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1276 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1278 /* Test DDL_DRIVES. */
1279 strcpy(pathBuffer, "w*.c");
1280 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1281 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
1282 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
1284 /* There should be some content in the listbox. In particular, there should
1285 * be at least one element before, since the string "[-c-]" should
1286 * have been added. Depending on the user setting, more drives might have
1287 * been added.
1289 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1290 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
1291 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
1292 itemCount, itemCount_justDrives + itemCount_justFiles);
1293 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
1295 /* Every single item in the control should fit the format [-c-], or w*.c */
1296 for (i = 0; i < itemCount; i++)
1298 memset(pathBuffer, 0, MAX_PATH);
1299 driveletter = '\0';
1300 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1301 p = pathBuffer + strlen(pathBuffer);
1302 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1304 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1305 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1307 else
1310 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1311 (*(p-1) == 'c' || *(p-1) == 'C') &&
1312 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1316 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1317 strcpy(pathBuffer, wildcard);
1318 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1319 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1320 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
1322 /* There should be some content in the listbox. In particular, there should
1323 * be exactly the number of plain files, plus the number of mapped drives.
1325 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1326 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
1327 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1328 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
1329 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1331 /* Every single item in the control should start with a w and end in .c,
1332 * except for the "[..]" string, which should appear exactly as it is,
1333 * and the mapped drives in the format "[-X-]".
1335 for (i = 0; i < itemCount; i++)
1337 memset(pathBuffer, 0, MAX_PATH);
1338 driveletter = '\0';
1339 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1340 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1341 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1344 /* This tests behavior when no files match the wildcard */
1345 strcpy(pathBuffer, BAD_EXTENSION);
1346 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1347 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1348 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
1349 BAD_EXTENSION, res, itemCount_justDrives -1);
1351 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1352 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1354 /* Test DDL_DIRECTORY|DDL_DRIVES. */
1355 strcpy(pathBuffer, "w*.c");
1356 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1357 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1358 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
1360 /* There should be some content in the listbox. In particular, there should
1361 * be exactly the number of plain files, plus the number of mapped drives.
1363 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1364 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
1365 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1366 itemCount, itemCount_justFiles + itemCount_justDrives);
1367 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1369 /* Every single item in the control should start with a w and end in .c,
1370 * except the mapped drives in the format "[-X-]". The "[..]" directory
1371 * should not appear.
1373 for (i = 0; i < itemCount; i++)
1375 memset(pathBuffer, 0, MAX_PATH);
1376 driveletter = '\0';
1377 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1378 p = pathBuffer + strlen(pathBuffer);
1379 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1380 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1381 else
1383 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1384 (*(p-1) == 'c' || *(p-1) == 'C') &&
1385 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1388 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1389 strcpy(pathBuffer, wildcard);
1390 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1391 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1392 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n",
1393 GetLastError());
1395 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1396 ok (itemCount == itemCount_allDirs,
1397 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1398 itemCount, itemCount_allDirs);
1399 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1401 if (itemCount)
1403 memset(pathBuffer, 0, MAX_PATH);
1404 SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1405 ok( !strcmp(pathBuffer, "[..]"), "First element is %s, not [..]\n", pathBuffer);
1408 /* This tests behavior when no files match the wildcard */
1409 strcpy(pathBuffer, BAD_EXTENSION);
1410 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1411 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1412 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1413 BAD_EXTENSION, res, -1);
1415 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1416 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1419 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1420 strcpy(pathBuffer, "w*.c");
1421 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1422 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1423 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
1425 /* There should be no elements, since "[..]" does not fit w*.c */
1426 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1427 ok (itemCount == 0,
1428 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1429 itemCount, 0);
1431 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1432 strcpy(pathBuffer, wildcard);
1433 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1434 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1435 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1437 /* There should be no plain files on the listbox */
1438 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1439 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1440 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1441 itemCount, itemCount_justDrives + itemCount_allDirs);
1442 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1444 for (i = 0; i < itemCount; i++)
1446 memset(pathBuffer, 0, MAX_PATH);
1447 driveletter = '\0';
1448 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1449 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1450 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1451 else
1452 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1453 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1456 /* This tests behavior when no files match the wildcard */
1457 strcpy(pathBuffer, BAD_EXTENSION);
1458 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1459 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1460 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1461 BAD_EXTENSION, res, itemCount_justDrives -1);
1463 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1464 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1466 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1467 strcpy(pathBuffer, "w*.c");
1468 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1469 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1470 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1472 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
1473 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1474 ok (itemCount == itemCount_justDrives,
1475 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1476 itemCount, itemCount_justDrives);
1477 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1479 for (i = 0; i < itemCount; i++)
1481 memset(pathBuffer, 0, MAX_PATH);
1482 driveletter = '\0';
1483 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1484 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1485 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1487 DestroyWindow(hList);
1489 DeleteFileA( "wtest1.tmp.c" );
1490 RemoveDirectoryA("lb_dir_test");
1492 SetCurrentDirectoryA(curdir);
1495 static HWND g_listBox;
1496 static HWND g_label;
1498 #define ID_TEST_LABEL 1001
1499 #define ID_TEST_LISTBOX 1002
1501 static BOOL on_listbox_container_create(HWND hwnd, CREATESTRUCTA *lpcs)
1503 g_label = CreateWindowA(WC_STATICA, "Contents of static control before DlgDirList.",
1504 WS_CHILD | WS_VISIBLE, 10, 10, 512, 32, hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1505 if (!g_label) return FALSE;
1507 g_listBox = CreateWindowA(WC_LISTBOXA, "DlgDirList test",
1508 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL, 10, 60, 256, 256,
1509 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1510 if (!g_listBox) return FALSE;
1512 return TRUE;
1515 static LRESULT CALLBACK listbox_container_window_procA(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1517 LRESULT result = 0;
1519 switch (uiMsg)
1521 case WM_DESTROY:
1522 PostQuitMessage(0);
1523 break;
1524 case WM_CREATE:
1525 result = on_listbox_container_create(hwnd, (CREATESTRUCTA *)lParam) ? 0 : (LRESULT)-1;
1526 break;
1527 default:
1528 result = DefWindowProcA(hwnd, uiMsg, wParam, lParam);
1529 break;
1531 return result;
1534 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1536 WNDCLASSA cls;
1538 cls.style = 0;
1539 cls.cbClsExtra = 0;
1540 cls.cbWndExtra = 0;
1541 cls.hInstance = hInst;
1542 cls.hIcon = NULL;
1543 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
1544 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1545 cls.lpszMenuName = NULL;
1546 cls.lpfnWndProc = listbox_container_window_procA;
1547 cls.lpszClassName = "ListboxContainerClass";
1548 if (!RegisterClassA (&cls)) return FALSE;
1550 return TRUE;
1553 static void test_listbox_dlgdir(void)
1555 HINSTANCE hInst;
1556 HWND hWnd;
1557 int res, itemCount;
1558 int itemCount_allDirs;
1559 int itemCount_justFiles;
1560 int itemCount_justDrives;
1561 int i;
1562 char pathBuffer[MAX_PATH];
1563 char itemBuffer[MAX_PATH];
1564 char tempBuffer[MAX_PATH];
1565 char * p;
1566 char driveletter;
1567 HANDLE file;
1568 BOOL ret;
1570 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1571 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1572 CloseHandle( file );
1574 /* NOTE: for this test to succeed, there must be no subdirectories
1575 under the current directory. In addition, there must be at least
1576 one file that fits the wildcard w*.c . Normally, the test
1577 directory itself satisfies both conditions.
1580 hInst = GetModuleHandleA(0);
1581 ret = RegisterListboxWindowClass(hInst);
1582 ok(ret, "Failed to register test class.\n");
1584 hWnd = CreateWindowA("ListboxContainerClass", "ListboxContainerClass",
1585 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1586 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1587 NULL, NULL, hInst, 0);
1588 ok(hWnd != NULL, "Failed to create container window.\n");
1590 /* Test for standard usage */
1592 /* The following should be overwritten by the directory path */
1593 SendMessageA(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1595 /* This should list all the w*.c files in the test directory
1596 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1598 strcpy(pathBuffer, "w*.c");
1599 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1600 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1602 /* Path specification gets converted to uppercase */
1603 ok (!strcmp(pathBuffer, "W*.C"),
1604 "expected conversion to uppercase, got %s\n", pathBuffer);
1606 /* Loaded path should have overwritten the label text */
1607 SendMessageA(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer);
1608 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1610 /* There should be some content in the listbox */
1611 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1612 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1613 itemCount_justFiles = itemCount;
1615 /* Every single item in the control should start with a w and end in .c */
1616 for (i = 0; i < itemCount; i++)
1618 memset(pathBuffer, 0, MAX_PATH);
1619 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1620 p = pathBuffer + strlen(pathBuffer);
1621 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1622 (*(p-1) == 'c' || *(p-1) == 'C') &&
1623 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1626 /* Test behavior when no files match the wildcard */
1627 strcpy(pathBuffer, BAD_EXTENSION);
1628 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1629 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1631 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1632 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1634 /* Test DDL_DIRECTORY */
1635 strcpy(pathBuffer, "w*.c");
1636 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY);
1637 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1639 /* There should be some content in the listbox. In particular, there should
1640 * be exactly more elements than before, since the directories should
1641 * have been added.
1643 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1644 itemCount_allDirs = itemCount - itemCount_justFiles;
1645 ok (itemCount >= itemCount_justFiles, "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1646 itemCount, itemCount_justFiles);
1648 /* Every single item in the control should start with a w and end in .c,
1649 * except for the "[..]" string, which should appear exactly as it is.
1651 for (i = 0; i < itemCount; i++)
1653 memset(pathBuffer, 0, MAX_PATH);
1654 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1655 p = pathBuffer + strlen(pathBuffer);
1656 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1657 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1658 (*(p-1) == 'c' || *(p-1) == 'C') &&
1659 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1662 /* Test behavior when no files match the wildcard */
1663 strcpy(pathBuffer, BAD_EXTENSION);
1664 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY);
1665 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1667 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1668 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1669 itemCount_allDirs, itemCount);
1670 for (i = 0; i < itemCount; i++)
1672 memset(pathBuffer, 0, MAX_PATH);
1673 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1674 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1675 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1678 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1679 strcpy(pathBuffer, "w*.c");
1680 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DRIVES);
1681 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1683 /* There should be some content in the listbox. In particular, there should
1684 * be at least one element before, since the string "[-c-]" should
1685 * have been added. Depending on the user setting, more drives might have
1686 * been added.
1688 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1689 ok (itemCount >= 1,
1690 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1691 itemCount, 1);
1692 itemCount_justDrives = itemCount;
1694 /* Every single item in the control should fit the format [-c-] */
1695 for (i = 0; i < itemCount; i++)
1697 memset(pathBuffer, 0, MAX_PATH);
1698 driveletter = '\0';
1699 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1700 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1701 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1702 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1703 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1704 /* Correct after invalid entry is found */
1705 trace("removing count of invalid entry %s\n", pathBuffer);
1706 itemCount_justDrives--;
1710 /* Test behavior when no files match the wildcard */
1711 strcpy(pathBuffer, BAD_EXTENSION);
1712 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DRIVES);
1713 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1715 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1716 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1718 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1719 strcpy(pathBuffer, "w*.c");
1720 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES);
1721 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1723 /* There should be some content in the listbox. In particular, there should
1724 * be exactly the number of plain files, plus the number of mapped drives,
1725 * plus one "[..]"
1727 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1728 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1729 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1730 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1732 /* Every single item in the control should start with a w and end in .c,
1733 * except for the "[..]" string, which should appear exactly as it is,
1734 * and the mapped drives in the format "[-X-]".
1736 for (i = 0; i < itemCount; i++)
1738 memset(pathBuffer, 0, MAX_PATH);
1739 driveletter = '\0';
1740 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1741 p = pathBuffer + strlen(pathBuffer);
1742 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1743 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1744 else
1745 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1746 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1747 (*(p-1) == 'c' || *(p-1) == 'C') &&
1748 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1751 /* Test behavior when no files match the wildcard */
1752 strcpy(pathBuffer, BAD_EXTENSION);
1753 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES);
1754 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1756 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1757 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1758 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1759 itemCount_justDrives + itemCount_allDirs, itemCount);
1761 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1762 strcpy(pathBuffer, "w*.c");
1763 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_EXCLUSIVE);
1764 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1766 /* There should be exactly one element: "[..]" */
1767 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1768 ok (itemCount == itemCount_allDirs,
1769 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1770 itemCount, itemCount_allDirs);
1772 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1774 memset(pathBuffer, 0, MAX_PATH);
1775 SendMessageA(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1776 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1779 /* Test behavior when no files match the wildcard */
1780 strcpy(pathBuffer, BAD_EXTENSION);
1781 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_EXCLUSIVE);
1782 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1784 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1785 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1787 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1788 strcpy(pathBuffer, "w*.c");
1789 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1790 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1792 /* There should be no plain files on the listbox */
1793 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1794 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1795 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1796 itemCount, itemCount_justDrives + itemCount_allDirs);
1798 for (i = 0; i < itemCount; i++)
1800 memset(pathBuffer, 0, MAX_PATH);
1801 driveletter = '\0';
1802 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1803 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1804 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1805 else
1806 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1807 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1810 /* Test behavior when no files match the wildcard */
1811 strcpy(pathBuffer, BAD_EXTENSION);
1812 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1813 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1815 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1816 ok (itemCount == itemCount_justDrives + itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1818 /* Now test DlgDirSelectEx() in normal operation */
1819 /* Fill with everything - drives, directory and all plain files. */
1820 strcpy(pathBuffer, "*");
1821 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES);
1822 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1824 SendMessageA(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1825 memset(pathBuffer, 0, MAX_PATH);
1826 SetLastError(0xdeadbeef);
1827 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1828 ok (GetLastError() == 0xdeadbeef,
1829 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1830 GetLastError());
1831 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1832 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1834 ok (!*pathBuffer, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1836 /* Test proper drive/dir/file recognition */
1837 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1838 for (i = 0; i < itemCount; i++)
1840 memset(itemBuffer, 0, MAX_PATH);
1841 memset(pathBuffer, 0, MAX_PATH);
1842 memset(tempBuffer, 0, MAX_PATH);
1843 driveletter = '\0';
1844 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1845 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1846 ok (res == i, "SendMessageA(LB_SETCURSEL, %d) failed\n", i);
1847 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1)
1849 /* Current item is a drive letter */
1850 SetLastError(0xdeadbeef);
1851 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1852 ok (GetLastError() == 0xdeadbeef,
1853 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1854 i, GetLastError());
1855 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1857 /* For drive letters, DlgDirSelectEx tacks on a colon */
1858 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1859 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1861 else if (itemBuffer[0] == '[')
1863 /* Current item is the parent directory */
1864 SetLastError(0xdeadbeef);
1865 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1866 ok (GetLastError() == 0xdeadbeef,
1867 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1868 i, GetLastError());
1869 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1871 /* For directories, DlgDirSelectEx tacks on a backslash */
1872 p = pathBuffer + strlen(pathBuffer);
1873 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1875 tempBuffer[0] = '[';
1876 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1877 strcat(tempBuffer, "]");
1878 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1880 else
1882 /* Current item is a plain file */
1883 SetLastError(0xdeadbeef);
1884 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1885 ok (GetLastError() == 0xdeadbeef,
1886 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1887 i, GetLastError());
1888 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1890 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1891 * for example, "Makefile", which gets reported as "Makefile."
1893 strcpy(tempBuffer, itemBuffer);
1894 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1895 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1899 DeleteFileA( "wtest1.tmp.c" );
1901 /* Now test DlgDirSelectEx() in abnormal operation */
1902 /* Fill list with bogus entries, that look somewhat valid */
1903 SendMessageA(g_listBox, LB_RESETCONTENT, 0, 0);
1904 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1905 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1906 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1907 for (i = 0; i < itemCount; i++)
1909 memset(itemBuffer, 0, MAX_PATH);
1910 memset(pathBuffer, 0, MAX_PATH);
1911 memset(tempBuffer, 0, MAX_PATH);
1912 driveletter = '\0';
1913 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1914 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1915 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1916 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1)
1918 /* Current item is a drive letter */
1919 SetLastError(0xdeadbeef);
1920 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1921 ok (GetLastError() == 0xdeadbeef,
1922 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1923 i, GetLastError());
1924 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1926 /* For drive letters, DlgDirSelectEx tacks on a colon */
1927 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1928 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1930 else if (itemBuffer[0] == '[')
1932 /* Current item is the parent directory */
1933 SetLastError(0xdeadbeef);
1934 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1935 ok (GetLastError() == 0xdeadbeef,
1936 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1937 i, GetLastError());
1938 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1940 /* For directories, DlgDirSelectEx tacks on a backslash */
1941 p = pathBuffer + strlen(pathBuffer);
1942 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1944 tempBuffer[0] = '[';
1945 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1946 strcat(tempBuffer, "]");
1947 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1949 else
1951 /* Current item is a plain file */
1952 SetLastError(0xdeadbeef);
1953 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1954 ok (GetLastError() == 0xdeadbeef,
1955 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1956 i, GetLastError());
1957 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1959 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1960 * This affects for example, "Makefile", which gets reported as "Makefile."
1962 strcpy(tempBuffer, itemBuffer);
1963 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1964 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1968 /* Test behavior when loading folders from root with and without wildcard */
1969 strcpy(pathBuffer, "C:\\");
1970 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1971 ok(res, "DlgDirList failed to list C:\\ folders\n");
1972 ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1974 strcpy(pathBuffer, "C:\\*");
1975 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1976 ok(res, "DlgDirList failed to list C:\\* folders\n");
1977 ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1979 /* Try loading files from an invalid folder */
1980 SetLastError(0xdeadbeef);
1981 strcpy(pathBuffer, "C:\\INVALID$$DIR");
1982 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1983 ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
1984 ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
1985 "GetLastError should return 0x589, got 0x%X\n",GetLastError());
1987 DestroyWindow(hWnd);
1990 static void test_set_count( void )
1992 static const DWORD styles[] =
1994 LBS_OWNERDRAWFIXED,
1995 LBS_HASSTRINGS,
1997 HWND parent, listbox;
1998 unsigned int i;
1999 LONG ret;
2000 RECT r;
2002 parent = create_parent();
2003 listbox = create_listbox( LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VISIBLE, parent );
2005 UpdateWindow( listbox );
2006 GetUpdateRect( listbox, &r, TRUE );
2007 ok( IsRectEmpty( &r ), "got non-empty rect\n");
2009 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
2010 ok( ret == 0, "got %d\n", ret );
2011 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
2012 ok( ret == 100, "got %d\n", ret );
2014 GetUpdateRect( listbox, &r, TRUE );
2015 ok( !IsRectEmpty( &r ), "got empty rect\n");
2017 ValidateRect( listbox, NULL );
2018 GetUpdateRect( listbox, &r, TRUE );
2019 ok( IsRectEmpty( &r ), "got non-empty rect\n");
2021 ret = SendMessageA( listbox, LB_SETCOUNT, 99, 0 );
2022 ok( ret == 0, "got %d\n", ret );
2024 GetUpdateRect( listbox, &r, TRUE );
2025 ok( !IsRectEmpty( &r ), "got empty rect\n");
2027 ret = SendMessageA( listbox, LB_SETCOUNT, -5, 0 );
2028 ok( ret == 0, "got %d\n", ret );
2029 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
2030 ok( ret == -5, "got %d\n", ret );
2032 DestroyWindow( listbox );
2034 for (i = 0; i < ARRAY_SIZE(styles); ++i)
2036 listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent );
2038 SetLastError( 0xdeadbeef );
2039 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
2040 ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret );
2041 ok( GetLastError() == 0xdeadbeef, "Unexpected error %d.\n", GetLastError() );
2043 DestroyWindow( listbox );
2046 DestroyWindow( parent );
2049 static void test_GetListBoxInfo(void)
2051 static const struct message getlistboxinfo_seq[] =
2053 { LB_GETLISTBOXINFO, sent },
2054 { 0 }
2056 HWND listbox, parent;
2057 DWORD ret;
2059 parent = create_parent();
2060 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
2062 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2063 ret = GetListBoxInfo(listbox);
2064 ok(ret > 0, "got %d\n", ret);
2065 ok_sequence(sequences, LB_SEQ_INDEX, getlistboxinfo_seq, "GetListBoxInfo()", FALSE);
2067 DestroyWindow(listbox);
2068 DestroyWindow(parent);
2071 static void test_init_storage( void )
2073 static const DWORD styles[] =
2075 LBS_HASSTRINGS,
2076 LBS_NODATA | LBS_OWNERDRAWFIXED,
2078 HWND parent, listbox;
2079 LONG ret, items_size;
2080 int i, j;
2082 parent = create_parent();
2083 for (i = 0; i < ARRAY_SIZE(styles); i++)
2085 listbox = CreateWindowA(WC_LISTBOXA, "TestList", styles[i] | WS_CHILD,
2086 0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0);
2088 items_size = SendMessageA(listbox, LB_INITSTORAGE, 100, 0);
2089 ok(items_size >= 100, "expected at least 100, got %d\n", items_size);
2091 ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
2092 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2094 /* it doesn't grow since the space was already reserved */
2095 ret = SendMessageA(listbox, LB_INITSTORAGE, items_size, 0);
2096 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2098 /* it doesn't shrink the reserved space */
2099 ret = SendMessageA(listbox, LB_INITSTORAGE, 42, 0);
2100 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2102 /* now populate almost all of it so it's not reserved anymore */
2103 if (styles[i] & LBS_NODATA)
2105 ret = SendMessageA(listbox, LB_SETCOUNT, items_size - 1, 0);
2106 ok(ret == 0, "unexpected return value %d\n", ret);
2108 else
2110 for (j = 0; j < items_size - 1; j++)
2112 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
2113 ok(ret == j, "expected %d, got %d\n", j, ret);
2117 /* we still have one more reserved slot, so it doesn't grow yet */
2118 ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
2119 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2121 /* fill the slot and check again, it should grow this time */
2122 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
2123 ok(ret == items_size - 1, "expected %d, got %d\n", items_size - 1, ret);
2124 ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
2125 ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
2126 ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
2127 ok(ret > items_size, "expected it to grow past %d, got %d\n", items_size, ret);
2129 DestroyWindow(listbox);
2131 DestroyWindow(parent);
2134 static void test_missing_lbuttonup(void)
2136 HWND listbox, parent, capture;
2138 parent = create_parent();
2139 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
2141 /* Send button down without a corresponding button up */
2142 SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(10, 10));
2143 capture = GetCapture();
2144 ok(capture == listbox, "got %p expected %p\n", capture, listbox);
2146 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */
2147 got_selchange = 0;
2148 SetFocus(NULL);
2149 capture = GetCapture();
2150 ok(capture == NULL, "got %p\n", capture);
2151 ok(got_selchange, "got %d\n", got_selchange);
2153 DestroyWindow(listbox);
2154 DestroyWindow(parent);
2157 static void test_extents(void)
2159 HWND listbox, parent;
2160 SCROLLINFO sinfo;
2161 DWORD res;
2162 BOOL br;
2164 parent = create_parent();
2166 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
2168 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2169 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
2171 sinfo.cbSize = sizeof(sinfo);
2172 sinfo.fMask = SIF_RANGE;
2173 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2174 ok(br == TRUE, "GetScrollInfo failed\n");
2175 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2176 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
2177 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2178 "List box should not have a horizontal scroll bar\n");
2180 /* horizontal extent < width */
2181 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
2183 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2184 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
2186 sinfo.cbSize = sizeof(sinfo);
2187 sinfo.fMask = SIF_RANGE;
2188 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2189 ok(br == TRUE, "GetScrollInfo failed\n");
2190 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2191 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
2192 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2193 "List box should not have a horizontal scroll bar\n");
2195 /* horizontal extent > width */
2196 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
2198 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2199 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
2201 sinfo.cbSize = sizeof(sinfo);
2202 sinfo.fMask = SIF_RANGE;
2203 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2204 ok(br == TRUE, "GetScrollInfo failed\n");
2205 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2206 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
2207 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2208 "List box should not have a horizontal scroll bar\n");
2210 DestroyWindow(listbox);
2212 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL, parent);
2214 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2215 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
2217 sinfo.cbSize = sizeof(sinfo);
2218 sinfo.fMask = SIF_RANGE;
2219 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2220 ok(br == TRUE, "GetScrollInfo failed\n");
2221 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2222 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
2223 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2224 "List box should not have a horizontal scroll bar\n");
2226 /* horizontal extent < width */
2227 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
2229 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2230 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
2232 sinfo.cbSize = sizeof(sinfo);
2233 sinfo.fMask = SIF_RANGE;
2234 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2235 ok(br == TRUE, "GetScrollInfo failed\n");
2236 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2237 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
2238 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2239 "List box should not have a horizontal scroll bar\n");
2241 /* horizontal extent > width */
2242 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
2244 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2245 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
2247 sinfo.cbSize = sizeof(sinfo);
2248 sinfo.fMask = SIF_RANGE;
2249 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2250 ok(br == TRUE, "GetScrollInfo failed\n");
2251 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2252 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
2253 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2254 "List box should have a horizontal scroll bar\n");
2256 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
2258 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2259 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
2261 sinfo.cbSize = sizeof(sinfo);
2262 sinfo.fMask = SIF_RANGE;
2263 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2264 ok(br == TRUE, "GetScrollInfo failed\n");
2265 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2266 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
2267 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
2268 "List box should not have a horizontal scroll bar\n");
2270 DestroyWindow(listbox);
2273 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL | LBS_DISABLENOSCROLL, parent);
2275 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2276 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
2278 sinfo.cbSize = sizeof(sinfo);
2279 sinfo.fMask = SIF_RANGE;
2280 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2281 ok(br == TRUE, "GetScrollInfo failed\n");
2282 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2283 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
2284 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2285 "List box should have a horizontal scroll bar\n");
2287 /* horizontal extent < width */
2288 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
2290 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2291 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
2293 sinfo.cbSize = sizeof(sinfo);
2294 sinfo.fMask = SIF_RANGE;
2295 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2296 ok(br == TRUE, "GetScrollInfo failed\n");
2297 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2298 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
2299 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2300 "List box should have a horizontal scroll bar\n");
2302 /* horizontal extent > width */
2303 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
2305 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2306 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
2308 sinfo.cbSize = sizeof(sinfo);
2309 sinfo.fMask = SIF_RANGE;
2310 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2311 ok(br == TRUE, "GetScrollInfo failed\n");
2312 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2313 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
2314 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2315 "List box should have a horizontal scroll bar\n");
2317 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
2319 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2320 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
2322 sinfo.cbSize = sizeof(sinfo);
2323 sinfo.fMask = SIF_RANGE;
2324 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2325 ok(br == TRUE, "GetScrollInfo failed\n");
2326 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2327 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
2328 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2329 "List box should have a horizontal scroll bar\n");
2331 DestroyWindow(listbox);
2333 DestroyWindow(parent);
2336 static void test_listbox(void)
2338 static const struct listbox_test SS =
2339 /* {add_style} */
2340 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2341 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2342 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2343 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2345 /* {selected, anchor, caret, selcount}{TODO fields} */
2346 static const struct listbox_test SS_NS =
2347 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2348 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2349 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2350 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2352 static const struct listbox_test MS =
2353 {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
2354 { 1, 1, 1, 1}, {0,0,0,0},
2355 { 2, 1, 2, 1}, {0,0,0,0},
2356 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2358 static const struct listbox_test MS_NS =
2359 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2360 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2361 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2362 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2364 static const struct listbox_test ES =
2365 {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
2366 { 1, 1, 1, 1}, {0,0,0,0},
2367 { 2, 2, 2, 1}, {0,0,0,0},
2368 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2370 static const struct listbox_test ES_NS =
2371 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2372 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2373 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2374 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2376 static const struct listbox_test EMS =
2377 {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
2378 { 1, 1, 1, 1}, {0,0,0,0},
2379 { 2, 2, 2, 1}, {0,0,0,0},
2380 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2382 static const struct listbox_test EMS_NS =
2383 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2384 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2385 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2386 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2388 run_test(0, SS);
2389 run_test(LBS_NOSEL, SS_NS);
2390 run_test(LBS_MULTIPLESEL, MS);
2391 run_test(LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
2392 run_test(LBS_EXTENDEDSEL, ES);
2393 run_test(LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
2394 run_test(LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
2395 run_test(LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
2397 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED, SS);
2398 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOSEL, SS_NS);
2399 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL, MS);
2400 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
2401 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL, ES);
2402 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
2403 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
2404 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
2407 static const struct message lb_addstring_ownerdraw_parent_seq[] =
2409 { WM_MEASUREITEM, sent|wparam|lparam, 0x1012, 0xf30604ed },
2410 { WM_MEASUREITEM, sent|wparam|lparam, 0x1112, 0xf30604ee },
2411 { WM_MEASUREITEM, sent|wparam|lparam, 0x1212, 0xf30604ef },
2412 { 0 }
2415 static const struct message lb_addstring_sort_parent_seq[] =
2417 { WM_MEASUREITEM, sent|wparam|lparam, 0x1012, 0xf30604ed },
2418 { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ed, 0xf30604ee },
2419 { WM_MEASUREITEM, sent|wparam|lparam, 0x1112, 0xf30604ee },
2420 { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ed, 0xf30604ef },
2421 { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ee, 0xf30604ef },
2422 { WM_MEASUREITEM, sent|wparam|lparam, 0x1212, 0xf30604ef },
2423 { 0 }
2426 static const struct message empty_seq[] =
2428 { 0 }
2431 static void test_WM_MEASUREITEM(void)
2433 HWND parent, listbox;
2434 LRESULT data, ret;
2436 parent = create_parent();
2437 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE, parent);
2439 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
2440 ok(data == (LRESULT)strings[0], "data = %08lx, expected %p\n", data, strings[0]);
2441 DestroyWindow(parent);
2443 parent = create_parent();
2444 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS, parent);
2446 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
2447 ok(!data, "data = %08lx\n", data);
2449 /* LBS_HASSTRINGS */
2450 parent = create_parent();
2451 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
2452 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE,
2453 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
2455 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2457 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
2458 ok(ret == 0, "expected 0, got %ld\n", ret);
2459 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
2460 ok(ret == 1, "expected 1, got %ld\n", ret);
2461 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
2462 ok(ret == 2, "expected 2, got %ld\n", ret);
2464 ok_sequence(sequences, PARENT_SEQ_INDEX, lb_addstring_ownerdraw_parent_seq,
2465 "LB_ADDSTRING (LBS_HASSTRINGS, ownerdraw)", FALSE);
2466 DestroyWindow(listbox);
2468 /* LBS_SORT, no LBS_HASSTRINGS */
2469 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
2470 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT | WS_VISIBLE,
2471 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
2473 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2475 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
2476 ok(ret == 0, "expected 0, got %ld\n", ret);
2477 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
2478 ok(ret == 1, "expected 1, got %ld\n", ret);
2479 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
2480 ok(ret == 2, "expected 2, got %ld\n", ret);
2482 ok_sequence(sequences, PARENT_SEQ_INDEX, lb_addstring_sort_parent_seq, "LB_ADDSTRING (LBS_SORT)", FALSE);
2483 DestroyWindow(listbox);
2485 /* LBS_HASSTRINGS */
2486 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
2487 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | WS_VISIBLE,
2488 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
2490 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2492 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
2493 ok(ret == 0, "expected 0, got %ld\n", ret);
2494 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
2495 ok(ret == 1, "expected 1, got %ld\n", ret);
2496 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
2497 ok(ret == 2, "expected 2, got %ld\n", ret);
2499 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "LB_ADDSTRING (LBS_HASSTRINGS)", FALSE);
2500 DestroyWindow(listbox);
2502 /* LBS_HASSTRINGS, LBS_SORT */
2503 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
2504 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | LBS_SORT | WS_VISIBLE,
2505 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
2507 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2509 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
2510 ok(ret == 0, "expected 0, got %ld\n", ret);
2511 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
2512 ok(ret == 0, "expected 0, got %ld\n", ret);
2513 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
2514 ok(ret == 1, "expected 1, got %ld\n", ret);
2516 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "LB_ADDSTRING (LBS_HASSTRINGS, LBS_SORT)", FALSE);
2517 DestroyWindow(listbox);
2519 DestroyWindow(parent);
2522 static void test_LBS_NODATA(void)
2524 static const DWORD invalid_styles[] =
2527 LBS_OWNERDRAWVARIABLE,
2528 LBS_SORT,
2529 LBS_HASSTRINGS,
2530 LBS_OWNERDRAWFIXED | LBS_SORT,
2531 LBS_OWNERDRAWFIXED | LBS_HASSTRINGS,
2533 static const UINT invalid_idx[] = { -2, 2 };
2534 static const UINT valid_idx[] = { 0, 1 };
2535 static const ULONG_PTR zero_data;
2536 HWND listbox, parent;
2537 INT ret, text_len;
2538 unsigned int i;
2539 ULONG_PTR data;
2540 BOOL is_wow64;
2542 listbox = CreateWindowA(WC_LISTBOXA, "TestList", LBS_NODATA | LBS_OWNERDRAWFIXED | WS_VISIBLE,
2543 0, 0, 100, 100, NULL, NULL, NULL, 0);
2544 ok(listbox != NULL, "Failed to create ListBox window.\n");
2546 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
2547 ok(ret == 0, "Unexpected return value %d.\n", ret);
2548 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
2549 ok(ret == 1, "Unexpected return value %d.\n", ret);
2550 ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
2551 ok(ret == 2, "Unexpected return value %d.\n", ret);
2553 /* Invalid indices. */
2554 for (i = 0; i < ARRAY_SIZE(invalid_idx); ++i)
2556 ret = SendMessageA(listbox, LB_SETITEMDATA, invalid_idx[i], 42);
2557 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2558 ret = SendMessageA(listbox, LB_GETTEXTLEN, invalid_idx[i], 0);
2559 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2560 if (ret == LB_ERR)
2562 ret = SendMessageA(listbox, LB_GETTEXT, invalid_idx[i], (LPARAM)&data);
2563 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2565 ret = SendMessageA(listbox, LB_GETITEMDATA, invalid_idx[i], 0);
2566 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2569 IsWow64Process(GetCurrentProcess(), &is_wow64);
2570 #ifdef _WIN64
2571 text_len = 8;
2572 #else
2573 text_len = is_wow64 ? 8 : 4;
2574 #endif
2576 /* Valid indices. */
2577 for (i = 0; i < ARRAY_SIZE(valid_idx); ++i)
2579 ret = SendMessageA(listbox, LB_SETITEMDATA, valid_idx[i], 42);
2580 ok(ret == TRUE, "Unexpected return value %d.\n", ret);
2581 ret = SendMessageA(listbox, LB_GETTEXTLEN, valid_idx[i], 0);
2582 todo_wine_if(is_wow64)
2583 ok(ret == text_len, "Unexpected return value %d.\n", ret);
2585 memset(&data, 0xee, sizeof(data));
2586 ret = SendMessageA(listbox, LB_GETTEXT, valid_idx[i], (LPARAM)&data);
2587 ok(ret == sizeof(data), "Unexpected return value %d.\n", ret);
2588 ok(!memcmp(&data, &zero_data, sizeof(data)), "Unexpected item data.\n");
2590 ret = SendMessageA(listbox, LB_GETITEMDATA, valid_idx[i], 0);
2591 ok(ret == 0, "Unexpected return value %d.\n", ret);
2594 /* More messages that don't work with LBS_NODATA. */
2595 ret = SendMessageA(listbox, LB_FINDSTRING, 1, 0);
2596 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2597 ret = SendMessageA(listbox, LB_FINDSTRING, 1, 42);
2598 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2599 ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 0);
2600 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2601 ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 42);
2602 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2603 ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 0);
2604 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2605 ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 42);
2606 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2608 DestroyWindow(listbox);
2610 /* Invalid window style combinations. */
2611 parent = create_parent();
2612 ok(parent != NULL, "Failed to create parent window.\n");
2614 for (i = 0; i < ARRAY_SIZE(invalid_styles); ++i)
2616 DWORD style;
2618 listbox = CreateWindowA(WC_LISTBOXA, "TestList", LBS_NODATA | WS_CHILD | invalid_styles[i],
2619 0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0);
2620 ok(listbox != NULL, "Failed to create a listbox.\n");
2622 style = GetWindowLongA(listbox, GWL_STYLE);
2623 ok((style & invalid_styles[i]) == invalid_styles[i], "%u: unexpected window styles %#x.\n", i, style);
2624 ret = SendMessageA(listbox, LB_SETCOUNT, 100, 0);
2625 ok(ret == LB_ERR, "%u: unexpected return value %d.\n", i, ret);
2626 DestroyWindow(listbox);
2629 DestroyWindow(parent);
2632 START_TEST(listbox)
2634 ULONG_PTR ctx_cookie;
2635 HANDLE hCtx;
2637 if (!load_v6_module(&ctx_cookie, &hCtx))
2638 return;
2640 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2642 test_listbox();
2643 test_item_height();
2644 test_ownerdraw();
2645 test_LB_SELITEMRANGE();
2646 test_LB_SETCURSEL();
2647 test_listbox_height();
2648 test_changing_selection_styles();
2649 test_itemfrompoint();
2650 test_listbox_item_data();
2651 test_listbox_LB_DIR();
2652 test_listbox_dlgdir();
2653 test_set_count();
2654 test_init_storage();
2655 test_GetListBoxInfo();
2656 test_missing_lbuttonup();
2657 test_extents();
2658 test_WM_MEASUREITEM();
2659 test_LB_SETSEL();
2660 test_LBS_NODATA();
2662 unload_v6_module(ctx_cookie, hCtx);