[ADVAPI32_WINETEST] Revert service.c changes from 3c1b7834e1 to avoid testbot hangs...
[reactos.git] / modules / rostests / winetests / user32 / listbox.c
1 /* Unit test suite for list boxes.
2 *
3 * Copyright 2003 Ferenc Wagner
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #include "precomp.h"
21
22 #ifdef VISIBLE
23 #define WAIT Sleep (1000)
24 #define REDRAW RedrawWindow (handle, NULL, 0, RDW_UPDATENOW)
25 #else
26 #define WAIT
27 #define REDRAW
28 #endif
29
30 static const char * const strings[4] = {
31 "First added",
32 "Second added",
33 "Third added",
34 "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."
35 };
36
37 static const char BAD_EXTENSION[] = "*.badtxt";
38
39 static HWND
40 create_listbox (DWORD add_style, HWND parent)
41 {
42 HWND handle;
43 INT_PTR ctl_id=0;
44 if (parent)
45 ctl_id=1;
46 handle=CreateWindowA("LISTBOX", "TestList",
47 (LBS_STANDARD & ~LBS_SORT) | add_style,
48 0, 0, 100, 100,
49 parent, (HMENU)ctl_id, NULL, 0);
50
51 assert (handle);
52 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[0]);
53 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[1]);
54 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[2]);
55 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[3]);
56
57 #ifdef VISIBLE
58 ShowWindow (handle, SW_SHOW);
59 #endif
60 REDRAW;
61
62 return handle;
63 }
64
65 struct listbox_prop {
66 DWORD add_style;
67 };
68
69 struct listbox_stat {
70 int selected, anchor, caret, selcount;
71 };
72
73 struct listbox_test {
74 struct listbox_prop prop;
75 struct listbox_stat init, init_todo;
76 struct listbox_stat click, click_todo;
77 struct listbox_stat step, step_todo;
78 struct listbox_stat sel, sel_todo;
79 };
80
81 static void
82 listbox_query (HWND handle, struct listbox_stat *results)
83 {
84 results->selected = SendMessageA(handle, LB_GETCURSEL, 0, 0);
85 results->anchor = SendMessageA(handle, LB_GETANCHORINDEX, 0, 0);
86 results->caret = SendMessageA(handle, LB_GETCARETINDEX, 0, 0);
87 results->selcount = SendMessageA(handle, LB_GETSELCOUNT, 0, 0);
88 }
89
90 static void
91 buttonpress (HWND handle, WORD x, WORD y)
92 {
93 LPARAM lp=x+(y<<16);
94
95 WAIT;
96 SendMessageA(handle, WM_LBUTTONDOWN, MK_LBUTTON, lp);
97 SendMessageA(handle, WM_LBUTTONUP, 0, lp);
98 REDRAW;
99 }
100
101 static void
102 keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
103 {
104 LPARAM lp=1+(scancode<<16)+(extended?KEYEVENTF_EXTENDEDKEY:0);
105
106 WAIT;
107 SendMessageA(handle, WM_KEYDOWN, keycode, lp);
108 SendMessageA(handle, WM_KEYUP , keycode, lp | 0xc000000);
109 REDRAW;
110 }
111
112 #define listbox_field_ok(t, s, f, got) \
113 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
114 ": expected %d, got %d\n", (unsigned int)t.prop.add_style, \
115 t.s.f, got.f)
116
117 #define listbox_todo_field_ok(t, s, f, got) \
118 todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); }
119
120 #define listbox_ok(t, s, got) \
121 listbox_todo_field_ok(t, s, selected, got); \
122 listbox_todo_field_ok(t, s, anchor, got); \
123 listbox_todo_field_ok(t, s, caret, got); \
124 listbox_todo_field_ok(t, s, selcount, got)
125
126 static void
127 check (const struct listbox_test test)
128 {
129 struct listbox_stat answer;
130 HWND hLB=create_listbox (test.prop.add_style, 0);
131 RECT second_item;
132 int i;
133 int res;
134
135 listbox_query (hLB, &answer);
136 listbox_ok (test, init, answer);
137
138 SendMessageA(hLB, LB_GETITEMRECT, 1, (LPARAM) &second_item);
139 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
140
141 listbox_query (hLB, &answer);
142 listbox_ok (test, click, answer);
143
144 keypress (hLB, VK_DOWN, 0x50, TRUE);
145
146 listbox_query (hLB, &answer);
147 listbox_ok (test, step, answer);
148
149 DestroyWindow (hLB);
150 hLB=create_listbox (test.prop.add_style, 0);
151
152 SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
153 listbox_query (hLB, &answer);
154 listbox_ok (test, sel, answer);
155
156 for (i=0;i<4;i++) {
157 DWORD size = SendMessageA(hLB, LB_GETTEXTLEN, i, 0);
158 CHAR *txt;
159 WCHAR *txtw;
160 int resA, resW;
161
162 txt = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, size+1);
163 resA=SendMessageA(hLB, LB_GETTEXT, i, (LPARAM)txt);
164 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
165
166 txtw = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, 2*size+2);
167 resW=SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
168 if (resA != resW) {
169 trace("SendMessageW(LB_GETTEXT) not supported on this platform (resA=%d resW=%d), skipping...\n",
170 resA, resW);
171 } else {
172 WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL );
173 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
174 }
175
176 HeapFree (GetProcessHeap(), 0, txtw);
177 HeapFree (GetProcessHeap(), 0, txt);
178 }
179
180 /* Confirm the count of items, and that an invalid delete does not remove anything */
181 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
182 ok((res==4), "Expected 4 items, got %d\n", res);
183 res = SendMessageA(hLB, LB_DELETESTRING, -1, 0);
184 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
185 res = SendMessageA(hLB, LB_DELETESTRING, 4, 0);
186 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
187 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0);
188 ok((res==4), "Expected 4 items, got %d\n", res);
189
190 WAIT;
191 DestroyWindow (hLB);
192 }
193
194 static void check_item_height(void)
195 {
196 HWND hLB;
197 HDC hdc;
198 HFONT font;
199 TEXTMETRICA tm;
200 INT itemHeight;
201
202 hLB = create_listbox (0, 0);
203 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n");
204 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n");
205 ok (GetTextMetricsA( hdc, &tm ), "Can't read font metrics\n");
206 ReleaseDC( hLB, hdc);
207
208 ok (SendMessageA(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
209
210 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
211 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight);
212
213 DestroyWindow (hLB);
214
215 hLB = CreateWindowA("LISTBOX", "TestList", LBS_OWNERDRAWVARIABLE,
216 0, 0, 100, 100, NULL, NULL, NULL, 0);
217 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
218 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
219 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 5, 0);
220 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
221 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, -5, 0);
222 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
223 DestroyWindow (hLB);
224 }
225
226 static int got_selchange;
227
228 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
229 {
230 switch (msg)
231 {
232 case WM_DRAWITEM:
233 {
234 RECT rc_item, rc_client, rc_clip;
235 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
236
237 trace("%p WM_DRAWITEM %08lx %08lx\n", hwnd, wparam, lparam);
238
239 ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
240 wparam, dis->CtlID);
241 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
242
243 GetClientRect(dis->hwndItem, &rc_client);
244 trace("hwndItem %p client rect %s\n", dis->hwndItem, wine_dbgstr_rect(&rc_client));
245 GetClipBox(dis->hDC, &rc_clip);
246 trace("clip rect %s\n", wine_dbgstr_rect(&rc_clip));
247 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip),
248 "client rect of the listbox should be equal to the clip box,"
249 "or the clip box should be empty\n");
250
251 trace("rcItem %s\n", wine_dbgstr_rect(&dis->rcItem));
252 SendMessageA(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
253 trace("item rect %s\n", wine_dbgstr_rect(&rc_item));
254 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
255
256 break;
257 }
258
259 case WM_COMMAND:
260 if (HIWORD( wparam ) == LBN_SELCHANGE) got_selchange++;
261 break;
262
263 default:
264 break;
265 }
266
267 return DefWindowProcA(hwnd, msg, wparam, lparam);
268 }
269
270 static HWND create_parent( void )
271 {
272 WNDCLASSA cls;
273 HWND parent;
274 static ATOM class;
275
276 if (!class)
277 {
278 cls.style = 0;
279 cls.lpfnWndProc = main_window_proc;
280 cls.cbClsExtra = 0;
281 cls.cbWndExtra = 0;
282 cls.hInstance = GetModuleHandleA(NULL);
283 cls.hIcon = 0;
284 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
285 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
286 cls.lpszMenuName = NULL;
287 cls.lpszClassName = "main_window_class";
288 class = RegisterClassA( &cls );
289 }
290
291 parent = CreateWindowExA(0, "main_window_class", NULL,
292 WS_POPUP | WS_VISIBLE,
293 100, 100, 400, 400,
294 GetDesktopWindow(), 0,
295 GetModuleHandleA(NULL), NULL);
296 return parent;
297 }
298
299 static void test_ownerdraw(void)
300 {
301 HWND parent, hLB;
302 INT ret;
303 RECT rc;
304
305 parent = create_parent();
306 assert(parent);
307
308 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
309 assert(hLB);
310
311 SetForegroundWindow(hLB);
312 UpdateWindow(hLB);
313
314 /* make height short enough */
315 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
316 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
317 SWP_NOZORDER | SWP_NOMOVE);
318
319 /* make 0 item invisible */
320 SendMessageA(hLB, LB_SETTOPINDEX, 1, 0);
321 ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0);
322 ok(ret == 1, "wrong top index %d\n", ret);
323
324 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
325 trace("item 0 rect %s\n", wine_dbgstr_rect(&rc));
326 ok(!IsRectEmpty(&rc), "empty item rect\n");
327 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
328
329 DestroyWindow(hLB);
330 DestroyWindow(parent);
331 }
332
333 #define listbox_test_query(exp, got) \
334 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
335 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
336 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
337 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
338
339 static void test_LB_SELITEMRANGE(void)
340 {
341 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
342 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
343 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
344 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
345 HWND hLB;
346 struct listbox_stat answer;
347 INT ret;
348
349 trace("testing LB_SELITEMRANGE\n");
350
351 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
352 assert(hLB);
353
354 listbox_query(hLB, &answer);
355 listbox_test_query(test_nosel, answer);
356
357 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
358 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
359 listbox_query(hLB, &answer);
360 listbox_test_query(test_1, answer);
361
362 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
363 listbox_query(hLB, &answer);
364 listbox_test_query(test_nosel, answer);
365
366 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
367 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
368 listbox_query(hLB, &answer);
369 listbox_test_query(test_3, answer);
370
371 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
372 listbox_query(hLB, &answer);
373 listbox_test_query(test_nosel, answer);
374
375 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
376 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
377 listbox_query(hLB, &answer);
378 listbox_test_query(test_nosel, answer);
379
380 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
381 listbox_query(hLB, &answer);
382 listbox_test_query(test_nosel, answer);
383
384 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
385 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
386 listbox_query(hLB, &answer);
387 listbox_test_query(test_1, answer);
388
389 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
390 listbox_query(hLB, &answer);
391 listbox_test_query(test_nosel, answer);
392
393 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
394 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
395 listbox_query(hLB, &answer);
396 listbox_test_query(test_nosel, answer);
397
398 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
399 listbox_query(hLB, &answer);
400 listbox_test_query(test_nosel, answer);
401
402 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
403 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
404 listbox_query(hLB, &answer);
405 listbox_test_query(test_2, answer);
406
407 SendMessageA(hLB, LB_SETSEL, FALSE, -1);
408 listbox_query(hLB, &answer);
409 listbox_test_query(test_nosel, answer);
410
411 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
412 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
413 listbox_query(hLB, &answer);
414 listbox_test_query(test_2, answer);
415
416 DestroyWindow(hLB);
417 }
418
419 static void test_LB_SETCURSEL(void)
420 {
421 HWND parent, hLB;
422 INT ret;
423
424 trace("testing LB_SETCURSEL\n");
425
426 parent = create_parent();
427 assert(parent);
428
429 hLB = create_listbox(LBS_NOINTEGRALHEIGHT | WS_CHILD, parent);
430 assert(hLB);
431
432 SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32);
433
434 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0);
435 ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret);
436 ret = GetScrollPos(hLB, SB_VERT);
437 ok(ret == 0, "expected vscroll 0, got %d\n", ret);
438
439 ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0);
440 ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret);
441 ret = GetScrollPos(hLB, SB_VERT);
442 ok(ret == 1, "expected vscroll 1, got %d\n", ret);
443
444 DestroyWindow(hLB);
445 }
446
447 static void test_listbox_height(void)
448 {
449 HWND hList;
450 int r, id;
451
452 hList = CreateWindowA( "ListBox", "list test", 0,
453 1, 1, 600, 100, NULL, NULL, NULL, NULL );
454 ok( hList != NULL, "failed to create listbox\n");
455
456 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
457 ok( id == 0, "item id wrong\n");
458
459 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
460 ok( r == 0, "send message failed\n");
461
462 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
463 ok( r == 20, "height wrong\n");
464
465 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
466 ok( r == -1, "send message failed\n");
467
468 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
469 ok( r == 20, "height wrong\n");
470
471 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
472 ok( r == -1, "send message failed\n");
473
474 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
475 ok( r == 20, "height wrong\n");
476
477 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
478 ok( r == 0, "send message failed\n");
479
480 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 );
481 ok( r == 0xff, "height wrong\n");
482
483 DestroyWindow( hList );
484 }
485
486 static void test_itemfrompoint(void)
487 {
488 /* WS_POPUP is required in order to have a more accurate size calculation (
489 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
490 behavior of partially-displayed item.
491 */
492 HWND hList = CreateWindowA( "ListBox", "list test",
493 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
494 1, 1, 600, 100, NULL, NULL, NULL, NULL );
495 ULONG r, id;
496 RECT rc;
497
498 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000, nt4 returns 0xffffffff */
499 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
500 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
501
502 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
503 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
504
505 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
506 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r );
507
508 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
509 ok( id == 0, "item id wrong\n");
510 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
511 ok( id == 1, "item id wrong\n");
512
513 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
514 ok( r == 0x1, "ret %x\n", r );
515
516 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
517 ok( r == 0x10001 || broken(r == 1), /* nt4 */
518 "ret %x\n", r );
519
520 /* Resize control so that below assertions about sizes are valid */
521 r = SendMessageA( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
522 ok( r == 1, "ret %x\n", r);
523 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
524 ok( r != 0, "ret %x\n", r);
525
526 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
527 ok( id == 2, "item id wrong\n");
528 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
529 ok( id == 3, "item id wrong\n");
530 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
531 ok( id == 4, "item id wrong\n");
532 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
533 ok( id == 5, "item id wrong\n");
534 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
535 ok( id == 6, "item id wrong\n");
536 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
537 ok( id == 7, "item id wrong\n");
538
539 /* Set the listbox up so that id 1 is at the top, this leaves 5
540 partially visible at the bottom and 6, 7 are invisible */
541
542 SendMessageA( hList, LB_SETTOPINDEX, 1, 0);
543 r = SendMessageA( hList, LB_GETTOPINDEX, 0, 0);
544 ok( r == 1, "top %d\n", r);
545
546 r = SendMessageA( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
547 ok( r == 1, "ret %x\n", r);
548 r = SendMessageA( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
549 ok( r == 0, "ret %x\n", r);
550
551 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
552 ok( r == 1, "ret %x\n", r);
553
554 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
555 ok( r == 0x10001 || broken(r == 1), /* nt4 */
556 "ret %x\n", r );
557
558 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
559 ok( r == 0x10001 || broken(r == 1), /* nt4 */
560 "ret %x\n", r );
561
562 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
563 ok( r == 0x10005 || broken(r == 5), /* nt4 */
564 "item %x\n", r );
565
566 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
567 ok( r == 0x10005 || broken(r == 5), /* nt4 */
568 "item %x\n", r );
569
570 DestroyWindow( hList );
571 }
572
573 static void test_listbox_item_data(void)
574 {
575 HWND hList;
576 int r, id;
577
578 hList = CreateWindowA( "ListBox", "list test", 0,
579 1, 1, 600, 100, NULL, NULL, NULL, NULL );
580 ok( hList != NULL, "failed to create listbox\n");
581
582 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
583 ok( id == 0, "item id wrong\n");
584
585 r = SendMessageA( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
586 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
587
588 r = SendMessageA( hList, LB_GETITEMDATA, 0, 0);
589 ok( r == 20, "get item data failed\n");
590
591 DestroyWindow( hList );
592 }
593
594 static void test_listbox_LB_DIR(void)
595 {
596 HWND hList;
597 int res, itemCount;
598 int itemCount_justFiles;
599 int itemCount_justDrives;
600 int itemCount_allFiles;
601 int itemCount_allDirs;
602 int i;
603 char pathBuffer[MAX_PATH];
604 char * p;
605 char driveletter;
606 const char *wildcard = "*";
607 HANDLE file;
608
609 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
610 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
611 CloseHandle( file );
612
613 /* NOTE: for this test to succeed, there must be no subdirectories
614 under the current directory. In addition, there must be at least
615 one file that fits the wildcard w*.c . Normally, the test
616 directory itself satisfies both conditions.
617 */
618 hList = CreateWindowA( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
619 1, 1, 600, 100, NULL, NULL, NULL, NULL );
620 assert(hList);
621
622 /* Test for standard usage */
623
624 /* This should list all the files in the test directory. */
625 strcpy(pathBuffer, wildcard);
626 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
627 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
628 if (res == -1) /* "*" wildcard doesn't work on win9x */
629 {
630 wildcard = "*.*";
631 strcpy(pathBuffer, wildcard);
632 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
633 }
634 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
635
636 /* There should be some content in the listbox */
637 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
638 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
639 itemCount_allFiles = itemCount;
640 ok(res + 1 == itemCount,
641 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
642 itemCount - 1, res);
643
644 /* This tests behavior when no files match the wildcard */
645 strcpy(pathBuffer, BAD_EXTENSION);
646 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
647 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
648 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
649
650 /* There should be NO content in the listbox */
651 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
652 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
653
654
655 /* This should list all the w*.c files in the test directory
656 * As of this writing, this includes win.c, winstation.c, wsprintf.c
657 */
658 strcpy(pathBuffer, "w*.c");
659 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
660 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer);
661 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
662
663 /* Path specification does NOT converted to uppercase */
664 ok (!strcmp(pathBuffer, "w*.c"),
665 "expected no change to pathBuffer, got %s\n", pathBuffer);
666
667 /* There should be some content in the listbox */
668 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
669 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
670 itemCount_justFiles = itemCount;
671 ok(res + 1 == itemCount,
672 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
673 itemCount - 1, res);
674
675 /* Every single item in the control should start with a w and end in .c */
676 for (i = 0; i < itemCount; i++) {
677 memset(pathBuffer, 0, MAX_PATH);
678 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
679 p = pathBuffer + strlen(pathBuffer);
680 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
681 (*(p-1) == 'c' || *(p-1) == 'C') &&
682 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
683 }
684
685 /* Test DDL_DIRECTORY */
686 strcpy(pathBuffer, wildcard);
687 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
688 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
689 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
690
691 /* There should be some content in the listbox.
692 * All files plus "[..]"
693 */
694 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
695 itemCount_allDirs = itemCount - itemCount_allFiles;
696 ok (itemCount > itemCount_allFiles,
697 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n",
698 itemCount, itemCount_allFiles);
699 ok(res + 1 == itemCount,
700 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
701 itemCount - 1, res);
702
703 /* This tests behavior when no files match the wildcard */
704 strcpy(pathBuffer, BAD_EXTENSION);
705 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
706 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
707 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
708
709 /* There should be NO content in the listbox */
710 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
711 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
712
713
714 /* Test DDL_DIRECTORY */
715 strcpy(pathBuffer, "w*.c");
716 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
717 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
718 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
719
720 /* There should be some content in the listbox. Since the parent directory does not
721 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
722 */
723 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
724 ok (itemCount == itemCount_justFiles,
725 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
726 itemCount, itemCount_justFiles);
727 ok(res + 1 == itemCount,
728 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
729 itemCount - 1, res);
730
731 /* Every single item in the control should start with a w and end in .c. */
732 for (i = 0; i < itemCount; i++) {
733 memset(pathBuffer, 0, MAX_PATH);
734 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
735 p = pathBuffer + strlen(pathBuffer);
736 ok(
737 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
738 (*(p-1) == 'c' || *(p-1) == 'C') &&
739 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
740 }
741
742
743 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
744 strcpy(pathBuffer, wildcard);
745 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
746 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
747 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
748
749 /* There should be some content in the listbox. In particular, there should
750 * be at least one element before, since the string "[-c-]" should
751 * have been added. Depending on the user setting, more drives might have
752 * been added.
753 */
754 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
755 ok (itemCount >= 1,
756 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
757 itemCount, 1);
758 itemCount_justDrives = itemCount;
759 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
760
761 /* Every single item in the control should fit the format [-c-] */
762 for (i = 0; i < itemCount; i++) {
763 memset(pathBuffer, 0, MAX_PATH);
764 driveletter = '\0';
765 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
766 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
767 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
768 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
769 if (!(driveletter >= 'a' && driveletter <= 'z')) {
770 /* Correct after invalid entry is found */
771 trace("removing count of invalid entry %s\n", pathBuffer);
772 itemCount_justDrives--;
773 }
774 }
775
776 /* This tests behavior when no files match the wildcard */
777 strcpy(pathBuffer, BAD_EXTENSION);
778 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
779 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
780 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
781 BAD_EXTENSION, res, itemCount_justDrives -1);
782
783 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
784 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
785 itemCount, itemCount_justDrives);
786
787 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
788 itemCount_justFiles, itemCount_justDrives);
789
790 /* Test DDL_DRIVES. */
791 strcpy(pathBuffer, wildcard);
792 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
793 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
794 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
795
796 /* There should be some content in the listbox. In particular, there should
797 * be at least one element before, since the string "[-c-]" should
798 * have been added. Depending on the user setting, more drives might have
799 * been added.
800 */
801 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
802 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
803 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n",
804 itemCount, itemCount_justDrives + itemCount_allFiles);
805 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n");
806
807 /* This tests behavior when no files match the wildcard */
808 strcpy(pathBuffer, BAD_EXTENSION);
809 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
810 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
811 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
812 BAD_EXTENSION, res, itemCount_justDrives -1);
813
814 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
815 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
816
817
818 /* Test DDL_DRIVES. */
819 strcpy(pathBuffer, "w*.c");
820 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
821 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
822 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
823
824 /* There should be some content in the listbox. In particular, there should
825 * be at least one element before, since the string "[-c-]" should
826 * have been added. Depending on the user setting, more drives might have
827 * been added.
828 */
829 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
830 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
831 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
832 itemCount, itemCount_justDrives + itemCount_justFiles);
833 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
834
835 /* Every single item in the control should fit the format [-c-], or w*.c */
836 for (i = 0; i < itemCount; i++) {
837 memset(pathBuffer, 0, MAX_PATH);
838 driveletter = '\0';
839 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
840 p = pathBuffer + strlen(pathBuffer);
841 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
842 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
843 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
844 } else {
845 ok(
846 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
847 (*(p-1) == 'c' || *(p-1) == 'C') &&
848 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
849 }
850 }
851
852
853 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
854 strcpy(pathBuffer, wildcard);
855 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
856 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
857 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
858
859 /* There should be some content in the listbox. In particular, there should
860 * be exactly the number of plain files, plus the number of mapped drives.
861 */
862 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
863 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs,
864 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
865 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs);
866 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
867
868 /* Every single item in the control should start with a w and end in .c,
869 * except for the "[..]" string, which should appear exactly as it is,
870 * and the mapped drives in the format "[-X-]".
871 */
872 for (i = 0; i < itemCount; i++) {
873 memset(pathBuffer, 0, MAX_PATH);
874 driveletter = '\0';
875 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
876 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
877 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
878 }
879 }
880
881 /* This tests behavior when no files match the wildcard */
882 strcpy(pathBuffer, BAD_EXTENSION);
883 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
884 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
885 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
886 BAD_EXTENSION, res, itemCount_justDrives -1);
887
888 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
889 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
890
891
892
893 /* Test DDL_DIRECTORY|DDL_DRIVES. */
894 strcpy(pathBuffer, "w*.c");
895 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
896 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
897 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
898
899 /* There should be some content in the listbox. In particular, there should
900 * be exactly the number of plain files, plus the number of mapped drives.
901 */
902 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
903 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
904 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
905 itemCount, itemCount_justFiles + itemCount_justDrives);
906 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
907
908 /* Every single item in the control should start with a w and end in .c,
909 * except the mapped drives in the format "[-X-]". The "[..]" directory
910 * should not appear.
911 */
912 for (i = 0; i < itemCount; i++) {
913 memset(pathBuffer, 0, MAX_PATH);
914 driveletter = '\0';
915 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
916 p = pathBuffer + strlen(pathBuffer);
917 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
918 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
919 } else {
920 ok(
921 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
922 (*(p-1) == 'c' || *(p-1) == 'C') &&
923 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
924 }
925 }
926
927 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
928 strcpy(pathBuffer, wildcard);
929 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
930 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
931 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError());
932
933 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
934 ok (itemCount == itemCount_allDirs,
935 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
936 itemCount, itemCount_allDirs);
937 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
938
939 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
940 {
941 memset(pathBuffer, 0, MAX_PATH);
942 SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
943 ok( !strcmp(pathBuffer, "[..]"), "First element is not [..]\n");
944 }
945
946 /* This tests behavior when no files match the wildcard */
947 strcpy(pathBuffer, BAD_EXTENSION);
948 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
949 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
950 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
951 BAD_EXTENSION, res, -1);
952
953 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
954 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
955
956
957 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
958 strcpy(pathBuffer, "w*.c");
959 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
960 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
961 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
962
963 /* There should be no elements, since "[..]" does not fit w*.c */
964 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
965 ok (itemCount == 0,
966 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
967 itemCount, 0);
968
969 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
970 strcpy(pathBuffer, wildcard);
971 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
972 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
973 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
974
975 /* There should be no plain files on the listbox */
976 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
977 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
978 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
979 itemCount, itemCount_justDrives + itemCount_allDirs);
980 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
981
982 for (i = 0; i < itemCount; i++) {
983 memset(pathBuffer, 0, MAX_PATH);
984 driveletter = '\0';
985 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
986 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
987 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
988 } else {
989 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
990 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
991 }
992 }
993
994 /* This tests behavior when no files match the wildcard */
995 strcpy(pathBuffer, BAD_EXTENSION);
996 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
997 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
998 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
999 BAD_EXTENSION, res, itemCount_justDrives -1);
1000
1001 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1002 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
1003
1004 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1005 strcpy(pathBuffer, "w*.c");
1006 SendMessageA(hList, LB_RESETCONTENT, 0, 0);
1007 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
1008 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
1009
1010 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
1011 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0);
1012 ok (itemCount == itemCount_justDrives,
1013 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1014 itemCount, itemCount_justDrives);
1015 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
1016
1017 for (i = 0; i < itemCount; i++) {
1018 memset(pathBuffer, 0, MAX_PATH);
1019 driveletter = '\0';
1020 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
1021 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1022 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1023 }
1024 DestroyWindow(hList);
1025
1026 DeleteFileA( "wtest1.tmp.c" );
1027 }
1028
1029 static HWND g_listBox;
1030 static HWND g_label;
1031
1032 #define ID_TEST_LABEL 1001
1033 #define ID_TEST_LISTBOX 1002
1034
1035 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCTA lpcs)
1036 {
1037 g_label = CreateWindowA(
1038 "Static",
1039 "Contents of static control before DlgDirList.",
1040 WS_CHILD | WS_VISIBLE,
1041 10, 10, 512, 32,
1042 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
1043 if (!g_label) return FALSE;
1044 g_listBox = CreateWindowA(
1045 "ListBox",
1046 "DlgDirList test",
1047 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1048 10, 60, 256, 256,
1049 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1050 if (!g_listBox) return FALSE;
1051
1052 return TRUE;
1053 }
1054
1055 static LRESULT CALLBACK listbox_container_window_procA (
1056 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1057 {
1058 LRESULT result = 0;
1059
1060 switch (uiMsg) {
1061 case WM_DESTROY:
1062 PostQuitMessage(0);
1063 break;
1064 case WM_CREATE:
1065 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1066 ? 0 : (LRESULT)-1;
1067 break;
1068 default:
1069 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1070 break;
1071 }
1072 return result;
1073 }
1074
1075 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1076 {
1077 WNDCLASSA cls;
1078
1079 cls.style = 0;
1080 cls.cbClsExtra = 0;
1081 cls.cbWndExtra = 0;
1082 cls.hInstance = hInst;
1083 cls.hIcon = NULL;
1084 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
1085 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1086 cls.lpszMenuName = NULL;
1087 cls.lpfnWndProc = listbox_container_window_procA;
1088 cls.lpszClassName = "ListboxContainerClass";
1089 if (!RegisterClassA (&cls)) return FALSE;
1090
1091 return TRUE;
1092 }
1093
1094 static void test_listbox_dlgdir(void)
1095 {
1096 HINSTANCE hInst;
1097 HWND hWnd;
1098 int res, itemCount;
1099 int itemCount_allDirs;
1100 int itemCount_justFiles;
1101 int itemCount_justDrives;
1102 int i;
1103 char pathBuffer[MAX_PATH];
1104 char itemBuffer[MAX_PATH];
1105 char tempBuffer[MAX_PATH];
1106 char * p;
1107 char driveletter;
1108 HANDLE file;
1109
1110 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1111 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1112 CloseHandle( file );
1113
1114 /* NOTE: for this test to succeed, there must be no subdirectories
1115 under the current directory. In addition, there must be at least
1116 one file that fits the wildcard w*.c . Normally, the test
1117 directory itself satisfies both conditions.
1118 */
1119
1120 hInst = GetModuleHandleA(0);
1121 if (!RegisterListboxWindowClass(hInst)) assert(0);
1122 hWnd = CreateWindowA("ListboxContainerClass", "ListboxContainerClass",
1123 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1124 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1125 NULL, NULL, hInst, 0);
1126 assert(hWnd);
1127
1128 /* Test for standard usage */
1129
1130 /* The following should be overwritten by the directory path */
1131 SendMessageA(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1132
1133 /* This should list all the w*.c files in the test directory
1134 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1135 */
1136 strcpy(pathBuffer, "w*.c");
1137 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1138 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1139
1140 /* Path specification gets converted to uppercase */
1141 ok (!strcmp(pathBuffer, "W*.C"),
1142 "expected conversion to uppercase, got %s\n", pathBuffer);
1143
1144 /* Loaded path should have overwritten the label text */
1145 SendMessageA(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer);
1146 trace("Static control after DlgDirList: %s\n", pathBuffer);
1147 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1148
1149 /* There should be some content in the listbox */
1150 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1151 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1152 itemCount_justFiles = itemCount;
1153
1154 /* Every single item in the control should start with a w and end in .c */
1155 for (i = 0; i < itemCount; i++) {
1156 memset(pathBuffer, 0, MAX_PATH);
1157 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1158 p = pathBuffer + strlen(pathBuffer);
1159 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1160 (*(p-1) == 'c' || *(p-1) == 'C') &&
1161 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1162 }
1163
1164 /* Test behavior when no files match the wildcard */
1165 strcpy(pathBuffer, BAD_EXTENSION);
1166 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1167 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1168
1169 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1170 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1171
1172 /* Test DDL_DIRECTORY */
1173 strcpy(pathBuffer, "w*.c");
1174 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1175 DDL_DIRECTORY);
1176 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1177
1178 /* There should be some content in the listbox. In particular, there should
1179 * be exactly more elements than before, since the directories should
1180 * have been added.
1181 */
1182 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1183 itemCount_allDirs = itemCount - itemCount_justFiles;
1184 ok (itemCount >= itemCount_justFiles,
1185 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n",
1186 itemCount, itemCount_justFiles);
1187
1188 /* Every single item in the control should start with a w and end in .c,
1189 * except for the "[..]" string, which should appear exactly as it is.
1190 */
1191 for (i = 0; i < itemCount; i++) {
1192 memset(pathBuffer, 0, MAX_PATH);
1193 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1194 p = pathBuffer + strlen(pathBuffer);
1195 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1196 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1197 (*(p-1) == 'c' || *(p-1) == 'C') &&
1198 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1199 }
1200
1201 /* Test behavior when no files match the wildcard */
1202 strcpy(pathBuffer, BAD_EXTENSION);
1203 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1204 DDL_DIRECTORY);
1205 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1206
1207 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1208 ok (itemCount == itemCount_allDirs,
1209 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1210 itemCount_allDirs, itemCount);
1211 for (i = 0; i < itemCount; i++) {
1212 memset(pathBuffer, 0, MAX_PATH);
1213 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1214 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1215 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer);
1216 }
1217
1218
1219 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1220 strcpy(pathBuffer, "w*.c");
1221 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1222 DDL_DRIVES);
1223 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1224
1225 /* There should be some content in the listbox. In particular, there should
1226 * be at least one element before, since the string "[-c-]" should
1227 * have been added. Depending on the user setting, more drives might have
1228 * been added.
1229 */
1230 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1231 ok (itemCount >= 1,
1232 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1233 itemCount, 1);
1234 itemCount_justDrives = itemCount;
1235
1236 /* Every single item in the control should fit the format [-c-] */
1237 for (i = 0; i < itemCount; i++) {
1238 memset(pathBuffer, 0, MAX_PATH);
1239 driveletter = '\0';
1240 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1241 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1242 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1243 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1244 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1245 /* Correct after invalid entry is found */
1246 trace("removing count of invalid entry %s\n", pathBuffer);
1247 itemCount_justDrives--;
1248 }
1249 }
1250
1251 /* Test behavior when no files match the wildcard */
1252 strcpy(pathBuffer, BAD_EXTENSION);
1253 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1254 DDL_DRIVES);
1255 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1256
1257 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1258 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1259
1260
1261 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1262 strcpy(pathBuffer, "w*.c");
1263 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1264 DDL_DIRECTORY|DDL_DRIVES);
1265 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1266
1267 /* There should be some content in the listbox. In particular, there should
1268 * be exactly the number of plain files, plus the number of mapped drives,
1269 * plus one "[..]"
1270 */
1271 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1272 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs,
1273 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1274 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs);
1275
1276 /* Every single item in the control should start with a w and end in .c,
1277 * except for the "[..]" string, which should appear exactly as it is,
1278 * and the mapped drives in the format "[-X-]".
1279 */
1280 for (i = 0; i < itemCount; i++) {
1281 memset(pathBuffer, 0, MAX_PATH);
1282 driveletter = '\0';
1283 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1284 p = pathBuffer + strlen(pathBuffer);
1285 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1286 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1287 } else {
1288 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') ||
1289 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1290 (*(p-1) == 'c' || *(p-1) == 'C') &&
1291 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1292 }
1293 }
1294
1295 /* Test behavior when no files match the wildcard */
1296 strcpy(pathBuffer, BAD_EXTENSION);
1297 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1298 DDL_DIRECTORY|DDL_DRIVES);
1299 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1300
1301 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1302 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1303 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1304 itemCount_justDrives + itemCount_allDirs, itemCount);
1305
1306
1307
1308 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1309 strcpy(pathBuffer, "w*.c");
1310 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1311 DDL_DIRECTORY|DDL_EXCLUSIVE);
1312 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1313
1314 /* There should be exactly one element: "[..]" */
1315 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1316 ok (itemCount == itemCount_allDirs,
1317 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1318 itemCount, itemCount_allDirs);
1319
1320 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */
1321 {
1322 memset(pathBuffer, 0, MAX_PATH);
1323 SendMessageA(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1324 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1325 }
1326
1327 /* Test behavior when no files match the wildcard */
1328 strcpy(pathBuffer, BAD_EXTENSION);
1329 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1330 DDL_DIRECTORY|DDL_EXCLUSIVE);
1331 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1332
1333 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1334 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n");
1335
1336
1337 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1338 strcpy(pathBuffer, "w*.c");
1339 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1340 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1341 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1342
1343 /* There should be no plain files on the listbox */
1344 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1345 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1346 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1347 itemCount, itemCount_justDrives + itemCount_allDirs);
1348
1349 for (i = 0; i < itemCount; i++) {
1350 memset(pathBuffer, 0, MAX_PATH);
1351 driveletter = '\0';
1352 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1353 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1354 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1355 } else {
1356 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']',
1357 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer);
1358 }
1359 }
1360
1361 /* Test behavior when no files match the wildcard */
1362 strcpy(pathBuffer, BAD_EXTENSION);
1363 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1364 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1365 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1366
1367 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1368 ok (itemCount == itemCount_justDrives + itemCount_allDirs,
1369 "DlgDirList() incorrectly filled the listbox!\n");
1370
1371 /* Now test DlgDirSelectEx() in normal operation */
1372 /* Fill with everything - drives, directory and all plain files. */
1373 strcpy(pathBuffer, "*");
1374 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1375 DDL_DIRECTORY|DDL_DRIVES);
1376 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1377
1378 SendMessageA(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1379 memset(pathBuffer, 0, MAX_PATH);
1380 SetLastError(0xdeadbeef);
1381 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1382 ok (GetLastError() == 0xdeadbeef,
1383 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1384 GetLastError());
1385 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1386 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1387 /*
1388 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1389 */
1390 /* Test proper drive/dir/file recognition */
1391 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1392 for (i = 0; i < itemCount; i++) {
1393 memset(itemBuffer, 0, MAX_PATH);
1394 memset(pathBuffer, 0, MAX_PATH);
1395 memset(tempBuffer, 0, MAX_PATH);
1396 driveletter = '\0';
1397 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1398 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1399 ok (res == i, "SendMessageA(LB_SETCURSEL, %d) failed\n", i);
1400 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1401 /* Current item is a drive letter */
1402 SetLastError(0xdeadbeef);
1403 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1404 ok (GetLastError() == 0xdeadbeef,
1405 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1406 i, GetLastError());
1407 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1408
1409 /* For drive letters, DlgDirSelectEx tacks on a colon */
1410 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1411 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1412 } else if (itemBuffer[0] == '[') {
1413 /* Current item is the parent directory */
1414 SetLastError(0xdeadbeef);
1415 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1416 ok (GetLastError() == 0xdeadbeef,
1417 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1418 i, GetLastError());
1419 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1420
1421 /* For directories, DlgDirSelectEx tacks on a backslash */
1422 p = pathBuffer + strlen(pathBuffer);
1423 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1424
1425 tempBuffer[0] = '[';
1426 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1427 strcat(tempBuffer, "]");
1428 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1429 } else {
1430 /* Current item is a plain file */
1431 SetLastError(0xdeadbeef);
1432 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1433 ok (GetLastError() == 0xdeadbeef,
1434 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1435 i, GetLastError());
1436 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1437
1438 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1439 * for example, "Makefile", which gets reported as "Makefile."
1440 */
1441 strcpy(tempBuffer, itemBuffer);
1442 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1443 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1444 }
1445 }
1446
1447 DeleteFileA( "wtest1.tmp.c" );
1448
1449 /* Now test DlgDirSelectEx() in abnormal operation */
1450 /* Fill list with bogus entries, that look somewhat valid */
1451 SendMessageA(g_listBox, LB_RESETCONTENT, 0, 0);
1452 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1453 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1454 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0);
1455 for (i = 0; i < itemCount; i++) {
1456 memset(itemBuffer, 0, MAX_PATH);
1457 memset(pathBuffer, 0, MAX_PATH);
1458 memset(tempBuffer, 0, MAX_PATH);
1459 driveletter = '\0';
1460 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1461 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0);
1462 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1463 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1464 /* Current item is a drive letter */
1465 SetLastError(0xdeadbeef);
1466 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1467 ok (GetLastError() == 0xdeadbeef,
1468 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1469 i, GetLastError());
1470 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1471
1472 /* For drive letters, DlgDirSelectEx tacks on a colon */
1473 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1474 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1475 } else if (itemBuffer[0] == '[') {
1476 /* Current item is the parent directory */
1477 SetLastError(0xdeadbeef);
1478 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1479 ok (GetLastError() == 0xdeadbeef,
1480 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1481 i, GetLastError());
1482 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1483
1484 /* For directories, DlgDirSelectEx tacks on a backslash */
1485 p = pathBuffer + strlen(pathBuffer);
1486 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1487
1488 tempBuffer[0] = '[';
1489 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer));
1490 strcat(tempBuffer, "]");
1491 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1492 } else {
1493 /* Current item is a plain file */
1494 SetLastError(0xdeadbeef);
1495 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1496 ok (GetLastError() == 0xdeadbeef,
1497 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1498 i, GetLastError());
1499 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1500
1501 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1502 * This affects for example, "Makefile", which gets reported as "Makefile."
1503 */
1504 strcpy(tempBuffer, itemBuffer);
1505 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1506 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1507 }
1508 }
1509
1510 /* Test behavior when loading folders from root with and without wildcard */
1511 strcpy(pathBuffer, "C:\\");
1512 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1513 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\ folders\n");
1514 todo_wine ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1515 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1516
1517 strcpy(pathBuffer, "C:\\*");
1518 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1519 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\* folders\n");
1520 ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */,
1521 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
1522
1523 /* Try loading files from an invalid folder */
1524 SetLastError(0xdeadbeef);
1525 strcpy(pathBuffer, "C:\\INVALID$$DIR");
1526 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
1527 todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
1528 todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
1529 "GetLastError should return 0x589, got 0x%X\n",GetLastError());
1530
1531 DestroyWindow(hWnd);
1532 }
1533
1534 static void test_set_count( void )
1535 {
1536 HWND parent, listbox;
1537 LONG ret;
1538 RECT r;
1539
1540 parent = create_parent();
1541 listbox = create_listbox( LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VISIBLE, parent );
1542
1543 UpdateWindow( listbox );
1544 GetUpdateRect( listbox, &r, TRUE );
1545 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1546
1547 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
1548 ok( ret == 0, "got %d\n", ret );
1549 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
1550 ok( ret == 100, "got %d\n", ret );
1551
1552 GetUpdateRect( listbox, &r, TRUE );
1553 ok( !IsRectEmpty( &r ), "got empty rect\n");
1554
1555 ValidateRect( listbox, NULL );
1556 GetUpdateRect( listbox, &r, TRUE );
1557 ok( IsRectEmpty( &r ), "got non-empty rect\n");
1558
1559 ret = SendMessageA( listbox, LB_SETCOUNT, 99, 0 );
1560 ok( ret == 0, "got %d\n", ret );
1561
1562 GetUpdateRect( listbox, &r, TRUE );
1563 ok( !IsRectEmpty( &r ), "got empty rect\n");
1564
1565 DestroyWindow( listbox );
1566 DestroyWindow( parent );
1567 }
1568
1569 static DWORD (WINAPI *pGetListBoxInfo)(HWND);
1570 static int lb_getlistboxinfo;
1571
1572 static LRESULT WINAPI listbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1573 {
1574 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
1575
1576 if (message == LB_GETLISTBOXINFO)
1577 lb_getlistboxinfo++;
1578
1579 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
1580 }
1581
1582 static void test_GetListBoxInfo(void)
1583 {
1584 HWND listbox, parent;
1585 WNDPROC oldproc;
1586 DWORD ret;
1587
1588 pGetListBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetListBoxInfo");
1589
1590 if (!pGetListBoxInfo)
1591 {
1592 win_skip("GetListBoxInfo() not available\n");
1593 return;
1594 }
1595
1596 parent = create_parent();
1597 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1598
1599 oldproc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (LONG_PTR)listbox_subclass_proc);
1600 SetWindowLongPtrA(listbox, GWLP_USERDATA, (LONG_PTR)oldproc);
1601
1602 lb_getlistboxinfo = 0;
1603 ret = pGetListBoxInfo(listbox);
1604 ok(ret > 0, "got %d\n", ret);
1605 todo_wine
1606 ok(lb_getlistboxinfo == 0, "got %d\n", lb_getlistboxinfo);
1607
1608 DestroyWindow(listbox);
1609 DestroyWindow(parent);
1610 }
1611
1612 static void test_missing_lbuttonup( void )
1613 {
1614 HWND listbox, parent, capture;
1615
1616 parent = create_parent();
1617 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1618
1619 /* Send button down without a corresponding button up */
1620 SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(10,10));
1621 capture = GetCapture();
1622 ok(capture == listbox, "got %p expected %p\n", capture, listbox);
1623
1624 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */
1625 got_selchange = 0;
1626 SetFocus(NULL);
1627 capture = GetCapture();
1628 ok(capture == NULL, "got %p\n", capture);
1629 ok(got_selchange, "got %d\n", got_selchange);
1630
1631 DestroyWindow(listbox);
1632 DestroyWindow(parent);
1633 }
1634
1635 static void test_extents(void)
1636 {
1637 HWND listbox, parent;
1638 DWORD res;
1639 SCROLLINFO sinfo;
1640 BOOL br;
1641
1642 parent = create_parent();
1643
1644 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent);
1645
1646 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1647 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1648
1649 sinfo.cbSize = sizeof(sinfo);
1650 sinfo.fMask = SIF_RANGE;
1651 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1652 ok(br == TRUE, "GetScrollInfo failed\n");
1653 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1654 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1655 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1656 "List box should not have a horizontal scroll bar\n");
1657
1658 /* horizontal extent < width */
1659 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1660
1661 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1662 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1663
1664 sinfo.cbSize = sizeof(sinfo);
1665 sinfo.fMask = SIF_RANGE;
1666 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1667 ok(br == TRUE, "GetScrollInfo failed\n");
1668 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1669 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1670 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1671 "List box should not have a horizontal scroll bar\n");
1672
1673 /* horizontal extent > width */
1674 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1675
1676 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1677 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1678
1679 sinfo.cbSize = sizeof(sinfo);
1680 sinfo.fMask = SIF_RANGE;
1681 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1682 ok(br == TRUE, "GetScrollInfo failed\n");
1683 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1684 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1685 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1686 "List box should not have a horizontal scroll bar\n");
1687
1688 DestroyWindow(listbox);
1689
1690
1691 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL, parent);
1692
1693 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1694 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1695
1696 sinfo.cbSize = sizeof(sinfo);
1697 sinfo.fMask = SIF_RANGE;
1698 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1699 ok(br == TRUE, "GetScrollInfo failed\n");
1700 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1701 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax);
1702 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1703 "List box should not have a horizontal scroll bar\n");
1704
1705 /* horizontal extent < width */
1706 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1707
1708 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1709 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1710
1711 sinfo.cbSize = sizeof(sinfo);
1712 sinfo.fMask = SIF_RANGE;
1713 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1714 ok(br == TRUE, "GetScrollInfo failed\n");
1715 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1716 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
1717 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1718 "List box should not have a horizontal scroll bar\n");
1719
1720 /* horizontal extent > width */
1721 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1722
1723 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1724 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1725
1726 sinfo.cbSize = sizeof(sinfo);
1727 sinfo.fMask = SIF_RANGE;
1728 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1729 ok(br == TRUE, "GetScrollInfo failed\n");
1730 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1731 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
1732 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1733 "List box should have a horizontal scroll bar\n");
1734
1735 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
1736
1737 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1738 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
1739
1740 sinfo.cbSize = sizeof(sinfo);
1741 sinfo.fMask = SIF_RANGE;
1742 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1743 ok(br == TRUE, "GetScrollInfo failed\n");
1744 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1745 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1746 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0,
1747 "List box should not have a horizontal scroll bar\n");
1748
1749 DestroyWindow(listbox);
1750
1751
1752 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL | LBS_DISABLENOSCROLL, parent);
1753
1754 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1755 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res);
1756
1757 sinfo.cbSize = sizeof(sinfo);
1758 sinfo.fMask = SIF_RANGE;
1759 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1760 ok(br == TRUE, "GetScrollInfo failed\n");
1761 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1762 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1763 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1764 "List box should have a horizontal scroll bar\n");
1765
1766 /* horizontal extent < width */
1767 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0);
1768
1769 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1770 ok(res == 64, "Got wrong horizontal extent: %u\n", res);
1771
1772 sinfo.cbSize = sizeof(sinfo);
1773 sinfo.fMask = SIF_RANGE;
1774 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1775 ok(br == TRUE, "GetScrollInfo failed\n");
1776 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1777 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax);
1778 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1779 "List box should have a horizontal scroll bar\n");
1780
1781 /* horizontal extent > width */
1782 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0);
1783
1784 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1785 ok(res == 184, "Got wrong horizontal extent: %u\n", res);
1786
1787 sinfo.cbSize = sizeof(sinfo);
1788 sinfo.fMask = SIF_RANGE;
1789 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1790 ok(br == TRUE, "GetScrollInfo failed\n");
1791 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1792 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax);
1793 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1794 "List box should have a horizontal scroll bar\n");
1795
1796 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0);
1797
1798 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0);
1799 ok(res == 0, "Got wrong horizontal extent: %u\n", res);
1800
1801 sinfo.cbSize = sizeof(sinfo);
1802 sinfo.fMask = SIF_RANGE;
1803 br = GetScrollInfo(listbox, SB_HORZ, &sinfo);
1804 ok(br == TRUE, "GetScrollInfo failed\n");
1805 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin);
1806 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax);
1807 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0,
1808 "List box should have a horizontal scroll bar\n");
1809
1810 DestroyWindow(listbox);
1811
1812 DestroyWindow(parent);
1813 }
1814
1815 START_TEST(listbox)
1816 {
1817 const struct listbox_test SS =
1818 /* {add_style} */
1819 {{0},
1820 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1821 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1822 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1823 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1824 /* {selected, anchor, caret, selcount}{TODO fields} */
1825 const struct listbox_test SS_NS =
1826 {{LBS_NOSEL},
1827 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1828 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1829 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1830 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1831 const struct listbox_test MS =
1832 {{LBS_MULTIPLESEL},
1833 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1834 { 1, 1, 1, 1}, {0,0,0,0},
1835 { 2, 1, 2, 1}, {0,0,0,0},
1836 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1837 const struct listbox_test MS_NS =
1838 {{LBS_MULTIPLESEL | LBS_NOSEL},
1839 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1840 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1841 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1842 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1843 const struct listbox_test ES =
1844 {{LBS_EXTENDEDSEL},
1845 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1846 { 1, 1, 1, 1}, {0,0,0,0},
1847 { 2, 2, 2, 1}, {0,0,0,0},
1848 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1849 const struct listbox_test ES_NS =
1850 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1851 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1852 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1853 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1854 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1855 const struct listbox_test EMS =
1856 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1857 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1858 { 1, 1, 1, 1}, {0,0,0,0},
1859 { 2, 2, 2, 1}, {0,0,0,0},
1860 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1861 const struct listbox_test EMS_NS =
1862 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1863 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1864 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1865 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1866 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1867
1868 trace (" Testing single selection...\n");
1869 check (SS);
1870 trace (" ... with NOSEL\n");
1871 check (SS_NS);
1872 trace (" Testing multiple selection...\n");
1873 check (MS);
1874 trace (" ... with NOSEL\n");
1875 check (MS_NS);
1876 trace (" Testing extended selection...\n");
1877 check (ES);
1878 trace (" ... with NOSEL\n");
1879 check (ES_NS);
1880 trace (" Testing extended and multiple selection...\n");
1881 check (EMS);
1882 trace (" ... with NOSEL\n");
1883 check (EMS_NS);
1884
1885 check_item_height();
1886 test_ownerdraw();
1887 test_LB_SELITEMRANGE();
1888 test_LB_SETCURSEL();
1889 test_listbox_height();
1890 test_itemfrompoint();
1891 test_listbox_item_data();
1892 test_listbox_LB_DIR();
1893 test_listbox_dlgdir();
1894 test_set_count();
1895 test_GetListBoxInfo();
1896 test_missing_lbuttonup();
1897 test_extents();
1898 }