comctl32/tests: Add some tests for LBS_NODATA.
[wine.git] / dlls / comctl32 / tests / listbox.c
blob387660d1609cc8087d1e3495e6d1db14c010f858
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 PARENT_SEQ_INDEX,
38 NUM_MSG_SEQUENCES
41 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
43 /* encoded MEASUREITEMSTRUCT into a WPARAM */
44 typedef struct
46 union
48 struct
50 UINT CtlType : 4;
51 UINT CtlID : 4;
52 UINT itemID : 4;
53 UINT wParam : 20;
54 } item;
55 WPARAM wp;
56 } u;
57 } MEASURE_ITEM_STRUCT;
59 static unsigned hash_Ly_W(const WCHAR *str)
61 unsigned hash = 0;
63 for (; *str; str++)
64 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
66 return hash;
69 static unsigned hash_Ly(const char *str)
71 unsigned hash = 0;
73 for (; *str; str++)
74 hash = hash * 1664525u + (unsigned char)(*str) + 1013904223u;
76 return hash;
79 static const char * const strings[4] = {
80 "First added",
81 "Second added",
82 "Third added",
83 "Fourth added which is very long because at some time we only had a 256 byte character buffer and "
84 "that was overflowing in one of those applications that had a common dialog file open box and tried "
85 "to add a 300 characters long custom filter string which of course the code did not like and crashed. "
86 "Just make sure this string is longer than 256 characters."
89 static const char BAD_EXTENSION[] = "*.badtxt";
91 #define ID_LISTBOX 1
93 static HWND create_listbox(DWORD add_style, HWND parent)
95 INT_PTR ctl_id = 0;
96 HWND handle;
98 if (parent)
99 ctl_id = ID_LISTBOX;
101 handle = CreateWindowA(WC_LISTBOXA, "TestList", (LBS_STANDARD & ~LBS_SORT) | add_style, 0, 0, 100, 100,
102 parent, (HMENU)ctl_id, NULL, 0);
103 ok(handle != NULL, "Failed to create listbox window.\n");
105 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[0]);
106 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[1]);
107 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[2]);
108 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[3]);
110 return handle;
113 struct listbox_prop
115 DWORD add_style;
118 struct listbox_stat
120 int selected, anchor, caret, selcount;
123 struct listbox_test
125 struct listbox_stat init, init_todo;
126 struct listbox_stat click, click_todo;
127 struct listbox_stat step, step_todo;
128 struct listbox_stat sel, sel_todo;
131 static void listbox_query(HWND handle, struct listbox_stat *results)
133 results->selected = SendMessageA(handle, LB_GETCURSEL, 0, 0);
134 results->anchor = SendMessageA(handle, LB_GETANCHORINDEX, 0, 0);
135 results->caret = SendMessageA(handle, LB_GETCARETINDEX, 0, 0);
136 results->selcount = SendMessageA(handle, LB_GETSELCOUNT, 0, 0);
139 static void buttonpress(HWND handle, WORD x, WORD y)
141 LPARAM lp = x + (y << 16);
143 SendMessageA(handle, WM_LBUTTONDOWN, MK_LBUTTON, lp);
144 SendMessageA(handle, WM_LBUTTONUP, 0, lp);
147 static void keypress(HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
149 LPARAM lp = 1 + (scancode << 16) + (extended ? KEYEVENTF_EXTENDEDKEY : 0);
151 SendMessageA(handle, WM_KEYDOWN, keycode, lp);
152 SendMessageA(handle, WM_KEYUP , keycode, lp | 0xc000000);
155 #define listbox_field_ok(t, s, f, got) \
156 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
157 ": expected %d, got %d\n", style, t.s.f, got.f)
159 #define listbox_todo_field_ok(t, s, f, got) \
160 todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
162 #define listbox_ok(t, s, got) \
163 listbox_todo_field_ok(t, s, selected, got); \
164 listbox_todo_field_ok(t, s, anchor, got); \
165 listbox_todo_field_ok(t, s, caret, got); \
166 listbox_todo_field_ok(t, s, selcount, got)
168 static void run_test(DWORD style, const struct listbox_test test)
170 struct listbox_stat answer;
171 RECT second_item;
172 int i, res;
173 HWND hLB;
175 hLB = create_listbox (style, 0);
177 listbox_query (hLB, &answer);
178 listbox_ok (test, init, answer);
180 SendMessageA(hLB, LB_GETITEMRECT, 1, (LPARAM) &second_item);
181 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
183 listbox_query(hLB, &answer);
184 listbox_ok(test, click, answer);
186 keypress(hLB, VK_DOWN, 0x50, TRUE);
188 listbox_query(hLB, &answer);
189 listbox_ok(test, step, answer);
191 DestroyWindow(hLB);
193 hLB = create_listbox(style, 0);
195 SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
196 listbox_query(hLB, &answer);
197 listbox_ok(test, sel, answer);
199 for (i = 0; i < 4 && !(style & LBS_NODATA); i++)
201 DWORD size = SendMessageA(hLB, LB_GETTEXTLEN, i, 0);
202 int resA, resW;
203 WCHAR *txtw;
204 CHAR *txt;
206 txt = heap_alloc_zero(size + 1);
207 resA = SendMessageA(hLB, LB_GETTEXT, i, (LPARAM)txt);
208 ok(!strcmp(txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
210 txtw = heap_alloc_zero((size + 1) * sizeof(*txtw));
211 resW = SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
212 ok(resA == resW, "Unexpected text length.\n");
213 WideCharToMultiByte(CP_ACP, 0, txtw, -1, txt, size, NULL, NULL);
214 ok(!strcmp (txt, strings[i]), "Unexpected string for item %d, %s vs %s.\n", i, txt, strings[i]);
216 heap_free(txtw);
217 heap_free(txt);
220 /* Confirm the count of items, and that an invalid delete does not remove anything */
221 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
222 ok(res == 4, "Expected 4 items, got %d\n", res);
223 res = SendMessageA(hLB, LB_DELETESTRING, -1, 0);
224 ok(res == LB_ERR, "Expected LB_ERR items, got %d\n", res);
225 res = SendMessageA(hLB, LB_DELETESTRING, 4, 0);
226 ok(res == LB_ERR, "Expected LB_ERR items, got %d\n", res);
227 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
228 ok(res == 4, "Expected 4 items, got %d\n", res);
230 DestroyWindow(hLB);
233 static void test_item_height(void)
235 INT itemHeight;
236 TEXTMETRICA tm;
237 HFONT font;
238 HWND hLB;
239 HDC hdc;
241 hLB = create_listbox (0, 0);
242 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n");
243 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n");
244 ok (GetTextMetricsA( hdc, &tm ), "Can't read font metrics\n");
245 ReleaseDC( hLB, hdc);
247 ok (SendMessageA(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
249 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
250 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight);
252 DestroyWindow (hLB);
254 hLB = CreateWindowA(WC_LISTBOXA, "TestList", LBS_OWNERDRAWVARIABLE, 0, 0, 100, 100, NULL, NULL, NULL, 0);
256 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
257 ok(itemHeight > 0 && itemHeight <= tm.tmHeight, "Unexpected item height %d, expected %d.\n",
258 itemHeight, tm.tmHeight);
259 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 5, 0);
260 ok(itemHeight > 0 && itemHeight <= tm.tmHeight, "Unexpected item height %d, expected %d.\n",
261 itemHeight, tm.tmHeight);
262 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, -5, 0);
263 ok(itemHeight > 0 && itemHeight <= tm.tmHeight, "Unexpected item height %d, expected %d.\n",
264 itemHeight, tm.tmHeight);
266 DestroyWindow (hLB);
269 static int got_selchange;
271 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
273 static LONG defwndproc_counter = 0;
274 struct message m = { 0 };
275 LRESULT ret;
277 m.message = msg;
278 m.flags = sent|wparam|lparam;
279 if (defwndproc_counter) m.flags |= defwinproc;
280 m.wParam = wParam;
281 m.lParam = lParam;
283 switch (msg)
285 case WM_MEASUREITEM:
287 MEASUREITEMSTRUCT *mis = (void *)lParam;
288 BOOL is_unicode_data = FALSE;
289 MEASURE_ITEM_STRUCT mi;
291 if (mis->CtlType == ODT_LISTBOX)
293 HWND ctrl = GetDlgItem(hwnd, mis->CtlID);
294 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
297 mi.u.wp = 0;
298 mi.u.item.CtlType = mis->CtlType;
299 mi.u.item.CtlID = mis->CtlID;
300 mi.u.item.itemID = mis->itemID;
301 mi.u.item.wParam = wParam;
303 m.wParam = mi.u.wp;
304 if (is_unicode_data)
305 m.lParam = mis->itemData ? hash_Ly_W((const WCHAR *)mis->itemData) : 0;
306 else
307 m.lParam = mis->itemData ? hash_Ly((const char *)mis->itemData) : 0;
308 add_message(sequences, PARENT_SEQ_INDEX, &m);
310 ok(wParam == mis->CtlID, "got wParam=%08lx, expected %08x\n", wParam, mis->CtlID);
311 ok(mis->CtlType == ODT_LISTBOX, "mi->CtlType = %u\n", mis->CtlType);
312 ok(mis->CtlID == 1, "mi->CtlID = %u\n", mis->CtlID);
313 ok(mis->itemHeight, "mi->itemHeight = 0\n");
315 break;
317 case WM_COMPAREITEM:
319 COMPAREITEMSTRUCT *cis = (COMPAREITEMSTRUCT *)lParam;
320 HWND ctrl = GetDlgItem(hwnd, cis->CtlID);
321 BOOL is_unicode_data = TRUE;
323 ok(wParam == cis->CtlID, "expected %#x, got %#lx\n", cis->CtlID, wParam);
324 ok(cis->hwndItem == ctrl, "expected %p, got %p\n", ctrl, cis->hwndItem);
325 ok((int)cis->itemID1 >= 0, "expected >= 0, got %d\n", cis->itemID1);
326 ok((int)cis->itemID2 == -1, "expected -1, got %d\n", cis->itemID2);
328 if (cis->CtlType == ODT_LISTBOX)
329 is_unicode_data = GetWindowLongA(ctrl, GWL_STYLE) & LBS_HASSTRINGS;
331 if (is_unicode_data)
333 m.wParam = cis->itemData1 ? hash_Ly_W((const WCHAR *)cis->itemData1) : 0;
334 m.lParam = cis->itemData2 ? hash_Ly_W((const WCHAR *)cis->itemData2) : 0;
336 else
338 m.wParam = cis->itemData1 ? hash_Ly((const char *)cis->itemData1) : 0;
339 m.lParam = cis->itemData2 ? hash_Ly((const char *)cis->itemData2) : 0;
341 add_message(sequences, PARENT_SEQ_INDEX, &m);
342 break;
344 case WM_DRAWITEM:
346 RECT rc_item, rc_client, rc_clip;
347 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam;
349 ok(wParam == dis->CtlID, "got wParam=%08lx instead of %08x\n", wParam, dis->CtlID);
350 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
352 GetClientRect(dis->hwndItem, &rc_client);
353 GetClipBox(dis->hDC, &rc_clip);
354 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip),
355 "client rect of the listbox should be equal to the clip box,"
356 "or the clip box should be empty\n");
358 SendMessageA(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
359 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
361 break;
364 case WM_COMMAND:
365 if (HIWORD( wParam ) == LBN_SELCHANGE) got_selchange++;
366 break;
368 default:
369 break;
372 defwndproc_counter++;
373 ret = DefWindowProcA(hwnd, msg, wParam, lParam);
374 defwndproc_counter--;
376 return msg == WM_COMPAREITEM ? -1 : ret;
379 static HWND create_parent( void )
381 static ATOM class;
382 WNDCLASSA cls;
384 if (!class)
386 cls.style = 0;
387 cls.lpfnWndProc = main_window_proc;
388 cls.cbClsExtra = 0;
389 cls.cbWndExtra = 0;
390 cls.hInstance = GetModuleHandleA(NULL);
391 cls.hIcon = 0;
392 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
393 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
394 cls.lpszMenuName = NULL;
395 cls.lpszClassName = "main_window_class";
396 class = RegisterClassA( &cls );
399 return CreateWindowExA(0, "main_window_class", NULL, WS_POPUP | WS_VISIBLE, 100, 100, 400, 400, GetDesktopWindow(),
400 0, GetModuleHandleA(NULL), NULL);
403 static void test_ownerdraw(void)
405 HWND parent, hLB;
406 INT ret;
407 RECT rc;
409 parent = create_parent();
410 ok(parent != NULL, "Failed to create parent window.\n");
412 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
413 ok(hLB != NULL, "Failed to create listbox window.\n");
415 SetForegroundWindow(hLB);
416 UpdateWindow(hLB);
418 /* make height short enough */
419 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
420 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1, SWP_NOZORDER | SWP_NOMOVE);
422 /* make 0 item invisible */
423 SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
424 ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
425 ok(ret == 1, "wrong top index %d\n", ret);
427 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
428 ok(!IsRectEmpty(&rc), "empty item rect\n");
429 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
431 DestroyWindow(hLB);
433 /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
434 hLB = CreateWindowA(WC_LISTBOXA, "TestList", LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE, 0, 0, 100, 100,
435 NULL, NULL, NULL, 0);
436 ok(hLB != NULL, "last error 0x%08x\n", GetLastError());
438 ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
439 ok(ret == 0, "Unexpected return value %d.\n", ret);
440 ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
441 ok(ret == 1, "Unexpected return value %d.\n", ret);
443 ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 13);
444 ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
446 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
447 ok(ret == 13, "Unexpected item height %d.\n", ret);
449 ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 1, 42);
450 ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
452 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
453 todo_wine
454 ok(ret == 42, "Unexpected item height %d.\n", ret);
456 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 1, 0);
457 ok(ret == 42, "Unexpected item height %d.\n", ret);
459 DestroyWindow (hLB);
461 DestroyWindow(parent);
464 #define listbox_test_query(exp, got) \
465 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
466 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
467 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
468 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
470 static void test_LB_SELITEMRANGE(void)
472 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
473 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
474 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
475 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
476 struct listbox_stat answer;
477 HWND hLB;
478 INT ret;
480 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
481 ok(hLB != NULL, "Failed to create listbox window.\n");
483 listbox_query(hLB, &answer);
484 listbox_test_query(test_nosel, answer);
486 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
487 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
488 listbox_query(hLB, &answer);
489 listbox_test_query(test_1, answer);
491 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
492 listbox_query(hLB, &answer);
493 listbox_test_query(test_nosel, answer);
495 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
496 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
497 listbox_query(hLB, &answer);
498 listbox_test_query(test_3, answer);
500 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
501 listbox_query(hLB, &answer);
502 listbox_test_query(test_nosel, answer);
504 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
505 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
506 listbox_query(hLB, &answer);
507 listbox_test_query(test_nosel, answer);
509 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
510 listbox_query(hLB, &answer);
511 listbox_test_query(test_nosel, answer);
513 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
514 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
515 listbox_query(hLB, &answer);
516 listbox_test_query(test_1, answer);
518 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
519 listbox_query(hLB, &answer);
520 listbox_test_query(test_nosel, answer);
522 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
523 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
524 listbox_query(hLB, &answer);
525 listbox_test_query(test_nosel, answer);
527 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
528 listbox_query(hLB, &answer);
529 listbox_test_query(test_nosel, answer);
531 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
532 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
533 listbox_query(hLB, &answer);
534 listbox_test_query(test_2, answer);
536 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
537 listbox_query(hLB, &answer);
538 listbox_test_query(test_nosel, answer);
540 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
541 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
542 listbox_query(hLB, &answer);
543 listbox_test_query(test_2, answer);
545 DestroyWindow(hLB);
548 static void test_LB_SETCURSEL(void)
550 HWND parent, hLB;
551 INT ret;
553 parent = create_parent();
554 ok(parent != NULL, "Failed to create parent window.\n");
556 hLB = create_listbox(LBS_NOINTEGRALHEIGHT | WS_CHILD, parent);
557 ok(hLB != NULL, "Failed to create listbox.\n");
559 SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32);
561 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
562 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
564 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
565 ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret);
566 ret = GetScrollPos(hLB, SB_VERT);
567 ok(ret == 0, "expected vscroll 0, got %d\n", ret);
569 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
570 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
572 ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0);
573 ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret);
574 ret = GetScrollPos(hLB, SB_VERT);
575 ok(ret == 1, "expected vscroll 1, got %d\n", ret);
577 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
578 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
580 DestroyWindow(hLB);
582 hLB = create_listbox(0, 0);
583 ok(hLB != NULL, "Failed to create ListBox window.\n");
585 ret = SendMessageA(hLB, LB_SETCURSEL, 1, 0);
586 ok(ret == 1, "Unexpected return value %d.\n", ret);
588 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
589 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
591 DestroyWindow(hLB);
593 /* LBS_EXTENDEDSEL */
594 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
595 ok(hLB != NULL, "Failed to create listbox.\n");
597 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
598 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
600 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
601 ok(ret == -1, "LB_SETCURSEL returned %d instead of 2\n", ret);
603 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
604 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
606 DestroyWindow(hLB);
608 /* LBS_MULTIPLESEL */
609 hLB = create_listbox(LBS_MULTIPLESEL, 0);
610 ok(hLB != NULL, "Failed to create listbox.\n");
612 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
613 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
615 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
616 ok(ret == -1, "LB_SETCURSEL returned %d instead of 2\n", ret);
618 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
619 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
621 DestroyWindow(hLB);
624 static void test_LB_SETSEL(void)
626 HWND list;
627 int ret;
629 /* LBS_EXTENDEDSEL */
630 list = create_listbox(LBS_EXTENDEDSEL, 0);
631 ok(list != NULL, "Failed to create ListBox window.\n");
633 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
634 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
636 ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
637 ok(ret == 0, "Unexpected return value %d.\n", ret);
638 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
639 ok(ret == 0, "Unexpected anchor index %d.\n", ret);
641 ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
642 ok(ret == 0, "Unexpected return value %d.\n", ret);
643 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
644 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
646 ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
647 ok(ret == 0, "Unexpected return value %d.\n", ret);
648 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
649 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
651 DestroyWindow(list);
653 /* LBS_MULTIPLESEL */
654 list = create_listbox(LBS_MULTIPLESEL, 0);
655 ok(list != NULL, "Failed to create ListBox window.\n");
657 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
658 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
660 ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
661 ok(ret == 0, "Unexpected return value %d.\n", ret);
662 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
663 ok(ret == 0, "Unexpected anchor index %d.\n", ret);
665 ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
666 ok(ret == 0, "Unexpected return value %d.\n", ret);
667 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
668 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
670 ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
671 ok(ret == 0, "Unexpected return value %d.\n", ret);
672 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
673 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
675 DestroyWindow(list);
678 static void test_listbox_height(void)
680 HWND hList;
681 int r, id;
683 hList = CreateWindowA( WC_LISTBOXA, "list test", 0,
684 1, 1, 600, 100, NULL, NULL, NULL, NULL );
685 ok( hList != NULL, "failed to create listbox\n");
687 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
688 ok( id == 0, "item id wrong\n");
690 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
691 ok( r == 0, "send message failed\n");
693 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
694 ok( r == 20, "height wrong\n");
696 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
697 ok( r == -1, "send message failed\n");
699 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
700 ok( r == 20, "height wrong\n");
702 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 256, 0 ));
703 ok( r == -1, "Failed to set item height, %d.\n", r);
705 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
706 ok( r == 20, "Unexpected item height %d.\n", r);
708 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
709 ok( r == 0, "send message failed\n");
711 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
712 ok( r == 0xff, "height wrong\n");
714 DestroyWindow( hList );
717 static void test_itemfrompoint(void)
719 /* WS_POPUP is required in order to have a more accurate size calculation (
720 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
721 behavior of partially-displayed item.
723 HWND hList = CreateWindowA( WC_LISTBOXA, "list test",
724 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
725 1, 1, 600, 100, NULL, NULL, NULL, NULL );
726 ULONG r, id;
727 RECT rc;
729 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
730 ok( r == MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r );
732 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
733 ok( r == MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r );
735 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
736 ok( r == MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r );
738 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
739 ok( id == 0, "item id wrong\n");
740 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
741 ok( id == 1, "item id wrong\n");
743 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
744 ok( r == 0x1, "ret %x\n", r );
746 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
747 ok( r == MAKELPARAM(1, 1), "Unexpected ret value %#x.\n", r );
749 /* Resize control so that below assertions about sizes are valid */
750 r = SendMessageA( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
751 ok( r == 1, "ret %x\n", r);
752 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
753 ok( r != 0, "ret %x\n", r);
755 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
756 ok( id == 2, "item id wrong\n");
757 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
758 ok( id == 3, "item id wrong\n");
759 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
760 ok( id == 4, "item id wrong\n");
761 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
762 ok( id == 5, "item id wrong\n");
763 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
764 ok( id == 6, "item id wrong\n");
765 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
766 ok( id == 7, "item id wrong\n");
768 /* Set the listbox up so that id 1 is at the top, this leaves 5
769 partially visible at the bottom and 6, 7 are invisible */
771 SendMessageA( hList, LB_SETTOPINDEX, 1, 0);
772 r = SendMessageA( hList, LB_GETTOPINDEX, 0, 0);
773 ok( r == 1, "top %d\n", r);
775 r = SendMessageA( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
776 ok( r == 1, "ret %x\n", r);
777 r = SendMessageA( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
778 ok( r == 0, "ret %x\n", r);
780 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
781 ok( r == 1, "ret %x\n", r);
783 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
784 ok( r == 0x10001, "ret %x\n", r );
786 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
787 ok( r == 0x10001, "ret %x\n", r );
789 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
790 ok( r == 0x10005, "item %x\n", r );
792 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
793 ok( r == 0x10005, "item %x\n", r );
795 DestroyWindow( hList );
798 static void test_listbox_item_data(void)
800 HWND hList;
801 int r, id;
803 hList = CreateWindowA( WC_LISTBOXA, "list test", 0,
804 1, 1, 600, 100, NULL, NULL, NULL, NULL );
805 ok( hList != NULL, "failed to create listbox\n");
807 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
808 ok( id == 0, "item id wrong\n");
810 r = SendMessageA( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
811 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
813 r = SendMessageA( hList, LB_GETITEMDATA, 0, 0);
814 ok( r == 20, "get item data failed\n");
816 DestroyWindow( hList );
819 static void test_listbox_LB_DIR(void)
821 char path[MAX_PATH], curdir[MAX_PATH];
822 HWND hList;
823 int res, itemCount;
824 int itemCount_justFiles;
825 int itemCount_justDrives;
826 int itemCount_allFiles;
827 int itemCount_allDirs;
828 int i;
829 char pathBuffer[MAX_PATH];
830 char * p;
831 char driveletter;
832 const char *wildcard = "*";
833 HANDLE file;
834 BOOL ret;
836 GetCurrentDirectoryA(ARRAY_SIZE(curdir), curdir);
838 GetTempPathA(ARRAY_SIZE(path), path);
839 ret = SetCurrentDirectoryA(path);
840 ok(ret, "Failed to set current directory.\n");
842 ret = CreateDirectoryA("lb_dir_test", NULL);
843 ok(ret, "Failed to create test directory.\n");
845 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
846 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
847 CloseHandle( file );
849 /* NOTE: for this test to succeed, there must be no subdirectories
850 under the current directory. In addition, there must be at least
851 one file that fits the wildcard w*.c . Normally, the test
852 directory itself satisfies both conditions.
854 hList = CreateWindowA( WC_LISTBOXA, "list test", WS_VISIBLE|WS_POPUP,
855 1, 1, 600, 100, NULL, NULL, NULL, NULL );
856 ok(hList != NULL, "Failed to create listbox window.\n");
858 /* Test for standard usage */
860 /* This should list all the files in the test directory. */
861 strcpy(pathBuffer, wildcard);
862 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
863 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
864 if (res == -1) /* "*" wildcard doesn't work on win9x */
866 wildcard = "*.*";
867 strcpy(pathBuffer, wildcard);
868 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
870 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
872 /* There should be some content in the listbox */
873 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
874 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
875 itemCount_allFiles = itemCount;
876 ok(res + 1 == itemCount,
877 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
878 itemCount - 1, res);
880 /* This tests behavior when no files match the wildcard */
881 strcpy(pathBuffer, BAD_EXTENSION);
882 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
883 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
884 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
886 /* There should be NO content in the listbox */
887 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
888 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
891 /* This should list all the w*.c files in the test directory
892 * As of this writing, this includes win.c, winstation.c, wsprintf.c
894 strcpy(pathBuffer, "w*.c");
895 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
896 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
897 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
899 /* Path specification does NOT converted to uppercase */
900 ok (!strcmp(pathBuffer, "w*.c"),
901 "expected no change to pathBuffer, got %s\n", pathBuffer);
903 /* There should be some content in the listbox */
904 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
905 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
906 itemCount_justFiles = itemCount;
907 ok(res + 1 == itemCount,
908 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
909 itemCount - 1, res);
911 /* Every single item in the control should start with a w and end in .c */
912 for (i = 0; i < itemCount; i++)
914 memset(pathBuffer, 0, MAX_PATH);
915 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
916 p = pathBuffer + strlen(pathBuffer);
917 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
918 (*(p-1) == 'c' || *(p-1) == 'C') &&
919 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
922 /* Test DDL_DIRECTORY */
923 strcpy(pathBuffer, wildcard);
924 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
925 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
926 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
928 /* There should be some content in the listbox.
929 * All files plus "[..]"
931 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
932 itemCount_allDirs = itemCount - itemCount_allFiles;
933 ok (itemCount >= itemCount_allFiles,
934 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
935 itemCount, itemCount_allFiles);
936 ok(res + 1 == itemCount,
937 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
938 itemCount - 1, res);
940 /* This tests behavior when no files match the wildcard */
941 strcpy(pathBuffer, BAD_EXTENSION);
942 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
943 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
944 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
946 /* There should be NO content in the listbox */
947 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
948 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
950 /* Test DDL_DIRECTORY */
951 strcpy(pathBuffer, "w*.c");
952 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
953 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
954 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
956 /* There should be some content in the listbox. Since the parent directory does not
957 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
959 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
960 ok (itemCount == itemCount_justFiles,
961 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
962 itemCount, itemCount_justFiles);
963 ok(res + 1 == itemCount,
964 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
965 itemCount - 1, res);
967 /* Every single item in the control should start with a w and end in .c. */
968 for (i = 0; i < itemCount; i++)
970 memset(pathBuffer, 0, MAX_PATH);
971 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
972 p = pathBuffer + strlen(pathBuffer);
974 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
975 (*(p-1) == 'c' || *(p-1) == 'C') &&
976 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
979 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
980 strcpy(pathBuffer, wildcard);
981 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
982 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
983 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
985 /* There should be some content in the listbox. In particular, there should
986 * be at least one element before, since the string "[-c-]" should
987 * have been added. Depending on the user setting, more drives might have
988 * been added.
990 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
991 ok (itemCount >= 1,
992 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
993 itemCount, 1);
994 itemCount_justDrives = itemCount;
995 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
997 /* Every single item in the control should fit the format [-c-] */
998 for (i = 0; i < itemCount; i++)
1000 memset(pathBuffer, 0, MAX_PATH);
1001 driveletter = '\0';
1002 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1003 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1004 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1005 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1006 if (!(driveletter >= 'a' && driveletter <= 'z'))
1008 /* Correct after invalid entry is found */
1009 itemCount_justDrives--;
1013 /* This tests behavior when no files match the wildcard */
1014 strcpy(pathBuffer, BAD_EXTENSION);
1015 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1016 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1017 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1018 BAD_EXTENSION, res, itemCount_justDrives -1);
1020 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1021 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
1022 itemCount, itemCount_justDrives);
1024 /* Test DDL_DRIVES. */
1025 strcpy(pathBuffer, wildcard);
1026 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1027 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
1028 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
1030 /* There should be some content in the listbox. In particular, there should
1031 * be at least one element before, since the string "[-c-]" should
1032 * have been added. Depending on the user setting, more drives might have
1033 * been added.
1035 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1036 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
1037 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
1038 itemCount, itemCount_justDrives + itemCount_allFiles);
1039 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
1041 /* This tests behavior when no files match the wildcard */
1042 strcpy(pathBuffer, BAD_EXTENSION);
1043 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1044 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
1045 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
1046 BAD_EXTENSION, res, itemCount_justDrives -1);
1048 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1049 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1051 /* Test DDL_DRIVES. */
1052 strcpy(pathBuffer, "w*.c");
1053 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1054 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
1055 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
1057 /* There should be some content in the listbox. In particular, there should
1058 * be at least one element before, since the string "[-c-]" should
1059 * have been added. Depending on the user setting, more drives might have
1060 * been added.
1062 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1063 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
1064 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
1065 itemCount, itemCount_justDrives + itemCount_justFiles);
1066 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
1068 /* Every single item in the control should fit the format [-c-], or w*.c */
1069 for (i = 0; i < itemCount; i++)
1071 memset(pathBuffer, 0, MAX_PATH);
1072 driveletter = '\0';
1073 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1074 p = pathBuffer + strlen(pathBuffer);
1075 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1077 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1078 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1080 else
1083 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1084 (*(p-1) == 'c' || *(p-1) == 'C') &&
1085 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1089 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1090 strcpy(pathBuffer, wildcard);
1091 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1092 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1093 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
1095 /* There should be some content in the listbox. In particular, there should
1096 * be exactly the number of plain files, plus the number of mapped drives.
1098 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1099 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
1100 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1101 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
1102 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1104 /* Every single item in the control should start with a w and end in .c,
1105 * except for the "[..]" string, which should appear exactly as it is,
1106 * and the mapped drives in the format "[-X-]".
1108 for (i = 0; i < itemCount; i++)
1110 memset(pathBuffer, 0, MAX_PATH);
1111 driveletter = '\0';
1112 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1113 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1114 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1117 /* This tests behavior when no files match the wildcard */
1118 strcpy(pathBuffer, BAD_EXTENSION);
1119 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1120 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1121 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
1122 BAD_EXTENSION, res, itemCount_justDrives -1);
1124 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1125 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1127 /* Test DDL_DIRECTORY|DDL_DRIVES. */
1128 strcpy(pathBuffer, "w*.c");
1129 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1130 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1131 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
1133 /* There should be some content in the listbox. In particular, there should
1134 * be exactly the number of plain files, plus the number of mapped drives.
1136 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1137 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
1138 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1139 itemCount, itemCount_justFiles + itemCount_justDrives);
1140 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1142 /* Every single item in the control should start with a w and end in .c,
1143 * except the mapped drives in the format "[-X-]". The "[..]" directory
1144 * should not appear.
1146 for (i = 0; i < itemCount; i++)
1148 memset(pathBuffer, 0, MAX_PATH);
1149 driveletter = '\0';
1150 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1151 p = pathBuffer + strlen(pathBuffer);
1152 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1153 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1154 else
1156 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1157 (*(p-1) == 'c' || *(p-1) == 'C') &&
1158 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1161 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1162 strcpy(pathBuffer, wildcard);
1163 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1164 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1165 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n",
1166 GetLastError());
1168 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1169 ok (itemCount == itemCount_allDirs,
1170 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1171 itemCount, itemCount_allDirs);
1172 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1174 if (itemCount)
1176 memset(pathBuffer, 0, MAX_PATH);
1177 SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1178 ok( !strcmp(pathBuffer, "[..]"), "First element is %s, not [..]\n", pathBuffer);
1181 /* This tests behavior when no files match the wildcard */
1182 strcpy(pathBuffer, BAD_EXTENSION);
1183 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1184 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1185 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1186 BAD_EXTENSION, res, -1);
1188 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1189 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1192 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1193 strcpy(pathBuffer, "w*.c");
1194 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1195 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1196 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
1198 /* There should be no elements, since "[..]" does not fit w*.c */
1199 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1200 ok (itemCount == 0,
1201 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1202 itemCount, 0);
1204 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1205 strcpy(pathBuffer, wildcard);
1206 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1207 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1208 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1210 /* There should be no plain files on the listbox */
1211 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1212 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1213 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1214 itemCount, itemCount_justDrives + itemCount_allDirs);
1215 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1217 for (i = 0; i < itemCount; i++)
1219 memset(pathBuffer, 0, MAX_PATH);
1220 driveletter = '\0';
1221 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1222 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1223 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1224 else
1225 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1226 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1229 /* This tests behavior when no files match the wildcard */
1230 strcpy(pathBuffer, BAD_EXTENSION);
1231 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1232 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1233 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1234 BAD_EXTENSION, res, itemCount_justDrives -1);
1236 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1237 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1239 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1240 strcpy(pathBuffer, "w*.c");
1241 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1242 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1243 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1245 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
1246 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1247 ok (itemCount == itemCount_justDrives,
1248 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1249 itemCount, itemCount_justDrives);
1250 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1252 for (i = 0; i < itemCount; i++)
1254 memset(pathBuffer, 0, MAX_PATH);
1255 driveletter = '\0';
1256 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1257 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1258 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1260 DestroyWindow(hList);
1262 DeleteFileA( "wtest1.tmp.c" );
1263 RemoveDirectoryA("lb_dir_test");
1265 SetCurrentDirectoryA(curdir);
1268 static HWND g_listBox;
1269 static HWND g_label;
1271 #define ID_TEST_LABEL 1001
1272 #define ID_TEST_LISTBOX 1002
1274 static BOOL on_listbox_container_create(HWND hwnd, CREATESTRUCTA *lpcs)
1276 g_label = CreateWindowA(WC_STATICA, "Contents of static control before DlgDirList.",
1277 WS_CHILD | WS_VISIBLE, 10, 10, 512, 32, hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1278 if (!g_label) return FALSE;
1280 g_listBox = CreateWindowA(WC_LISTBOXA, "DlgDirList test",
1281 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL, 10, 60, 256, 256,
1282 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1283 if (!g_listBox) return FALSE;
1285 return TRUE;
1288 static LRESULT CALLBACK listbox_container_window_procA(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1290 LRESULT result = 0;
1292 switch (uiMsg)
1294 case WM_DESTROY:
1295 PostQuitMessage(0);
1296 break;
1297 case WM_CREATE:
1298 result = on_listbox_container_create(hwnd, (CREATESTRUCTA *)lParam) ? 0 : (LRESULT)-1;
1299 break;
1300 default:
1301 result = DefWindowProcA(hwnd, uiMsg, wParam, lParam);
1302 break;
1304 return result;
1307 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1309 WNDCLASSA cls;
1311 cls.style = 0;
1312 cls.cbClsExtra = 0;
1313 cls.cbWndExtra = 0;
1314 cls.hInstance = hInst;
1315 cls.hIcon = NULL;
1316 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
1317 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1318 cls.lpszMenuName = NULL;
1319 cls.lpfnWndProc = listbox_container_window_procA;
1320 cls.lpszClassName = "ListboxContainerClass";
1321 if (!RegisterClassA (&cls)) return FALSE;
1323 return TRUE;
1326 static void test_listbox_dlgdir(void)
1328 HINSTANCE hInst;
1329 HWND hWnd;
1330 int res, itemCount;
1331 int itemCount_allDirs;
1332 int itemCount_justFiles;
1333 int itemCount_justDrives;
1334 int i;
1335 char pathBuffer[MAX_PATH];
1336 char itemBuffer[MAX_PATH];
1337 char tempBuffer[MAX_PATH];
1338 char * p;
1339 char driveletter;
1340 HANDLE file;
1341 BOOL ret;
1343 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1344 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1345 CloseHandle( file );
1347 /* NOTE: for this test to succeed, there must be no subdirectories
1348 under the current directory. In addition, there must be at least
1349 one file that fits the wildcard w*.c . Normally, the test
1350 directory itself satisfies both conditions.
1353 hInst = GetModuleHandleA(0);
1354 ret = RegisterListboxWindowClass(hInst);
1355 ok(ret, "Failed to register test class.\n");
1357 hWnd = CreateWindowA("ListboxContainerClass", "ListboxContainerClass",
1358 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1359 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1360 NULL, NULL, hInst, 0);
1361 ok(hWnd != NULL, "Failed to create container window.\n");
1363 /* Test for standard usage */
1365 /* The following should be overwritten by the directory path */
1366 SendMessageA(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1368 /* This should list all the w*.c files in the test directory
1369 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1371 strcpy(pathBuffer, "w*.c");
1372 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1373 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1375 /* Path specification gets converted to uppercase */
1376 ok (!strcmp(pathBuffer, "W*.C"),
1377 "expected conversion to uppercase, got %s\n", pathBuffer);
1379 /* Loaded path should have overwritten the label text */
1380 SendMessageA(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer);
1381 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1383 /* There should be some content in the listbox */
1384 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1385 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1386 itemCount_justFiles = itemCount;
1388 /* Every single item in the control should start with a w and end in .c */
1389 for (i = 0; i < itemCount; i++)
1391 memset(pathBuffer, 0, MAX_PATH);
1392 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1393 p = pathBuffer + strlen(pathBuffer);
1394 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1395 (*(p-1) == 'c' || *(p-1) == 'C') &&
1396 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1399 /* Test behavior when no files match the wildcard */
1400 strcpy(pathBuffer, BAD_EXTENSION);
1401 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1402 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1404 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1405 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1407 /* Test DDL_DIRECTORY */
1408 strcpy(pathBuffer, "w*.c");
1409 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY);
1410 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1412 /* There should be some content in the listbox. In particular, there should
1413 * be exactly more elements than before, since the directories should
1414 * have been added.
1416 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1417 itemCount_allDirs = itemCount - itemCount_justFiles;
1418 ok (itemCount >= itemCount_justFiles, "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1419 itemCount, itemCount_justFiles);
1421 /* Every single item in the control should start with a w and end in .c,
1422 * except for the "[..]" string, which should appear exactly as it is.
1424 for (i = 0; i < itemCount; i++)
1426 memset(pathBuffer, 0, MAX_PATH);
1427 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1428 p = pathBuffer + strlen(pathBuffer);
1429 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1430 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1431 (*(p-1) == 'c' || *(p-1) == 'C') &&
1432 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1435 /* Test behavior when no files match the wildcard */
1436 strcpy(pathBuffer, BAD_EXTENSION);
1437 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY);
1438 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1440 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1441 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1442 itemCount_allDirs, itemCount);
1443 for (i = 0; i < itemCount; i++)
1445 memset(pathBuffer, 0, MAX_PATH);
1446 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1447 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1448 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1451 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1452 strcpy(pathBuffer, "w*.c");
1453 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DRIVES);
1454 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1456 /* There should be some content in the listbox. In particular, there should
1457 * be at least one element before, since the string "[-c-]" should
1458 * have been added. Depending on the user setting, more drives might have
1459 * been added.
1461 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1462 ok (itemCount >= 1,
1463 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1464 itemCount, 1);
1465 itemCount_justDrives = itemCount;
1467 /* Every single item in the control should fit the format [-c-] */
1468 for (i = 0; i < itemCount; i++)
1470 memset(pathBuffer, 0, MAX_PATH);
1471 driveletter = '\0';
1472 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1473 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1474 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1475 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1476 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1477 /* Correct after invalid entry is found */
1478 trace("removing count of invalid entry %s\n", pathBuffer);
1479 itemCount_justDrives--;
1483 /* Test behavior when no files match the wildcard */
1484 strcpy(pathBuffer, BAD_EXTENSION);
1485 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DRIVES);
1486 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1488 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1489 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1491 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1492 strcpy(pathBuffer, "w*.c");
1493 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES);
1494 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1496 /* There should be some content in the listbox. In particular, there should
1497 * be exactly the number of plain files, plus the number of mapped drives,
1498 * plus one "[..]"
1500 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1501 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1502 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1503 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1505 /* Every single item in the control should start with a w and end in .c,
1506 * except for the "[..]" string, which should appear exactly as it is,
1507 * and the mapped drives in the format "[-X-]".
1509 for (i = 0; i < itemCount; i++)
1511 memset(pathBuffer, 0, MAX_PATH);
1512 driveletter = '\0';
1513 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1514 p = pathBuffer + strlen(pathBuffer);
1515 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1516 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1517 else
1518 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1519 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1520 (*(p-1) == 'c' || *(p-1) == 'C') &&
1521 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1524 /* Test behavior when no files match the wildcard */
1525 strcpy(pathBuffer, BAD_EXTENSION);
1526 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES);
1527 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1529 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1530 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1531 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1532 itemCount_justDrives + itemCount_allDirs, itemCount);
1534 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1535 strcpy(pathBuffer, "w*.c");
1536 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_EXCLUSIVE);
1537 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1539 /* There should be exactly one element: "[..]" */
1540 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1541 ok (itemCount == itemCount_allDirs,
1542 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1543 itemCount, itemCount_allDirs);
1545 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1547 memset(pathBuffer, 0, MAX_PATH);
1548 SendMessageA(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1549 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1552 /* Test behavior when no files match the wildcard */
1553 strcpy(pathBuffer, BAD_EXTENSION);
1554 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_EXCLUSIVE);
1555 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1557 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1558 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1560 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1561 strcpy(pathBuffer, "w*.c");
1562 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1563 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1565 /* There should be no plain files on the listbox */
1566 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1567 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1568 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1569 itemCount, itemCount_justDrives + itemCount_allDirs);
1571 for (i = 0; i < itemCount; i++)
1573 memset(pathBuffer, 0, MAX_PATH);
1574 driveletter = '\0';
1575 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1576 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1)
1577 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1578 else
1579 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1580 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1583 /* Test behavior when no files match the wildcard */
1584 strcpy(pathBuffer, BAD_EXTENSION);
1585 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1586 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1588 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1589 ok (itemCount == itemCount_justDrives + itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1591 /* Now test DlgDirSelectEx() in normal operation */
1592 /* Fill with everything - drives, directory and all plain files. */
1593 strcpy(pathBuffer, "*");
1594 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES);
1595 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1597 SendMessageA(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1598 memset(pathBuffer, 0, MAX_PATH);
1599 SetLastError(0xdeadbeef);
1600 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1601 ok (GetLastError() == 0xdeadbeef,
1602 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1603 GetLastError());
1604 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1605 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1607 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1609 /* Test proper drive/dir/file recognition */
1610 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1611 for (i = 0; i < itemCount; i++)
1613 memset(itemBuffer, 0, MAX_PATH);
1614 memset(pathBuffer, 0, MAX_PATH);
1615 memset(tempBuffer, 0, MAX_PATH);
1616 driveletter = '\0';
1617 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1618 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1619 ok (res == i, "SendMessageA(LB_SETCURSEL, %d) failed\n", i);
1620 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1)
1622 /* Current item is a drive letter */
1623 SetLastError(0xdeadbeef);
1624 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1625 ok (GetLastError() == 0xdeadbeef,
1626 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1627 i, GetLastError());
1628 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1630 /* For drive letters, DlgDirSelectEx tacks on a colon */
1631 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1632 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1634 else if (itemBuffer[0] == '[')
1636 /* Current item is the parent directory */
1637 SetLastError(0xdeadbeef);
1638 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1639 ok (GetLastError() == 0xdeadbeef,
1640 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1641 i, GetLastError());
1642 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1644 /* For directories, DlgDirSelectEx tacks on a backslash */
1645 p = pathBuffer + strlen(pathBuffer);
1646 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1648 tempBuffer[0] = '[';
1649 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1650 strcat(tempBuffer, "]");
1651 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1653 else
1655 /* Current item is a plain file */
1656 SetLastError(0xdeadbeef);
1657 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1658 ok (GetLastError() == 0xdeadbeef,
1659 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1660 i, GetLastError());
1661 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1663 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1664 * for example, "Makefile", which gets reported as "Makefile."
1666 strcpy(tempBuffer, itemBuffer);
1667 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1668 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1672 DeleteFileA( "wtest1.tmp.c" );
1674 /* Now test DlgDirSelectEx() in abnormal operation */
1675 /* Fill list with bogus entries, that look somewhat valid */
1676 SendMessageA(g_listBox, LB_RESETCONTENT, 0, 0);
1677 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1678 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1679 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1680 for (i = 0; i < itemCount; i++)
1682 memset(itemBuffer, 0, MAX_PATH);
1683 memset(pathBuffer, 0, MAX_PATH);
1684 memset(tempBuffer, 0, MAX_PATH);
1685 driveletter = '\0';
1686 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1687 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1688 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1689 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1)
1691 /* Current item is a drive letter */
1692 SetLastError(0xdeadbeef);
1693 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1694 ok (GetLastError() == 0xdeadbeef,
1695 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1696 i, GetLastError());
1697 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1699 /* For drive letters, DlgDirSelectEx tacks on a colon */
1700 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1701 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1703 else if (itemBuffer[0] == '[')
1705 /* Current item is the parent directory */
1706 SetLastError(0xdeadbeef);
1707 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1708 ok (GetLastError() == 0xdeadbeef,
1709 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1710 i, GetLastError());
1711 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1713 /* For directories, DlgDirSelectEx tacks on a backslash */
1714 p = pathBuffer + strlen(pathBuffer);
1715 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1717 tempBuffer[0] = '[';
1718 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1719 strcat(tempBuffer, "]");
1720 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1722 else
1724 /* Current item is a plain file */
1725 SetLastError(0xdeadbeef);
1726 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1727 ok (GetLastError() == 0xdeadbeef,
1728 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1729 i, GetLastError());
1730 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1732 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1733 * This affects for example, "Makefile", which gets reported as "Makefile."
1735 strcpy(tempBuffer, itemBuffer);
1736 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1737 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1741 /* Test behavior when loading folders from root with and without wildcard */
1742 strcpy(pathBuffer, "C:\\");
1743 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1744 ok(res, "DlgDirList failed to list C:\\ folders\n");
1745 todo_wine ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1747 strcpy(pathBuffer, "C:\\*");
1748 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1749 ok(res, "DlgDirList failed to list C:\\* folders\n");
1750 ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1752 /* Try loading files from an invalid folder */
1753 SetLastError(0xdeadbeef);
1754 strcpy(pathBuffer, "C:\\INVALID$$DIR");
1755 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1756 todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
1757 todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
1758 "GetLastError should return 0x589, got 0x%X\n",GetLastError());
1760 DestroyWindow(hWnd);
1763 static void test_set_count( void )
1765 static const DWORD styles[] =
1767 LBS_OWNERDRAWFIXED,
1768 LBS_HASSTRINGS,
1770 HWND parent, listbox;
1771 unsigned int i;
1772 LONG ret;
1773 RECT r;
1775 parent = create_parent();
1776 listbox = create_listbox( LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VISIBLE, parent );
1778 UpdateWindow( listbox );
1779 GetUpdateRect( listbox, &r, TRUE );
1780 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1782 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
1783 ok( ret == 0, "got %d\n", ret );
1784 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
1785 ok( ret == 100, "got %d\n", ret );
1787 GetUpdateRect( listbox, &r, TRUE );
1788 ok( !IsRectEmpty( &r ), "got empty rect\n");
1790 ValidateRect( listbox, NULL );
1791 GetUpdateRect( listbox, &r, TRUE );
1792 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1794 ret = SendMessageA( listbox, LB_SETCOUNT, 99, 0 );
1795 ok( ret == 0, "got %d\n", ret );
1797 GetUpdateRect( listbox, &r, TRUE );
1798 ok( !IsRectEmpty( &r ), "got empty rect\n");
1800 DestroyWindow( listbox );
1802 for (i = 0; i < ARRAY_SIZE(styles); ++i)
1804 listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent );
1806 SetLastError( 0xdeadbeef );
1807 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
1808 todo_wine_if(i == 0)
1809 ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret );
1810 todo_wine_if(i == 1)
1811 ok( GetLastError() == 0xdeadbeef, "Unexpected error %d.\n", GetLastError() );
1813 DestroyWindow( listbox );
1816 DestroyWindow( parent );
1819 static int lb_getlistboxinfo;
1821 static LRESULT WINAPI listbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1823 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
1825 if (message == LB_GETLISTBOXINFO)
1826 lb_getlistboxinfo++;
1828 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
1831 static void test_GetListBoxInfo(void)
1833 HWND listbox, parent;
1834 WNDPROC oldproc;
1835 DWORD ret;
1837 parent = create_parent();
1838 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1840 oldproc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (LONG_PTR)listbox_subclass_proc);
1841 SetWindowLongPtrA(listbox, GWLP_USERDATA, (LONG_PTR)oldproc);
1843 lb_getlistboxinfo = 0;
1844 ret = GetListBoxInfo(listbox);
1845 ok(ret > 0, "got %d\n", ret);
1846 ok(lb_getlistboxinfo == 1, "got %d\n", lb_getlistboxinfo);
1848 DestroyWindow(listbox);
1849 DestroyWindow(parent);
1852 static void test_missing_lbuttonup(void)
1854 HWND listbox, parent, capture;
1856 parent = create_parent();
1857 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1859 /* Send button down without a corresponding button up */
1860 SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(10, 10));
1861 capture = GetCapture();
1862 ok(capture == listbox, "got %p expected %p\n", capture, listbox);
1864 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */
1865 got_selchange = 0;
1866 SetFocus(NULL);
1867 capture = GetCapture();
1868 ok(capture == NULL, "got %p\n", capture);
1869 ok(got_selchange, "got %d\n", got_selchange);
1871 DestroyWindow(listbox);
1872 DestroyWindow(parent);
1875 static void test_extents(void)
1877 HWND listbox, parent;
1878 SCROLLINFO sinfo;
1879 DWORD res;
1880 BOOL br;
1882 parent = create_parent();
1884 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1886 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1887 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1889 sinfo.cbSize = sizeof(sinfo);
1890 sinfo.fMask = SIF_RANGE;
1891 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1892 ok(br == TRUE, "GetScrollInfo failed\n");
1893 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1894 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1895 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1896 "List box should not have a horizontal scroll bar\n");
1898 /* horizontal extent < width */
1899 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1901 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1902 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1904 sinfo.cbSize = sizeof(sinfo);
1905 sinfo.fMask = SIF_RANGE;
1906 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1907 ok(br == TRUE, "GetScrollInfo failed\n");
1908 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1909 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1910 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1911 "List box should not have a horizontal scroll bar\n");
1913 /* horizontal extent > width */
1914 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1916 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1917 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1919 sinfo.cbSize = sizeof(sinfo);
1920 sinfo.fMask = SIF_RANGE;
1921 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1922 ok(br == TRUE, "GetScrollInfo failed\n");
1923 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1924 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1925 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1926 "List box should not have a horizontal scroll bar\n");
1928 DestroyWindow(listbox);
1930 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL, parent);
1932 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1933 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1935 sinfo.cbSize = sizeof(sinfo);
1936 sinfo.fMask = SIF_RANGE;
1937 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1938 ok(br == TRUE, "GetScrollInfo failed\n");
1939 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1940 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1941 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1942 "List box should not have a horizontal scroll bar\n");
1944 /* horizontal extent < width */
1945 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1947 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1948 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1950 sinfo.cbSize = sizeof(sinfo);
1951 sinfo.fMask = SIF_RANGE;
1952 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1953 ok(br == TRUE, "GetScrollInfo failed\n");
1954 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1955 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
1956 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1957 "List box should not have a horizontal scroll bar\n");
1959 /* horizontal extent > width */
1960 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1962 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1963 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1965 sinfo.cbSize = sizeof(sinfo);
1966 sinfo.fMask = SIF_RANGE;
1967 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1968 ok(br == TRUE, "GetScrollInfo failed\n");
1969 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1970 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
1971 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1972 "List box should have a horizontal scroll bar\n");
1974 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
1976 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1977 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
1979 sinfo.cbSize = sizeof(sinfo);
1980 sinfo.fMask = SIF_RANGE;
1981 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1982 ok(br == TRUE, "GetScrollInfo failed\n");
1983 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1984 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1985 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1986 "List box should not have a horizontal scroll bar\n");
1988 DestroyWindow(listbox);
1991 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL | LBS_DISABLENOSCROLL, parent);
1993 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1994 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1996 sinfo.cbSize = sizeof(sinfo);
1997 sinfo.fMask = SIF_RANGE;
1998 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1999 ok(br == TRUE, "GetScrollInfo failed\n");
2000 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2001 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
2002 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2003 "List box should have a horizontal scroll bar\n");
2005 /* horizontal extent < width */
2006 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
2008 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2009 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
2011 sinfo.cbSize = sizeof(sinfo);
2012 sinfo.fMask = SIF_RANGE;
2013 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2014 ok(br == TRUE, "GetScrollInfo failed\n");
2015 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2016 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
2017 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2018 "List box should have a horizontal scroll bar\n");
2020 /* horizontal extent > width */
2021 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
2023 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2024 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
2026 sinfo.cbSize = sizeof(sinfo);
2027 sinfo.fMask = SIF_RANGE;
2028 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2029 ok(br == TRUE, "GetScrollInfo failed\n");
2030 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2031 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
2032 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2033 "List box should have a horizontal scroll bar\n");
2035 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
2037 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
2038 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
2040 sinfo.cbSize = sizeof(sinfo);
2041 sinfo.fMask = SIF_RANGE;
2042 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
2043 ok(br == TRUE, "GetScrollInfo failed\n");
2044 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
2045 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
2046 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
2047 "List box should have a horizontal scroll bar\n");
2049 DestroyWindow(listbox);
2051 DestroyWindow(parent);
2054 static void test_listbox(void)
2056 static const struct listbox_test SS =
2057 /* {add_style} */
2058 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2059 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2060 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2061 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2063 /* {selected, anchor, caret, selcount}{TODO fields} */
2064 static const struct listbox_test SS_NS =
2065 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2066 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2067 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2068 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2070 static const struct listbox_test MS =
2071 {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
2072 { 1, 1, 1, 1}, {0,0,0,0},
2073 { 2, 1, 2, 1}, {0,0,0,0},
2074 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2076 static const struct listbox_test MS_NS =
2077 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2078 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2079 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2080 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2082 static const struct listbox_test ES =
2083 {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
2084 { 1, 1, 1, 1}, {0,0,0,0},
2085 { 2, 2, 2, 1}, {0,0,0,0},
2086 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2088 static const struct listbox_test ES_NS =
2089 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2090 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2091 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2092 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2094 static const struct listbox_test EMS =
2095 {{ 0, LB_ERR, 0, 0}, {0,0,0,0},
2096 { 1, 1, 1, 1}, {0,0,0,0},
2097 { 2, 2, 2, 1}, {0,0,0,0},
2098 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2100 static const struct listbox_test EMS_NS =
2101 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2102 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2103 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2104 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2106 run_test(0, SS);
2107 run_test(LBS_NOSEL, SS_NS);
2108 run_test(LBS_MULTIPLESEL, MS);
2109 run_test(LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
2110 run_test(LBS_EXTENDEDSEL, ES);
2111 run_test(LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
2112 run_test(LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
2113 run_test(LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
2115 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED, SS);
2116 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOSEL, SS_NS);
2117 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL, MS);
2118 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL | LBS_NOSEL, MS_NS);
2119 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL, ES);
2120 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS);
2121 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS);
2122 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS);
2125 static const struct message lb_addstring_ownerdraw_parent_seq[] =
2127 { WM_MEASUREITEM, sent|wparam|lparam, 0x1012, 0xf30604ed },
2128 { WM_MEASUREITEM, sent|wparam|lparam, 0x1112, 0xf30604ee },
2129 { WM_MEASUREITEM, sent|wparam|lparam, 0x1212, 0xf30604ef },
2130 { 0 }
2133 static const struct message lb_addstring_sort_parent_seq[] =
2135 { WM_MEASUREITEM, sent|wparam|lparam, 0x1012, 0xf30604ed },
2136 { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ed, 0xf30604ee },
2137 { WM_MEASUREITEM, sent|wparam|lparam, 0x1112, 0xf30604ee },
2138 { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ed, 0xf30604ef },
2139 { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ee, 0xf30604ef },
2140 { WM_MEASUREITEM, sent|wparam|lparam, 0x1212, 0xf30604ef },
2141 { 0 }
2144 static const struct message empty_seq[] =
2146 { 0 }
2149 static void test_WM_MEASUREITEM(void)
2151 HWND parent, listbox;
2152 LRESULT data, ret;
2154 parent = create_parent();
2155 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE, parent);
2157 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
2158 ok(data == (LRESULT)strings[0], "data = %08lx, expected %p\n", data, strings[0]);
2159 DestroyWindow(parent);
2161 parent = create_parent();
2162 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS, parent);
2164 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
2165 ok(!data, "data = %08lx\n", data);
2167 /* LBS_HASSTRINGS */
2168 parent = create_parent();
2169 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
2170 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE,
2171 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
2173 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2175 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
2176 ok(ret == 0, "expected 0, got %ld\n", ret);
2177 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
2178 ok(ret == 1, "expected 1, got %ld\n", ret);
2179 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
2180 ok(ret == 2, "expected 2, got %ld\n", ret);
2182 ok_sequence(sequences, PARENT_SEQ_INDEX, lb_addstring_ownerdraw_parent_seq,
2183 "LB_ADDSTRING (LBS_HASSTRINGS, ownerdraw)", FALSE);
2184 DestroyWindow(listbox);
2186 /* LBS_SORT, no LBS_HASSTRINGS */
2187 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
2188 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT | WS_VISIBLE,
2189 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
2191 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2193 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
2194 ok(ret == 0, "expected 0, got %ld\n", ret);
2195 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
2196 ok(ret == 1, "expected 1, got %ld\n", ret);
2197 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
2198 ok(ret == 2, "expected 2, got %ld\n", ret);
2200 ok_sequence(sequences, PARENT_SEQ_INDEX, lb_addstring_sort_parent_seq, "LB_ADDSTRING (LBS_SORT)", FALSE);
2201 DestroyWindow(listbox);
2203 /* LBS_HASSTRINGS */
2204 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
2205 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | WS_VISIBLE,
2206 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
2208 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2210 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
2211 ok(ret == 0, "expected 0, got %ld\n", ret);
2212 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
2213 ok(ret == 1, "expected 1, got %ld\n", ret);
2214 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
2215 ok(ret == 2, "expected 2, got %ld\n", ret);
2217 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "LB_ADDSTRING (LBS_HASSTRINGS)", FALSE);
2218 DestroyWindow(listbox);
2220 /* LBS_HASSTRINGS, LBS_SORT */
2221 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL,
2222 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | LBS_SORT | WS_VISIBLE,
2223 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL);
2225 flush_sequences(sequences, NUM_MSG_SEQUENCES);
2227 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2");
2228 ok(ret == 0, "expected 0, got %ld\n", ret);
2229 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0");
2230 ok(ret == 0, "expected 0, got %ld\n", ret);
2231 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1");
2232 ok(ret == 1, "expected 1, got %ld\n", ret);
2234 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "LB_ADDSTRING (LBS_HASSTRINGS, LBS_SORT)", FALSE);
2235 DestroyWindow(listbox);
2237 DestroyWindow(parent);
2240 static void test_LBS_NODATA(void)
2242 static const UINT invalid_idx[] = { -2, 2 };
2243 static const UINT valid_idx[] = { 0, 1 };
2244 static const ULONG_PTR zero_data;
2245 INT ret, text_len;
2246 unsigned int i;
2247 ULONG_PTR data;
2248 BOOL is_wow64;
2249 HWND listbox;
2251 listbox = CreateWindowA(WC_LISTBOXA, "TestList", LBS_NODATA | LBS_OWNERDRAWFIXED | WS_VISIBLE,
2252 0, 0, 100, 100, NULL, NULL, NULL, 0);
2253 ok(listbox != NULL, "Failed to create ListBox window.\n");
2255 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
2256 ok(ret == 0, "Unexpected return value %d.\n", ret);
2257 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0);
2258 ok(ret == 1, "Unexpected return value %d.\n", ret);
2259 ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
2260 ok(ret == 2, "Unexpected return value %d.\n", ret);
2262 /* Invalid indices. */
2263 for (i = 0; i < ARRAY_SIZE(invalid_idx); ++i)
2265 ret = SendMessageA(listbox, LB_SETITEMDATA, invalid_idx[i], 42);
2266 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2267 ret = SendMessageA(listbox, LB_GETTEXTLEN, invalid_idx[i], 0);
2268 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2269 if (ret == LB_ERR)
2271 ret = SendMessageA(listbox, LB_GETTEXT, invalid_idx[i], (LPARAM)&data);
2272 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2274 ret = SendMessageA(listbox, LB_GETITEMDATA, invalid_idx[i], 0);
2275 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2278 IsWow64Process(GetCurrentProcess(), &is_wow64);
2279 #ifdef _WIN64
2280 text_len = 8;
2281 #else
2282 text_len = is_wow64 ? 8 : 4;
2283 #endif
2285 /* Valid indices. */
2286 for (i = 0; i < ARRAY_SIZE(valid_idx); ++i)
2288 ret = SendMessageA(listbox, LB_SETITEMDATA, valid_idx[i], 42);
2289 ok(ret == TRUE, "Unexpected return value %d.\n", ret);
2290 ret = SendMessageA(listbox, LB_GETTEXTLEN, valid_idx[i], 0);
2291 todo_wine_if(text_len == 8)
2292 ok(ret == text_len, "Unexpected return value %d.\n", ret);
2294 memset(&data, 0xee, sizeof(data));
2295 ret = SendMessageA(listbox, LB_GETTEXT, valid_idx[i], (LPARAM)&data);
2296 todo_wine_if(sizeof(void *) == 8)
2297 ok(ret == sizeof(data), "Unexpected return value %d.\n", ret);
2298 todo_wine
2299 ok(!memcmp(&data, &zero_data, sizeof(data)), "Unexpected item data.\n");
2301 ret = SendMessageA(listbox, LB_GETITEMDATA, valid_idx[i], 0);
2302 todo_wine
2303 ok(ret == 0, "Unexpected return value %d.\n", ret);
2306 /* More messages that don't work with LBS_NODATA. */
2307 ret = SendMessageA(listbox, LB_FINDSTRING, 1, 42);
2308 todo_wine
2309 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2310 ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 42);
2311 todo_wine
2312 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2313 ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 42);
2314 todo_wine
2315 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret);
2317 DestroyWindow(listbox);
2320 START_TEST(listbox)
2322 ULONG_PTR ctx_cookie;
2323 HANDLE hCtx;
2325 if (!load_v6_module(&ctx_cookie, &hCtx))
2326 return;
2328 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2330 test_listbox();
2331 test_item_height();
2332 test_ownerdraw();
2333 test_LB_SELITEMRANGE();
2334 test_LB_SETCURSEL();
2335 test_listbox_height();
2336 test_itemfrompoint();
2337 test_listbox_item_data();
2338 test_listbox_LB_DIR();
2339 test_listbox_dlgdir();
2340 test_set_count();
2341 test_GetListBoxInfo();
2342 test_missing_lbuttonup();
2343 test_extents();
2344 test_WM_MEASUREITEM();
2345 test_LB_SETSEL();
2346 test_LBS_NODATA();
2348 unload_v6_module(ctx_cookie, hCtx);