user32/tests: Add some ListBox tests for anchor index.
[wine.git] / dlls / user32 / tests / listbox.c
blobee5211c3414f95c4dcca025082f8cb37ca36b794
1 /* Unit test suite for list boxes.
3 * Copyright 2003 Ferenc Wagner
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winnls.h"
30 #include "wine/test.h"
32 #ifdef VISIBLE
33 #define WAIT Sleep (1000)
34 #define REDRAW RedrawWindow (handle, NULL, 0, RDW_UPDATENOW)
35 #else
36 #define WAIT
37 #define REDRAW
38 #endif
40 static const char * const strings[4] = {
41 "First added",
42 "Second added",
43 "Third added",
44 "Fourth added which is very long because at some time we only had a 256 byte character buffer and that was overflowing in one of those applications that had a common dialog file open box and tried to add a 300 characters long custom filter string which of course the code did not like and crashed. Just make sure this string is longer than 256 characters."
47 static const char BAD_EXTENSION[] = "*.badtxt";
49 static int strcmp_aw(LPCWSTR strw, const char *stra)
51 WCHAR buf[1024];
53 if (!stra) return 1;
54 MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf));
55 return lstrcmpW(strw, buf);
58 static HWND
59 create_listbox (DWORD add_style, HWND parent)
61 HWND handle;
62 INT_PTR ctl_id=0;
63 if (parent)
64 ctl_id=1;
65 handle=CreateWindowA("LISTBOX", "TestList",
66 (LBS_STANDARD & ~LBS_SORT) | add_style,
67 0, 0, 100, 100,
68 parent, (HMENU)ctl_id, NULL, 0);
70 assert (handle);
71 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[0]);
72 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[1]);
73 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[2]);
74 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[3]);
76 #ifdef VISIBLE
77 ShowWindow (handle, SW_SHOW);
78 #endif
79 REDRAW;
81 return handle;
84 struct listbox_prop {
85 DWORD add_style;
88 struct listbox_stat {
89 int selected, anchor, caret, selcount;
92 struct listbox_test {
93 struct listbox_prop prop;
94 struct listbox_stat init, init_todo;
95 struct listbox_stat click, click_todo;
96 struct listbox_stat step, step_todo;
97 struct listbox_stat sel, sel_todo;
100 static void
101 listbox_query (HWND handle, struct listbox_stat *results)
103 results->selected = SendMessageA(handle, LB_GETCURSEL, 0, 0);
104 results->anchor = SendMessageA(handle, LB_GETANCHORINDEX, 0, 0);
105 results->caret = SendMessageA(handle, LB_GETCARETINDEX, 0, 0);
106 results->selcount = SendMessageA(handle, LB_GETSELCOUNT, 0, 0);
109 static void
110 buttonpress (HWND handle, WORD x, WORD y)
112 LPARAM lp=x+(y<<16);
114 WAIT;
115 SendMessageA(handle, WM_LBUTTONDOWN, MK_LBUTTON, lp);
116 SendMessageA(handle, WM_LBUTTONUP, 0, lp);
117 REDRAW;
120 static void
121 keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
123 LPARAM lp=1+(scancode<<16)+(extended?KEYEVENTF_EXTENDEDKEY:0);
125 WAIT;
126 SendMessageA(handle, WM_KEYDOWN, keycode, lp);
127 SendMessageA(handle, WM_KEYUP , keycode, lp | 0xc000000);
128 REDRAW;
131 #define listbox_field_ok(t, s, f, got) \
132 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
133 ": expected %d, got %d\n", (unsigned int)t.prop.add_style, \
134 t.s.f, got.f)
136 #define listbox_todo_field_ok(t, s, f, got) \
137 todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
139 #define listbox_ok(t, s, got) \
140 listbox_todo_field_ok(t, s, selected, got); \
141 listbox_todo_field_ok(t, s, anchor, got); \
142 listbox_todo_field_ok(t, s, caret, got); \
143 listbox_todo_field_ok(t, s, selcount, got)
145 static void
146 check (const struct listbox_test test)
148 struct listbox_stat answer;
149 HWND hLB=create_listbox (test.prop.add_style, 0);
150 RECT second_item;
151 int i;
152 int res;
154 listbox_query (hLB, &answer);
155 listbox_ok (test, init, answer);
157 SendMessageA(hLB, LB_GETITEMRECT, 1, (LPARAM) &second_item);
158 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
160 listbox_query (hLB, &answer);
161 listbox_ok (test, click, answer);
163 keypress (hLB, VK_DOWN, 0x50, TRUE);
165 listbox_query (hLB, &answer);
166 listbox_ok (test, step, answer);
168 DestroyWindow (hLB);
169 hLB=create_listbox (test.prop.add_style, 0);
171 SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
172 listbox_query (hLB, &answer);
173 listbox_ok (test, sel, answer);
175 for (i=0;i<4;i++) {
176 DWORD size = SendMessageA(hLB, LB_GETTEXTLEN, i, 0);
177 CHAR *txt;
178 WCHAR *txtw;
179 int resA, resW;
181 txt = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, size+1);
182 resA=SendMessageA(hLB, LB_GETTEXT, i, (LPARAM)txt);
183 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
185 txtw = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, 2*size+2);
186 resW=SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
187 if (resA != resW) {
188 trace("SendMessageW(LB_GETTEXT) not supported on this platform (resA=%d resW=%d), skipping...\n",
189 resA, resW);
190 } else {
191 WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL );
192 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
195 HeapFree (GetProcessHeap(), 0, txtw);
196 HeapFree (GetProcessHeap(), 0, txt);
199 /* Confirm the count of items, and that an invalid delete does not remove anything */
200 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
201 ok((res==4), "Expected 4 items, got %d\n", res);
202 res = SendMessageA(hLB, LB_DELETESTRING, -1, 0);
203 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
204 res = SendMessageA(hLB, LB_DELETESTRING, 4, 0);
205 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
206 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
207 ok((res==4), "Expected 4 items, got %d\n", res);
209 WAIT;
210 DestroyWindow (hLB);
213 static void check_item_height(void)
215 HWND hLB;
216 HDC hdc;
217 HFONT font;
218 TEXTMETRICA tm;
219 INT itemHeight;
221 hLB = create_listbox (0, 0);
222 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n");
223 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n");
224 ok (GetTextMetricsA( hdc, &tm ), "Can't read font metrics\n");
225 ReleaseDC( hLB, hdc);
227 ok (SendMessageA(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
229 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
230 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight);
232 DestroyWindow (hLB);
234 hLB = CreateWindowA("LISTBOX", "TestList", LBS_OWNERDRAWVARIABLE,
235 0, 0, 100, 100, NULL, NULL, NULL, 0);
236 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
237 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
238 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 5, 0);
239 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
240 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, -5, 0);
241 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
242 DestroyWindow (hLB);
245 static int got_selchange;
247 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
249 switch (msg)
251 case WM_MEASUREITEM:
253 DWORD style = GetWindowLongA(GetWindow(hwnd, GW_CHILD), GWL_STYLE);
254 MEASUREITEMSTRUCT *mi = (void*)lparam;
256 ok(wparam == mi->CtlID, "got wParam=%08lx, expected %08x\n", wparam, mi->CtlID);
257 ok(mi->CtlType == ODT_LISTBOX, "mi->CtlType = %u\n", mi->CtlType);
258 ok(mi->CtlID == 1, "mi->CtlID = %u\n", mi->CtlID);
259 ok(mi->itemHeight, "mi->itemHeight = 0\n");
261 if (mi->itemID > 4 || style & LBS_OWNERDRAWFIXED)
262 break;
264 if (style & LBS_HASSTRINGS)
266 ok(!strcmp_aw((WCHAR*)mi->itemData, strings[mi->itemID]),
267 "mi->itemData = %s (%d)\n", wine_dbgstr_w((WCHAR*)mi->itemData), mi->itemID);
269 else
271 ok((void*)mi->itemData == strings[mi->itemID],
272 "mi->itemData = %08lx, expected %p\n", mi->itemData, strings[mi->itemID]);
274 break;
276 case WM_DRAWITEM:
278 RECT rc_item, rc_client, rc_clip;
279 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
281 trace("%p WM_DRAWITEM %08lx %08lx\n", hwnd, wparam, lparam);
283 ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
284 wparam, dis->CtlID);
285 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
287 GetClientRect(dis->hwndItem, &rc_client);
288 trace("hwndItem %p client rect %s\n", dis->hwndItem, wine_dbgstr_rect(&rc_client));
289 GetClipBox(dis->hDC, &rc_clip);
290 trace("clip rect %s\n", wine_dbgstr_rect(&rc_clip));
291 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip),
292 "client rect of the listbox should be equal to the clip box,"
293 "or the clip box should be empty\n");
295 trace("rcItem %s\n", wine_dbgstr_rect(&dis->rcItem));
296 SendMessageA(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
297 trace("item rect %s\n", wine_dbgstr_rect(&rc_item));
298 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
300 break;
303 case WM_COMMAND:
304 if (HIWORD( wparam ) == LBN_SELCHANGE) got_selchange++;
305 break;
307 default:
308 break;
311 return DefWindowProcA(hwnd, msg, wparam, lparam);
314 static HWND create_parent( void )
316 WNDCLASSA cls;
317 HWND parent;
318 static ATOM class;
320 if (!class)
322 cls.style = 0;
323 cls.lpfnWndProc = main_window_proc;
324 cls.cbClsExtra = 0;
325 cls.cbWndExtra = 0;
326 cls.hInstance = GetModuleHandleA(NULL);
327 cls.hIcon = 0;
328 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
329 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
330 cls.lpszMenuName = NULL;
331 cls.lpszClassName = "main_window_class";
332 class = RegisterClassA( &cls );
335 parent = CreateWindowExA(0, "main_window_class", NULL,
336 WS_POPUP | WS_VISIBLE,
337 100, 100, 400, 400,
338 GetDesktopWindow(), 0,
339 GetModuleHandleA(NULL), NULL);
340 return parent;
343 static void test_ownerdraw(void)
345 HWND parent, hLB;
346 INT ret;
347 RECT rc;
349 parent = create_parent();
350 assert(parent);
352 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
353 assert(hLB);
355 SetForegroundWindow(hLB);
356 UpdateWindow(hLB);
358 /* make height short enough */
359 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
360 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
361 SWP_NOZORDER | SWP_NOMOVE);
363 /* make 0 item invisible */
364 SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
365 ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
366 ok(ret == 1, "wrong top index %d\n", ret);
368 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
369 trace("item 0 rect %s\n", wine_dbgstr_rect(&rc));
370 ok(!IsRectEmpty(&rc), "empty item rect\n");
371 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
373 DestroyWindow(hLB);
374 DestroyWindow(parent);
377 #define listbox_test_query(exp, got) \
378 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
379 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
380 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
381 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
383 static void test_LB_SELITEMRANGE(void)
385 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
386 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
387 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
388 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
389 HWND hLB;
390 struct listbox_stat answer;
391 INT ret;
393 trace("testing LB_SELITEMRANGE\n");
395 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
396 assert(hLB);
398 listbox_query(hLB, &answer);
399 listbox_test_query(test_nosel, answer);
401 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
402 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
403 listbox_query(hLB, &answer);
404 listbox_test_query(test_1, answer);
406 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
407 listbox_query(hLB, &answer);
408 listbox_test_query(test_nosel, answer);
410 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
411 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
412 listbox_query(hLB, &answer);
413 listbox_test_query(test_3, answer);
415 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
416 listbox_query(hLB, &answer);
417 listbox_test_query(test_nosel, answer);
419 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
420 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
421 listbox_query(hLB, &answer);
422 listbox_test_query(test_nosel, answer);
424 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
425 listbox_query(hLB, &answer);
426 listbox_test_query(test_nosel, answer);
428 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
429 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
430 listbox_query(hLB, &answer);
431 listbox_test_query(test_1, answer);
433 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
434 listbox_query(hLB, &answer);
435 listbox_test_query(test_nosel, answer);
437 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
438 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
439 listbox_query(hLB, &answer);
440 listbox_test_query(test_nosel, answer);
442 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
443 listbox_query(hLB, &answer);
444 listbox_test_query(test_nosel, answer);
446 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
447 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
448 listbox_query(hLB, &answer);
449 listbox_test_query(test_2, answer);
451 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
452 listbox_query(hLB, &answer);
453 listbox_test_query(test_nosel, answer);
455 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
456 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
457 listbox_query(hLB, &answer);
458 listbox_test_query(test_2, answer);
460 DestroyWindow(hLB);
463 static void test_LB_SETCURSEL(void)
465 HWND parent, hLB;
466 INT ret;
468 trace("testing LB_SETCURSEL\n");
470 parent = create_parent();
471 assert(parent);
473 hLB = create_listbox(LBS_NOINTEGRALHEIGHT | WS_CHILD, parent);
474 assert(hLB);
476 SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32);
478 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
479 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
481 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
482 ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret);
483 ret = GetScrollPos(hLB, SB_VERT);
484 ok(ret == 0, "expected vscroll 0, got %d\n", ret);
486 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
487 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
489 ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0);
490 ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret);
491 ret = GetScrollPos(hLB, SB_VERT);
492 ok(ret == 1, "expected vscroll 1, got %d\n", ret);
494 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
495 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
497 DestroyWindow(hLB);
499 hLB = create_listbox(0, 0);
500 ok(hLB != NULL, "Failed to create ListBox window.\n");
502 ret = SendMessageA(hLB, LB_SETCURSEL, 1, 0);
503 ok(ret == 1, "Unexpected return value %d.\n", ret);
505 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
506 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
508 DestroyWindow(hLB);
510 /* LBS_EXTENDEDSEL */
511 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
512 ok(hLB != NULL, "Failed to create ListBox window.\n");
514 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
515 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
517 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
518 ok(ret == -1, "Unexpected return value %d.\n", ret);
520 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
521 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
523 DestroyWindow(hLB);
525 /* LBS_MULTIPLESEL */
526 hLB = create_listbox(LBS_MULTIPLESEL, 0);
527 ok(hLB != NULL, "Failed to create ListBox window.\n");
529 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
530 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
532 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
533 ok(ret == -1, "Unexpected return value %d.\n", ret);
535 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0);
536 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
538 DestroyWindow(hLB);
541 static void test_LB_SETSEL(void)
543 HWND list;
544 int ret;
546 /* LBS_EXTENDEDSEL */
547 list = create_listbox(LBS_EXTENDEDSEL, 0);
548 ok(list != NULL, "Failed to create ListBox window.\n");
550 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
551 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
553 ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
554 ok(ret == 0, "Unexpected return value %d.\n", ret);
555 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
556 todo_wine
557 ok(ret == 0, "Unexpected anchor index %d.\n", ret);
559 ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
560 ok(ret == 0, "Unexpected return value %d.\n", ret);
561 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
562 todo_wine
563 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
565 ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
566 ok(ret == 0, "Unexpected return value %d.\n", ret);
567 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
568 todo_wine
569 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
571 DestroyWindow(list);
573 /* LBS_MULTIPLESEL */
574 list = create_listbox(LBS_MULTIPLESEL, 0);
575 ok(list != NULL, "Failed to create ListBox window.\n");
577 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
578 ok(ret == -1, "Unexpected anchor index %d.\n", ret);
580 ret = SendMessageA(list, LB_SETSEL, TRUE, 0);
581 ok(ret == 0, "Unexpected return value %d.\n", ret);
582 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
583 todo_wine
584 ok(ret == 0, "Unexpected anchor index %d.\n", ret);
586 ret = SendMessageA(list, LB_SETSEL, TRUE, 1);
587 ok(ret == 0, "Unexpected return value %d.\n", ret);
588 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
589 todo_wine
590 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
592 ret = SendMessageA(list, LB_SETSEL, FALSE, 1);
593 ok(ret == 0, "Unexpected return value %d.\n", ret);
594 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0);
595 todo_wine
596 ok(ret == 1, "Unexpected anchor index %d.\n", ret);
598 DestroyWindow(list);
601 static void test_listbox_height(void)
603 HWND hList;
604 int r, id;
606 hList = CreateWindowA( "ListBox", "list test", 0,
607 1, 1, 600, 100, NULL, NULL, NULL, NULL );
608 ok( hList != NULL, "failed to create listbox\n");
610 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
611 ok( id == 0, "item id wrong\n");
613 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
614 ok( r == 0, "send message failed\n");
616 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
617 ok( r == 20, "height wrong\n");
619 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
620 ok( r == -1, "send message failed\n");
622 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
623 ok( r == 20, "height wrong\n");
625 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
626 ok( r == -1, "send message failed\n");
628 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
629 ok( r == 20, "height wrong\n");
631 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
632 ok( r == 0, "send message failed\n");
634 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
635 ok( r == 0xff, "height wrong\n");
637 DestroyWindow( hList );
640 static void test_itemfrompoint(void)
642 /* WS_POPUP is required in order to have a more accurate size calculation (
643 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
644 behavior of partially-displayed item.
646 HWND hList = CreateWindowA( "ListBox", "list test",
647 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
648 1, 1, 600, 100, NULL, NULL, NULL, NULL );
649 ULONG r, id;
650 RECT rc;
652 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000, nt4 returns 0xffffffff */
653 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
654 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
656 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
657 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
659 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
660 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
662 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
663 ok( id == 0, "item id wrong\n");
664 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
665 ok( id == 1, "item id wrong\n");
667 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
668 ok( r == 0x1, "ret %x\n", r );
670 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
671 ok( r == 0x10001 || broken(r == 1), /* nt4 */
672 "ret %x\n", r );
674 /* Resize control so that below assertions about sizes are valid */
675 r = SendMessageA( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
676 ok( r == 1, "ret %x\n", r);
677 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
678 ok( r != 0, "ret %x\n", r);
680 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
681 ok( id == 2, "item id wrong\n");
682 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
683 ok( id == 3, "item id wrong\n");
684 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
685 ok( id == 4, "item id wrong\n");
686 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
687 ok( id == 5, "item id wrong\n");
688 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
689 ok( id == 6, "item id wrong\n");
690 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
691 ok( id == 7, "item id wrong\n");
693 /* Set the listbox up so that id 1 is at the top, this leaves 5
694 partially visible at the bottom and 6, 7 are invisible */
696 SendMessageA( hList, LB_SETTOPINDEX, 1, 0);
697 r = SendMessageA( hList, LB_GETTOPINDEX, 0, 0);
698 ok( r == 1, "top %d\n", r);
700 r = SendMessageA( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
701 ok( r == 1, "ret %x\n", r);
702 r = SendMessageA( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
703 ok( r == 0, "ret %x\n", r);
705 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
706 ok( r == 1, "ret %x\n", r);
708 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
709 ok( r == 0x10001 || broken(r == 1), /* nt4 */
710 "ret %x\n", r );
712 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
713 ok( r == 0x10001 || broken(r == 1), /* nt4 */
714 "ret %x\n", r );
716 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
717 ok( r == 0x10005 || broken(r == 5), /* nt4 */
718 "item %x\n", r );
720 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
721 ok( r == 0x10005 || broken(r == 5), /* nt4 */
722 "item %x\n", r );
724 DestroyWindow( hList );
727 static void test_listbox_item_data(void)
729 HWND hList;
730 int r, id;
732 hList = CreateWindowA( "ListBox", "list test", 0,
733 1, 1, 600, 100, NULL, NULL, NULL, NULL );
734 ok( hList != NULL, "failed to create listbox\n");
736 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
737 ok( id == 0, "item id wrong\n");
739 r = SendMessageA( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
740 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
742 r = SendMessageA( hList, LB_GETITEMDATA, 0, 0);
743 ok( r == 20, "get item data failed\n");
745 DestroyWindow( hList );
748 static void test_listbox_LB_DIR(void)
750 HWND hList;
751 int res, itemCount;
752 int itemCount_justFiles;
753 int itemCount_justDrives;
754 int itemCount_allFiles;
755 int itemCount_allDirs;
756 int i;
757 char pathBuffer[MAX_PATH];
758 char * p;
759 char driveletter;
760 const char *wildcard = "*";
761 HANDLE file;
763 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
764 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
765 CloseHandle( file );
767 /* NOTE: for this test to succeed, there must be no subdirectories
768 under the current directory. In addition, there must be at least
769 one file that fits the wildcard w*.c . Normally, the test
770 directory itself satisfies both conditions.
772 hList = CreateWindowA( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
773 1, 1, 600, 100, NULL, NULL, NULL, NULL );
774 assert(hList);
776 /* Test for standard usage */
778 /* This should list all the files in the test directory. */
779 strcpy(pathBuffer, wildcard);
780 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
781 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
782 if (res == -1) /* "*" wildcard doesn't work on win9x */
784 wildcard = "*.*";
785 strcpy(pathBuffer, wildcard);
786 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
788 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
790 /* There should be some content in the listbox */
791 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
792 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
793 itemCount_allFiles = itemCount;
794 ok(res + 1 == itemCount,
795 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
796 itemCount - 1, res);
798 /* This tests behavior when no files match the wildcard */
799 strcpy(pathBuffer, BAD_EXTENSION);
800 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
801 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
802 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
804 /* There should be NO content in the listbox */
805 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
806 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
809 /* This should list all the w*.c files in the test directory
810 * As of this writing, this includes win.c, winstation.c, wsprintf.c
812 strcpy(pathBuffer, "w*.c");
813 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
814 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
815 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
817 /* Path specification does NOT converted to uppercase */
818 ok (!strcmp(pathBuffer, "w*.c"),
819 "expected no change to pathBuffer, got %s\n", pathBuffer);
821 /* There should be some content in the listbox */
822 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
823 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
824 itemCount_justFiles = itemCount;
825 ok(res + 1 == itemCount,
826 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
827 itemCount - 1, res);
829 /* Every single item in the control should start with a w and end in .c */
830 for (i = 0; i < itemCount; i++) {
831 memset(pathBuffer, 0, MAX_PATH);
832 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
833 p = pathBuffer + strlen(pathBuffer);
834 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
835 (*(p-1) == 'c' || *(p-1) == 'C') &&
836 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
839 /* Test DDL_DIRECTORY */
840 strcpy(pathBuffer, wildcard);
841 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
842 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
843 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
845 /* There should be some content in the listbox.
846 * All files plus "[..]"
848 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
849 itemCount_allDirs = itemCount - itemCount_allFiles;
850 ok (itemCount > itemCount_allFiles,
851 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
852 itemCount, itemCount_allFiles);
853 ok(res + 1 == itemCount,
854 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
855 itemCount - 1, res);
857 /* This tests behavior when no files match the wildcard */
858 strcpy(pathBuffer, BAD_EXTENSION);
859 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
860 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
861 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
863 /* There should be NO content in the listbox */
864 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
865 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
868 /* Test DDL_DIRECTORY */
869 strcpy(pathBuffer, "w*.c");
870 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
871 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
872 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
874 /* There should be some content in the listbox. Since the parent directory does not
875 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
877 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
878 ok (itemCount == itemCount_justFiles,
879 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
880 itemCount, itemCount_justFiles);
881 ok(res + 1 == itemCount,
882 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
883 itemCount - 1, res);
885 /* Every single item in the control should start with a w and end in .c. */
886 for (i = 0; i < itemCount; i++) {
887 memset(pathBuffer, 0, MAX_PATH);
888 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
889 p = pathBuffer + strlen(pathBuffer);
891 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
892 (*(p-1) == 'c' || *(p-1) == 'C') &&
893 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
897 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
898 strcpy(pathBuffer, wildcard);
899 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
900 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
901 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
903 /* There should be some content in the listbox. In particular, there should
904 * be at least one element before, since the string "[-c-]" should
905 * have been added. Depending on the user setting, more drives might have
906 * been added.
908 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
909 ok (itemCount >= 1,
910 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
911 itemCount, 1);
912 itemCount_justDrives = itemCount;
913 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
915 /* Every single item in the control should fit the format [-c-] */
916 for (i = 0; i < itemCount; i++) {
917 memset(pathBuffer, 0, MAX_PATH);
918 driveletter = '\0';
919 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
920 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
921 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
922 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
923 if (!(driveletter >= 'a' && driveletter <= 'z')) {
924 /* Correct after invalid entry is found */
925 trace("removing count of invalid entry %s\n", pathBuffer);
926 itemCount_justDrives--;
930 /* This tests behavior when no files match the wildcard */
931 strcpy(pathBuffer, BAD_EXTENSION);
932 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
933 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
934 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
935 BAD_EXTENSION, res, itemCount_justDrives -1);
937 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
938 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
939 itemCount, itemCount_justDrives);
941 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
942 itemCount_justFiles, itemCount_justDrives);
944 /* Test DDL_DRIVES. */
945 strcpy(pathBuffer, wildcard);
946 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
947 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
948 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
950 /* There should be some content in the listbox. In particular, there should
951 * be at least one element before, since the string "[-c-]" should
952 * have been added. Depending on the user setting, more drives might have
953 * been added.
955 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
956 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
957 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
958 itemCount, itemCount_justDrives + itemCount_allFiles);
959 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
961 /* This tests behavior when no files match the wildcard */
962 strcpy(pathBuffer, BAD_EXTENSION);
963 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
964 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
965 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
966 BAD_EXTENSION, res, itemCount_justDrives -1);
968 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
969 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
972 /* Test DDL_DRIVES. */
973 strcpy(pathBuffer, "w*.c");
974 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
975 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
976 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
978 /* There should be some content in the listbox. In particular, there should
979 * be at least one element before, since the string "[-c-]" should
980 * have been added. Depending on the user setting, more drives might have
981 * been added.
983 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
984 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
985 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
986 itemCount, itemCount_justDrives + itemCount_justFiles);
987 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
989 /* Every single item in the control should fit the format [-c-], or w*.c */
990 for (i = 0; i < itemCount; i++) {
991 memset(pathBuffer, 0, MAX_PATH);
992 driveletter = '\0';
993 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
994 p = pathBuffer + strlen(pathBuffer);
995 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
996 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
997 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
998 } else {
1000 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1001 (*(p-1) == 'c' || *(p-1) == 'C') &&
1002 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1007 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1008 strcpy(pathBuffer, wildcard);
1009 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1010 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1011 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
1013 /* There should be some content in the listbox. In particular, there should
1014 * be exactly the number of plain files, plus the number of mapped drives.
1016 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1017 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
1018 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1019 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
1020 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1022 /* Every single item in the control should start with a w and end in .c,
1023 * except for the "[..]" string, which should appear exactly as it is,
1024 * and the mapped drives in the format "[-X-]".
1026 for (i = 0; i < itemCount; i++) {
1027 memset(pathBuffer, 0, MAX_PATH);
1028 driveletter = '\0';
1029 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1030 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1031 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1035 /* This tests behavior when no files match the wildcard */
1036 strcpy(pathBuffer, BAD_EXTENSION);
1037 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1038 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1039 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
1040 BAD_EXTENSION, res, itemCount_justDrives -1);
1042 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1043 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1047 /* Test DDL_DIRECTORY|DDL_DRIVES. */
1048 strcpy(pathBuffer, "w*.c");
1049 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1050 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
1051 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
1053 /* There should be some content in the listbox. In particular, there should
1054 * be exactly the number of plain files, plus the number of mapped drives.
1056 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1057 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
1058 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1059 itemCount, itemCount_justFiles + itemCount_justDrives);
1060 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
1062 /* Every single item in the control should start with a w and end in .c,
1063 * except the mapped drives in the format "[-X-]". The "[..]" directory
1064 * should not appear.
1066 for (i = 0; i < itemCount; i++) {
1067 memset(pathBuffer, 0, MAX_PATH);
1068 driveletter = '\0';
1069 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1070 p = pathBuffer + strlen(pathBuffer);
1071 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1072 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1073 } else {
1075 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1076 (*(p-1) == 'c' || *(p-1) == 'C') &&
1077 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1081 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1082 strcpy(pathBuffer, wildcard);
1083 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1084 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1085 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError());
1087 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1088 ok (itemCount == itemCount_allDirs,
1089 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1090 itemCount, itemCount_allDirs);
1091 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
1093 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1095 memset(pathBuffer, 0, MAX_PATH);
1096 SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1097 ok( !strcmp(pathBuffer, "[..]"), "First element is not [..]\n");
1100 /* This tests behavior when no files match the wildcard */
1101 strcpy(pathBuffer, BAD_EXTENSION);
1102 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1103 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1104 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1105 BAD_EXTENSION, res, -1);
1107 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1108 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1111 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1112 strcpy(pathBuffer, "w*.c");
1113 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1114 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1115 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
1117 /* There should be no elements, since "[..]" does not fit w*.c */
1118 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1119 ok (itemCount == 0,
1120 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1121 itemCount, 0);
1123 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1124 strcpy(pathBuffer, wildcard);
1125 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1126 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1127 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1129 /* There should be no plain files on the listbox */
1130 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1131 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1132 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1133 itemCount, itemCount_justDrives + itemCount_allDirs);
1134 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1136 for (i = 0; i < itemCount; i++) {
1137 memset(pathBuffer, 0, MAX_PATH);
1138 driveletter = '\0';
1139 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1140 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1141 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1142 } else {
1143 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1144 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1148 /* This tests behavior when no files match the wildcard */
1149 strcpy(pathBuffer, BAD_EXTENSION);
1150 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1151 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1152 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
1153 BAD_EXTENSION, res, itemCount_justDrives -1);
1155 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1156 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1158 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1159 strcpy(pathBuffer, "w*.c");
1160 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1161 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1162 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1164 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
1165 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1166 ok (itemCount == itemCount_justDrives,
1167 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1168 itemCount, itemCount_justDrives);
1169 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1171 for (i = 0; i < itemCount; i++) {
1172 memset(pathBuffer, 0, MAX_PATH);
1173 driveletter = '\0';
1174 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1175 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1176 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1178 DestroyWindow(hList);
1180 DeleteFileA( "wtest1.tmp.c" );
1183 static HWND g_listBox;
1184 static HWND g_label;
1186 #define ID_TEST_LABEL 1001
1187 #define ID_TEST_LISTBOX 1002
1189 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCTA lpcs)
1191 g_label = CreateWindowA(
1192 "Static",
1193 "Contents of static control before DlgDirList.",
1194 WS_CHILD | WS_VISIBLE,
1195 10, 10, 512, 32,
1196 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1197 if (!g_label) return FALSE;
1198 g_listBox = CreateWindowA(
1199 "ListBox",
1200 "DlgDirList test",
1201 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1202 10, 60, 256, 256,
1203 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1204 if (!g_listBox) return FALSE;
1206 return TRUE;
1209 static LRESULT CALLBACK listbox_container_window_procA (
1210 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1212 LRESULT result = 0;
1214 switch (uiMsg) {
1215 case WM_DESTROY:
1216 PostQuitMessage(0);
1217 break;
1218 case WM_CREATE:
1219 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1220 ? 0 : (LRESULT)-1;
1221 break;
1222 default:
1223 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1224 break;
1226 return result;
1229 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1231 WNDCLASSA cls;
1233 cls.style = 0;
1234 cls.cbClsExtra = 0;
1235 cls.cbWndExtra = 0;
1236 cls.hInstance = hInst;
1237 cls.hIcon = NULL;
1238 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
1239 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1240 cls.lpszMenuName = NULL;
1241 cls.lpfnWndProc = listbox_container_window_procA;
1242 cls.lpszClassName = "ListboxContainerClass";
1243 if (!RegisterClassA (&cls)) return FALSE;
1245 return TRUE;
1248 static void test_listbox_dlgdir(void)
1250 HINSTANCE hInst;
1251 HWND hWnd;
1252 int res, itemCount;
1253 int itemCount_allDirs;
1254 int itemCount_justFiles;
1255 int itemCount_justDrives;
1256 int i;
1257 char pathBuffer[MAX_PATH];
1258 char itemBuffer[MAX_PATH];
1259 char tempBuffer[MAX_PATH];
1260 char * p;
1261 char driveletter;
1262 HANDLE file;
1264 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1265 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1266 CloseHandle( file );
1268 /* NOTE: for this test to succeed, there must be no subdirectories
1269 under the current directory. In addition, there must be at least
1270 one file that fits the wildcard w*.c . Normally, the test
1271 directory itself satisfies both conditions.
1274 hInst = GetModuleHandleA(0);
1275 if (!RegisterListboxWindowClass(hInst)) assert(0);
1276 hWnd = CreateWindowA("ListboxContainerClass", "ListboxContainerClass",
1277 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1278 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1279 NULL, NULL, hInst, 0);
1280 assert(hWnd);
1282 /* Test for standard usage */
1284 /* The following should be overwritten by the directory path */
1285 SendMessageA(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1287 /* This should list all the w*.c files in the test directory
1288 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1290 strcpy(pathBuffer, "w*.c");
1291 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1292 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1294 /* Path specification gets converted to uppercase */
1295 ok (!strcmp(pathBuffer, "W*.C"),
1296 "expected conversion to uppercase, got %s\n", pathBuffer);
1298 /* Loaded path should have overwritten the label text */
1299 SendMessageA(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer);
1300 trace("Static control after DlgDirList: %s\n", pathBuffer);
1301 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1303 /* There should be some content in the listbox */
1304 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1305 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1306 itemCount_justFiles = itemCount;
1308 /* Every single item in the control should start with a w and end in .c */
1309 for (i = 0; i < itemCount; i++) {
1310 memset(pathBuffer, 0, MAX_PATH);
1311 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1312 p = pathBuffer + strlen(pathBuffer);
1313 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1314 (*(p-1) == 'c' || *(p-1) == 'C') &&
1315 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1318 /* Test behavior when no files match the wildcard */
1319 strcpy(pathBuffer, BAD_EXTENSION);
1320 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1321 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1323 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1324 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1326 /* Test DDL_DIRECTORY */
1327 strcpy(pathBuffer, "w*.c");
1328 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1329 DDL_DIRECTORY);
1330 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1332 /* There should be some content in the listbox. In particular, there should
1333 * be exactly more elements than before, since the directories should
1334 * have been added.
1336 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1337 itemCount_allDirs = itemCount - itemCount_justFiles;
1338 ok (itemCount >= itemCount_justFiles,
1339 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1340 itemCount, itemCount_justFiles);
1342 /* Every single item in the control should start with a w and end in .c,
1343 * except for the "[..]" string, which should appear exactly as it is.
1345 for (i = 0; i < itemCount; i++) {
1346 memset(pathBuffer, 0, MAX_PATH);
1347 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1348 p = pathBuffer + strlen(pathBuffer);
1349 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1350 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1351 (*(p-1) == 'c' || *(p-1) == 'C') &&
1352 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1355 /* Test behavior when no files match the wildcard */
1356 strcpy(pathBuffer, BAD_EXTENSION);
1357 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1358 DDL_DIRECTORY);
1359 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1361 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1362 ok (itemCount == itemCount_allDirs,
1363 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1364 itemCount_allDirs, itemCount);
1365 for (i = 0; i < itemCount; i++) {
1366 memset(pathBuffer, 0, MAX_PATH);
1367 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1368 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1369 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1373 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1374 strcpy(pathBuffer, "w*.c");
1375 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1376 DDL_DRIVES);
1377 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1379 /* There should be some content in the listbox. In particular, there should
1380 * be at least one element before, since the string "[-c-]" should
1381 * have been added. Depending on the user setting, more drives might have
1382 * been added.
1384 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1385 ok (itemCount >= 1,
1386 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1387 itemCount, 1);
1388 itemCount_justDrives = itemCount;
1390 /* Every single item in the control should fit the format [-c-] */
1391 for (i = 0; i < itemCount; i++) {
1392 memset(pathBuffer, 0, MAX_PATH);
1393 driveletter = '\0';
1394 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1395 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1396 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1397 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1398 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1399 /* Correct after invalid entry is found */
1400 trace("removing count of invalid entry %s\n", pathBuffer);
1401 itemCount_justDrives--;
1405 /* Test behavior when no files match the wildcard */
1406 strcpy(pathBuffer, BAD_EXTENSION);
1407 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1408 DDL_DRIVES);
1409 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1411 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1412 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1415 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1416 strcpy(pathBuffer, "w*.c");
1417 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1418 DDL_DIRECTORY|DDL_DRIVES);
1419 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1421 /* There should be some content in the listbox. In particular, there should
1422 * be exactly the number of plain files, plus the number of mapped drives,
1423 * plus one "[..]"
1425 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1426 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1427 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1428 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1430 /* Every single item in the control should start with a w and end in .c,
1431 * except for the "[..]" string, which should appear exactly as it is,
1432 * and the mapped drives in the format "[-X-]".
1434 for (i = 0; i < itemCount; i++) {
1435 memset(pathBuffer, 0, MAX_PATH);
1436 driveletter = '\0';
1437 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1438 p = pathBuffer + strlen(pathBuffer);
1439 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1440 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1441 } else {
1442 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1443 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1444 (*(p-1) == 'c' || *(p-1) == 'C') &&
1445 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1449 /* Test behavior when no files match the wildcard */
1450 strcpy(pathBuffer, BAD_EXTENSION);
1451 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1452 DDL_DIRECTORY|DDL_DRIVES);
1453 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1455 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1456 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1457 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1458 itemCount_justDrives + itemCount_allDirs, itemCount);
1462 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1463 strcpy(pathBuffer, "w*.c");
1464 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1465 DDL_DIRECTORY|DDL_EXCLUSIVE);
1466 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1468 /* There should be exactly one element: "[..]" */
1469 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1470 ok (itemCount == itemCount_allDirs,
1471 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1472 itemCount, itemCount_allDirs);
1474 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1476 memset(pathBuffer, 0, MAX_PATH);
1477 SendMessageA(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1478 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1481 /* Test behavior when no files match the wildcard */
1482 strcpy(pathBuffer, BAD_EXTENSION);
1483 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1484 DDL_DIRECTORY|DDL_EXCLUSIVE);
1485 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1487 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1488 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1491 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1492 strcpy(pathBuffer, "w*.c");
1493 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1494 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1495 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1497 /* There should be no plain files on the listbox */
1498 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1499 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1500 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1501 itemCount, itemCount_justDrives + itemCount_allDirs);
1503 for (i = 0; i < itemCount; i++) {
1504 memset(pathBuffer, 0, MAX_PATH);
1505 driveletter = '\0';
1506 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1507 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1508 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1509 } else {
1510 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1511 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1515 /* Test behavior when no files match the wildcard */
1516 strcpy(pathBuffer, BAD_EXTENSION);
1517 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1518 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1519 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1521 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1522 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1523 "DlgDirList() incorrectly filled the listbox!\n");
1525 /* Now test DlgDirSelectEx() in normal operation */
1526 /* Fill with everything - drives, directory and all plain files. */
1527 strcpy(pathBuffer, "*");
1528 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1529 DDL_DIRECTORY|DDL_DRIVES);
1530 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1532 SendMessageA(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1533 memset(pathBuffer, 0, MAX_PATH);
1534 SetLastError(0xdeadbeef);
1535 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1536 ok (GetLastError() == 0xdeadbeef,
1537 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1538 GetLastError());
1539 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1540 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1542 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1544 /* Test proper drive/dir/file recognition */
1545 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1546 for (i = 0; i < itemCount; i++) {
1547 memset(itemBuffer, 0, MAX_PATH);
1548 memset(pathBuffer, 0, MAX_PATH);
1549 memset(tempBuffer, 0, MAX_PATH);
1550 driveletter = '\0';
1551 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1552 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1553 ok (res == i, "SendMessageA(LB_SETCURSEL, %d) failed\n", i);
1554 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1555 /* Current item is a drive letter */
1556 SetLastError(0xdeadbeef);
1557 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1558 ok (GetLastError() == 0xdeadbeef,
1559 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1560 i, GetLastError());
1561 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1563 /* For drive letters, DlgDirSelectEx tacks on a colon */
1564 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1565 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1566 } else if (itemBuffer[0] == '[') {
1567 /* Current item is the parent directory */
1568 SetLastError(0xdeadbeef);
1569 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1570 ok (GetLastError() == 0xdeadbeef,
1571 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1572 i, GetLastError());
1573 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1575 /* For directories, DlgDirSelectEx tacks on a backslash */
1576 p = pathBuffer + strlen(pathBuffer);
1577 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1579 tempBuffer[0] = '[';
1580 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1581 strcat(tempBuffer, "]");
1582 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1583 } else {
1584 /* Current item is a plain file */
1585 SetLastError(0xdeadbeef);
1586 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1587 ok (GetLastError() == 0xdeadbeef,
1588 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1589 i, GetLastError());
1590 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1592 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1593 * for example, "Makefile", which gets reported as "Makefile."
1595 strcpy(tempBuffer, itemBuffer);
1596 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1597 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1601 DeleteFileA( "wtest1.tmp.c" );
1603 /* Now test DlgDirSelectEx() in abnormal operation */
1604 /* Fill list with bogus entries, that look somewhat valid */
1605 SendMessageA(g_listBox, LB_RESETCONTENT, 0, 0);
1606 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1607 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1608 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1609 for (i = 0; i < itemCount; i++) {
1610 memset(itemBuffer, 0, MAX_PATH);
1611 memset(pathBuffer, 0, MAX_PATH);
1612 memset(tempBuffer, 0, MAX_PATH);
1613 driveletter = '\0';
1614 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1615 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1616 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1617 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1618 /* Current item is a drive letter */
1619 SetLastError(0xdeadbeef);
1620 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1621 ok (GetLastError() == 0xdeadbeef,
1622 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1623 i, GetLastError());
1624 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1626 /* For drive letters, DlgDirSelectEx tacks on a colon */
1627 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1628 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1629 } else if (itemBuffer[0] == '[') {
1630 /* Current item is the parent directory */
1631 SetLastError(0xdeadbeef);
1632 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1633 ok (GetLastError() == 0xdeadbeef,
1634 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1635 i, GetLastError());
1636 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1638 /* For directories, DlgDirSelectEx tacks on a backslash */
1639 p = pathBuffer + strlen(pathBuffer);
1640 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1642 tempBuffer[0] = '[';
1643 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1644 strcat(tempBuffer, "]");
1645 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1646 } else {
1647 /* Current item is a plain file */
1648 SetLastError(0xdeadbeef);
1649 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1650 ok (GetLastError() == 0xdeadbeef,
1651 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1652 i, GetLastError());
1653 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1655 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1656 * This affects for example, "Makefile", which gets reported as "Makefile."
1658 strcpy(tempBuffer, itemBuffer);
1659 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1660 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1664 /* Test behavior when loading folders from root with and without wildcard */
1665 strcpy(pathBuffer, "C:\\");
1666 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1667 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\ folders\n");
1668 todo_wine ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1669 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1671 strcpy(pathBuffer, "C:\\*");
1672 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1673 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\* folders\n");
1674 ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1675 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1677 /* Try loading files from an invalid folder */
1678 SetLastError(0xdeadbeef);
1679 strcpy(pathBuffer, "C:\\INVALID$$DIR");
1680 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1681 todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
1682 todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
1683 "GetLastError should return 0x589, got 0x%X\n",GetLastError());
1685 DestroyWindow(hWnd);
1688 static void test_set_count( void )
1690 HWND parent, listbox;
1691 LONG ret;
1692 RECT r;
1694 parent = create_parent();
1695 listbox = create_listbox( LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VISIBLE, parent );
1697 UpdateWindow( listbox );
1698 GetUpdateRect( listbox, &r, TRUE );
1699 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1701 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
1702 ok( ret == 0, "got %d\n", ret );
1703 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
1704 ok( ret == 100, "got %d\n", ret );
1706 GetUpdateRect( listbox, &r, TRUE );
1707 ok( !IsRectEmpty( &r ), "got empty rect\n");
1709 ValidateRect( listbox, NULL );
1710 GetUpdateRect( listbox, &r, TRUE );
1711 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1713 ret = SendMessageA( listbox, LB_SETCOUNT, 99, 0 );
1714 ok( ret == 0, "got %d\n", ret );
1716 GetUpdateRect( listbox, &r, TRUE );
1717 ok( !IsRectEmpty( &r ), "got empty rect\n");
1719 DestroyWindow( listbox );
1720 DestroyWindow( parent );
1723 static DWORD (WINAPI *pGetListBoxInfo)(HWND);
1724 static int lb_getlistboxinfo;
1726 static LRESULT WINAPI listbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1728 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
1730 if (message == LB_GETLISTBOXINFO)
1731 lb_getlistboxinfo++;
1733 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
1736 static void test_GetListBoxInfo(void)
1738 HWND listbox, parent;
1739 WNDPROC oldproc;
1740 DWORD ret;
1742 pGetListBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetListBoxInfo");
1744 if (!pGetListBoxInfo)
1746 win_skip("GetListBoxInfo() not available\n");
1747 return;
1750 parent = create_parent();
1751 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1753 oldproc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (LONG_PTR)listbox_subclass_proc);
1754 SetWindowLongPtrA(listbox, GWLP_USERDATA, (LONG_PTR)oldproc);
1756 lb_getlistboxinfo = 0;
1757 ret = pGetListBoxInfo(listbox);
1758 ok(ret > 0, "got %d\n", ret);
1759 todo_wine
1760 ok(lb_getlistboxinfo == 0, "got %d\n", lb_getlistboxinfo);
1762 DestroyWindow(listbox);
1763 DestroyWindow(parent);
1766 static void test_missing_lbuttonup( void )
1768 HWND listbox, parent, capture;
1770 parent = create_parent();
1771 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1773 /* Send button down without a corresponding button up */
1774 SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(10,10));
1775 capture = GetCapture();
1776 ok(capture == listbox, "got %p expected %p\n", capture, listbox);
1778 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */
1779 got_selchange = 0;
1780 SetFocus(NULL);
1781 capture = GetCapture();
1782 ok(capture == NULL, "got %p\n", capture);
1783 ok(got_selchange, "got %d\n", got_selchange);
1785 DestroyWindow(listbox);
1786 DestroyWindow(parent);
1789 static void test_extents(void)
1791 HWND listbox, parent;
1792 DWORD res;
1793 SCROLLINFO sinfo;
1794 BOOL br;
1796 parent = create_parent();
1798 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1800 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1801 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1803 sinfo.cbSize = sizeof(sinfo);
1804 sinfo.fMask = SIF_RANGE;
1805 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1806 ok(br == TRUE, "GetScrollInfo failed\n");
1807 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1808 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1809 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1810 "List box should not have a horizontal scroll bar\n");
1812 /* horizontal extent < width */
1813 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1815 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1816 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1818 sinfo.cbSize = sizeof(sinfo);
1819 sinfo.fMask = SIF_RANGE;
1820 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1821 ok(br == TRUE, "GetScrollInfo failed\n");
1822 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1823 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1824 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1825 "List box should not have a horizontal scroll bar\n");
1827 /* horizontal extent > width */
1828 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1830 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1831 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1833 sinfo.cbSize = sizeof(sinfo);
1834 sinfo.fMask = SIF_RANGE;
1835 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1836 ok(br == TRUE, "GetScrollInfo failed\n");
1837 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1838 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1839 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1840 "List box should not have a horizontal scroll bar\n");
1842 DestroyWindow(listbox);
1845 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL, parent);
1847 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1848 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1850 sinfo.cbSize = sizeof(sinfo);
1851 sinfo.fMask = SIF_RANGE;
1852 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1853 ok(br == TRUE, "GetScrollInfo failed\n");
1854 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1855 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1856 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1857 "List box should not have a horizontal scroll bar\n");
1859 /* horizontal extent < width */
1860 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1862 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1863 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1865 sinfo.cbSize = sizeof(sinfo);
1866 sinfo.fMask = SIF_RANGE;
1867 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1868 ok(br == TRUE, "GetScrollInfo failed\n");
1869 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1870 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
1871 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1872 "List box should not have a horizontal scroll bar\n");
1874 /* horizontal extent > width */
1875 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1877 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1878 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1880 sinfo.cbSize = sizeof(sinfo);
1881 sinfo.fMask = SIF_RANGE;
1882 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1883 ok(br == TRUE, "GetScrollInfo failed\n");
1884 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1885 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
1886 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1887 "List box should have a horizontal scroll bar\n");
1889 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
1891 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1892 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
1894 sinfo.cbSize = sizeof(sinfo);
1895 sinfo.fMask = SIF_RANGE;
1896 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1897 ok(br == TRUE, "GetScrollInfo failed\n");
1898 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1899 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1900 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1901 "List box should not have a horizontal scroll bar\n");
1903 DestroyWindow(listbox);
1906 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL | LBS_DISABLENOSCROLL, parent);
1908 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1909 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1911 sinfo.cbSize = sizeof(sinfo);
1912 sinfo.fMask = SIF_RANGE;
1913 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1914 ok(br == TRUE, "GetScrollInfo failed\n");
1915 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1916 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1917 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1918 "List box should have a horizontal scroll bar\n");
1920 /* horizontal extent < width */
1921 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1923 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1924 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1926 sinfo.cbSize = sizeof(sinfo);
1927 sinfo.fMask = SIF_RANGE;
1928 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1929 ok(br == TRUE, "GetScrollInfo failed\n");
1930 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1931 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
1932 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1933 "List box should have a horizontal scroll bar\n");
1935 /* horizontal extent > width */
1936 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1938 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1939 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1941 sinfo.cbSize = sizeof(sinfo);
1942 sinfo.fMask = SIF_RANGE;
1943 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1944 ok(br == TRUE, "GetScrollInfo failed\n");
1945 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1946 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
1947 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1948 "List box should have a horizontal scroll bar\n");
1950 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
1952 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1953 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
1955 sinfo.cbSize = sizeof(sinfo);
1956 sinfo.fMask = SIF_RANGE;
1957 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1958 ok(br == TRUE, "GetScrollInfo failed\n");
1959 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1960 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1961 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1962 "List box should have a horizontal scroll bar\n");
1964 DestroyWindow(listbox);
1966 DestroyWindow(parent);
1969 static void test_WM_MEASUREITEM(void)
1971 HWND parent, listbox;
1972 LRESULT data;
1974 parent = create_parent();
1975 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE, parent);
1977 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
1978 ok(data == (LRESULT)strings[0], "data = %08lx, expected %p\n", data, strings[0]);
1979 DestroyWindow(parent);
1981 parent = create_parent();
1982 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS, parent);
1984 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0);
1985 ok(!data, "data = %08lx\n", data);
1986 DestroyWindow(parent);
1989 START_TEST(listbox)
1991 const struct listbox_test SS =
1992 /* {add_style} */
1993 {{0},
1994 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1995 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1996 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1997 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1998 /* {selected, anchor, caret, selcount}{TODO fields} */
1999 const struct listbox_test SS_NS =
2000 {{LBS_NOSEL},
2001 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2002 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2003 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2004 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2005 const struct listbox_test MS =
2006 {{LBS_MULTIPLESEL},
2007 { 0, LB_ERR, 0, 0}, {0,0,0,0},
2008 { 1, 1, 1, 1}, {0,0,0,0},
2009 { 2, 1, 2, 1}, {0,0,0,0},
2010 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2011 const struct listbox_test MS_NS =
2012 {{LBS_MULTIPLESEL | LBS_NOSEL},
2013 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2014 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2015 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2016 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2017 const struct listbox_test ES =
2018 {{LBS_EXTENDEDSEL},
2019 { 0, LB_ERR, 0, 0}, {0,0,0,0},
2020 { 1, 1, 1, 1}, {0,0,0,0},
2021 { 2, 2, 2, 1}, {0,0,0,0},
2022 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2023 const struct listbox_test ES_NS =
2024 {{LBS_EXTENDEDSEL | LBS_NOSEL},
2025 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2026 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2027 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2028 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2029 const struct listbox_test EMS =
2030 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
2031 { 0, LB_ERR, 0, 0}, {0,0,0,0},
2032 { 1, 1, 1, 1}, {0,0,0,0},
2033 { 2, 2, 2, 1}, {0,0,0,0},
2034 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
2035 const struct listbox_test EMS_NS =
2036 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
2037 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
2038 { 1, 1, 1, LB_ERR}, {0,0,0,0},
2039 { 2, 2, 2, LB_ERR}, {0,0,0,0},
2040 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
2042 trace (" Testing single selection...\n");
2043 check (SS);
2044 trace (" ... with NOSEL\n");
2045 check (SS_NS);
2046 trace (" Testing multiple selection...\n");
2047 check (MS);
2048 trace (" ... with NOSEL\n");
2049 check (MS_NS);
2050 trace (" Testing extended selection...\n");
2051 check (ES);
2052 trace (" ... with NOSEL\n");
2053 check (ES_NS);
2054 trace (" Testing extended and multiple selection...\n");
2055 check (EMS);
2056 trace (" ... with NOSEL\n");
2057 check (EMS_NS);
2059 check_item_height();
2060 test_ownerdraw();
2061 test_LB_SELITEMRANGE();
2062 test_LB_SETCURSEL();
2063 test_listbox_height();
2064 test_itemfrompoint();
2065 test_listbox_item_data();
2066 test_listbox_LB_DIR();
2067 test_listbox_dlgdir();
2068 test_set_count();
2069 test_GetListBoxInfo();
2070 test_missing_lbuttonup();
2071 test_extents();
2072 test_WM_MEASUREITEM();
2073 test_LB_SETSEL();