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