msi: Fix the published location of the upgrade code for the machine context.
[wine/multimedia.git] / dlls / user32 / tests / listbox.c
blob849372ce37019dde15cba4d8a0a2ae17456ce2b7
1 /* Unit test suite for list boxes.
3 * Copyright 2003 Ferenc Wagner
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <assert.h>
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winnls.h"
30 #include "wine/test.h"
32 #ifdef VISIBLE
33 #define WAIT Sleep (1000)
34 #define REDRAW RedrawWindow (handle, NULL, 0, RDW_UPDATENOW)
35 #else
36 #define WAIT
37 #define REDRAW
38 #endif
40 static const char * const strings[4] = {
41 "First added",
42 "Second added",
43 "Third added",
44 "Fourth added which is very long because at some time we only had a 256 byte character buffer and that was overflowing in one of those applications that had a common dialog file open box and tried to add a 300 characters long custom filter string which of course the code did not like and crashed. Just make sure this string is longer than 256 characters."
47 static const char BAD_EXTENSION[] = "*.txtbad";
49 static HWND
50 create_listbox (DWORD add_style, HWND parent)
52 HWND handle;
53 int ctl_id=0;
54 if (parent)
55 ctl_id=1;
56 handle=CreateWindow ("LISTBOX", "TestList",
57 (LBS_STANDARD & ~LBS_SORT) | add_style,
58 0, 0, 100, 100,
59 parent, (HMENU)ctl_id, NULL, 0);
61 assert (handle);
62 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[0]);
63 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[1]);
64 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[2]);
65 SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[3]);
67 #ifdef VISIBLE
68 ShowWindow (handle, SW_SHOW);
69 #endif
70 REDRAW;
72 return handle;
75 struct listbox_prop {
76 DWORD add_style;
79 struct listbox_stat {
80 int selected, anchor, caret, selcount;
83 struct listbox_test {
84 struct listbox_prop prop;
85 struct listbox_stat init, init_todo;
86 struct listbox_stat click, click_todo;
87 struct listbox_stat step, step_todo;
88 struct listbox_stat sel, sel_todo;
91 static void
92 listbox_query (HWND handle, struct listbox_stat *results)
94 results->selected = SendMessage (handle, LB_GETCURSEL, 0, 0);
95 results->anchor = SendMessage (handle, LB_GETANCHORINDEX, 0, 0);
96 results->caret = SendMessage (handle, LB_GETCARETINDEX, 0, 0);
97 results->selcount = SendMessage (handle, LB_GETSELCOUNT, 0, 0);
100 static void
101 buttonpress (HWND handle, WORD x, WORD y)
103 LPARAM lp=x+(y<<16);
105 WAIT;
106 SendMessage (handle, WM_LBUTTONDOWN, (WPARAM) MK_LBUTTON, lp);
107 SendMessage (handle, WM_LBUTTONUP , (WPARAM) 0 , lp);
108 REDRAW;
111 static void
112 keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
114 LPARAM lp=1+(scancode<<16)+(extended?KEYEVENTF_EXTENDEDKEY:0);
116 WAIT;
117 SendMessage (handle, WM_KEYDOWN, keycode, lp);
118 SendMessage (handle, WM_KEYUP , keycode, lp | 0xc000000);
119 REDRAW;
122 #define listbox_field_ok(t, s, f, got) \
123 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
124 ": expected %d, got %d\n", (unsigned int)t.prop.add_style, \
125 t.s.f, got.f)
127 #define listbox_todo_field_ok(t, s, f, got) \
128 if (t.s##_todo.f) todo_wine { listbox_field_ok(t, s, f, got); } \
129 else listbox_field_ok(t, s, f, got)
131 #define listbox_ok(t, s, got) \
132 listbox_todo_field_ok(t, s, selected, got); \
133 listbox_todo_field_ok(t, s, anchor, got); \
134 listbox_todo_field_ok(t, s, caret, got); \
135 listbox_todo_field_ok(t, s, selcount, got)
137 static void
138 check (const struct listbox_test test)
140 struct listbox_stat answer;
141 HWND hLB=create_listbox (test.prop.add_style, 0);
142 RECT second_item;
143 int i;
144 int res;
146 listbox_query (hLB, &answer);
147 listbox_ok (test, init, answer);
149 SendMessage (hLB, LB_GETITEMRECT, (WPARAM) 1, (LPARAM) &second_item);
150 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
152 listbox_query (hLB, &answer);
153 listbox_ok (test, click, answer);
155 keypress (hLB, VK_DOWN, 0x50, TRUE);
157 listbox_query (hLB, &answer);
158 listbox_ok (test, step, answer);
160 DestroyWindow (hLB);
161 hLB=create_listbox (test.prop.add_style, 0);
163 SendMessage (hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
164 listbox_query (hLB, &answer);
165 listbox_ok (test, sel, answer);
167 for (i=0;i<4;i++) {
168 DWORD size = SendMessage (hLB, LB_GETTEXTLEN, i, 0);
169 CHAR *txt;
170 WCHAR *txtw;
171 int resA, resW;
173 txt = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, size+1);
174 resA=SendMessageA(hLB, LB_GETTEXT, i, (LPARAM)txt);
175 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
177 txtw = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, 2*size+2);
178 resW=SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw);
179 if (resA != resW) {
180 trace("SendMessageW(LB_GETTEXT) not supported on this platform (resA=%d resW=%d), skipping...\n",
181 resA, resW);
182 } else {
183 WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL );
184 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]);
187 HeapFree (GetProcessHeap(), 0, txtw);
188 HeapFree (GetProcessHeap(), 0, txt);
191 /* Confirm the count of items, and that an invalid delete does not remove anything */
192 res = SendMessage (hLB, LB_GETCOUNT, 0, 0);
193 ok((res==4), "Expected 4 items, got %d\n", res);
194 res = SendMessage (hLB, LB_DELETESTRING, -1, 0);
195 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
196 res = SendMessage (hLB, LB_DELETESTRING, 4, 0);
197 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
198 res = SendMessage (hLB, LB_GETCOUNT, 0, 0);
199 ok((res==4), "Expected 4 items, got %d\n", res);
201 WAIT;
202 DestroyWindow (hLB);
205 static void check_item_height(void)
207 HWND hLB;
208 HDC hdc;
209 HFONT font;
210 TEXTMETRIC tm;
211 INT itemHeight;
213 hLB = create_listbox (0, 0);
214 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n");
215 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n");
216 ok (GetTextMetrics( hdc, &tm ), "Can't read font metrics\n");
217 ReleaseDC( hLB, hdc);
219 ok (SendMessage(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n");
221 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, 0, 0);
222 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight);
224 DestroyWindow (hLB);
226 hLB = CreateWindow ("LISTBOX", "TestList", LBS_OWNERDRAWVARIABLE,
227 0, 0, 100, 100, NULL, NULL, NULL, 0);
228 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, 0, 0);
229 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
230 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, 5, 0);
231 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
232 itemHeight = SendMessage(hLB, LB_GETITEMHEIGHT, -5, 0);
233 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight);
234 DestroyWindow (hLB);
237 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
239 switch (msg)
241 case WM_DRAWITEM:
243 RECT rc_item, rc_client, rc_clip;
244 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam;
246 trace("%p WM_DRAWITEM %08lx %08lx\n", hwnd, wparam, lparam);
248 ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n",
249 wparam, dis->CtlID);
250 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
252 GetClientRect(dis->hwndItem, &rc_client);
253 trace("hwndItem %p client rect (%d,%d-%d,%d)\n", dis->hwndItem,
254 rc_client.left, rc_client.top, rc_client.right, rc_client.bottom);
255 GetClipBox(dis->hDC, &rc_clip);
256 trace("clip rect (%d,%d-%d,%d)\n", rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom);
257 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip),
258 "client rect of the listbox should be equal to the clip box,"
259 "or the clip box should be empty\n");
261 trace("rcItem (%d,%d-%d,%d)\n", dis->rcItem.left, dis->rcItem.top,
262 dis->rcItem.right, dis->rcItem.bottom);
263 SendMessage(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item);
264 trace("item rect (%d,%d-%d,%d)\n", rc_item.left, rc_item.top, rc_item.right, rc_item.bottom);
265 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n");
267 break;
270 default:
271 break;
274 return DefWindowProc(hwnd, msg, wparam, lparam);
277 static void test_ownerdraw(void)
279 WNDCLASS cls;
280 HWND parent, hLB;
281 INT ret;
282 RECT rc;
284 cls.style = 0;
285 cls.lpfnWndProc = main_window_proc;
286 cls.cbClsExtra = 0;
287 cls.cbWndExtra = 0;
288 cls.hInstance = GetModuleHandle(0);
289 cls.hIcon = 0;
290 cls.hCursor = LoadCursor(0, (LPSTR)IDC_ARROW);
291 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
292 cls.lpszMenuName = NULL;
293 cls.lpszClassName = "main_window_class";
294 assert(RegisterClass(&cls));
296 parent = CreateWindowEx(0, "main_window_class", NULL,
297 WS_POPUP | WS_VISIBLE,
298 100, 100, 400, 400,
299 GetDesktopWindow(), 0,
300 GetModuleHandle(0), NULL);
301 assert(parent);
303 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent);
304 assert(hLB);
306 UpdateWindow(hLB);
308 /* make height short enough */
309 SendMessage(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
310 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1,
311 SWP_NOZORDER | SWP_NOMOVE);
313 /* make 0 item invisible */
314 SendMessage(hLB, LB_SETTOPINDEX, 1, 0);
315 ret = SendMessage(hLB, LB_GETTOPINDEX, 0, 0);
316 ok(ret == 1, "wrong top index %d\n", ret);
318 SendMessage(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc);
319 trace("item 0 rect (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom);
320 ok(!IsRectEmpty(&rc), "empty item rect\n");
321 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
323 DestroyWindow(hLB);
324 DestroyWindow(parent);
327 #define listbox_test_query(exp, got) \
328 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
329 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
330 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
331 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
333 static void test_selection(void)
335 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
336 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
337 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
338 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
339 HWND hLB;
340 struct listbox_stat answer;
341 INT ret;
343 trace("testing LB_SELITEMRANGE\n");
345 hLB = create_listbox(LBS_EXTENDEDSEL, 0);
346 assert(hLB);
348 listbox_query(hLB, &answer);
349 listbox_test_query(test_nosel, answer);
351 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
352 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
353 listbox_query(hLB, &answer);
354 listbox_test_query(test_1, answer);
356 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
357 listbox_query(hLB, &answer);
358 listbox_test_query(test_nosel, answer);
360 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
361 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
362 listbox_query(hLB, &answer);
363 listbox_test_query(test_3, answer);
365 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
366 listbox_query(hLB, &answer);
367 listbox_test_query(test_nosel, answer);
369 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
370 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
371 listbox_query(hLB, &answer);
372 listbox_test_query(test_nosel, answer);
374 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
375 listbox_query(hLB, &answer);
376 listbox_test_query(test_nosel, answer);
378 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
379 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
380 listbox_query(hLB, &answer);
381 listbox_test_query(test_1, answer);
383 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
384 listbox_query(hLB, &answer);
385 listbox_test_query(test_nosel, answer);
387 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
388 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
389 listbox_query(hLB, &answer);
390 listbox_test_query(test_nosel, answer);
392 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
393 listbox_query(hLB, &answer);
394 listbox_test_query(test_nosel, answer);
396 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
397 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
398 listbox_query(hLB, &answer);
399 listbox_test_query(test_2, answer);
401 SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
402 listbox_query(hLB, &answer);
403 listbox_test_query(test_nosel, answer);
405 ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
406 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
407 listbox_query(hLB, &answer);
408 listbox_test_query(test_2, answer);
410 DestroyWindow(hLB);
413 static void test_listbox_height(void)
415 HWND hList;
416 int r, id;
418 hList = CreateWindow( "ListBox", "list test", 0,
419 1, 1, 600, 100, NULL, NULL, NULL, NULL );
420 ok( hList != NULL, "failed to create listbox\n");
422 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
423 ok( id == 0, "item id wrong\n");
425 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
426 ok( r == 0, "send message failed\n");
428 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
429 ok( r == 20, "height wrong\n");
431 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
432 ok( r == -1, "send message failed\n");
434 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
435 ok( r == 20, "height wrong\n");
437 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
438 ok( r == -1, "send message failed\n");
440 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
441 ok( r == 20, "height wrong\n");
443 r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
444 ok( r == 0, "send message failed\n");
446 r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
447 ok( r == 0xff, "height wrong\n");
449 DestroyWindow( hList );
452 static void test_itemfrompoint(void)
454 /* WS_POPUP is required in order to have a more accurate size calculation (
455 without caption). LBS_NOINTEGRALHEIGHT is required in order to test
456 behavior of partially-displayed item.
458 HWND hList = CreateWindow( "ListBox", "list test",
459 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT,
460 1, 1, 600, 100, NULL, NULL, NULL, NULL );
461 LONG r, id;
462 RECT rc;
464 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000 */
465 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
466 ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r );
468 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 ));
469 ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r );
471 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 ));
472 ok( r == 0x1ffff || r == 0x10000, "ret %x\n", r );
474 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
475 ok( id == 0, "item id wrong\n");
476 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi1");
477 ok( id == 1, "item id wrong\n");
479 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 ));
480 ok( r == 0x1, "ret %x\n", r );
482 r = SendMessage(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 ));
483 ok( r == 0x10001, "ret %x\n", r );
485 /* Resize control so that below assertions about sizes are valid */
486 r = SendMessage( hList, LB_GETITEMRECT, 0, (LPARAM)&rc);
487 ok( r == 1, "ret %x\n", r);
488 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE);
489 ok( r != 0, "ret %x\n", r);
491 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi2");
492 ok( id == 2, "item id wrong\n");
493 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi3");
494 ok( id == 3, "item id wrong\n");
495 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi4");
496 ok( id == 4, "item id wrong\n");
497 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi5");
498 ok( id == 5, "item id wrong\n");
499 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi6");
500 ok( id == 6, "item id wrong\n");
501 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi7");
502 ok( id == 7, "item id wrong\n");
504 /* Set the listbox up so that id 1 is at the top, this leaves 5
505 partially visible at the bottom and 6, 7 are invisible */
507 SendMessage( hList, LB_SETTOPINDEX, 1, 0);
508 r = SendMessage( hList, LB_GETTOPINDEX, 0, 0);
509 ok( r == 1, "top %d\n", r);
511 r = SendMessage( hList, LB_GETITEMRECT, 5, (LPARAM)&rc);
512 ok( r == 1, "ret %x\n", r);
513 r = SendMessage( hList, LB_GETITEMRECT, 6, (LPARAM)&rc);
514 ok( r == 0, "ret %x\n", r);
516 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) );
517 ok( r == 1, "ret %x\n", r);
519 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) );
520 ok( r == 0x10001, "ret %x\n", r );
522 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) );
523 ok( r == 0x10001, "ret %x\n", r );
525 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) );
526 ok( r == 0x10005, "item %x\n", r );
528 r = SendMessage( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) );
529 ok( r == 0x10005, "item %x\n", r );
531 DestroyWindow( hList );
534 static void test_listbox_item_data(void)
536 HWND hList;
537 int r, id;
539 hList = CreateWindow( "ListBox", "list test", 0,
540 1, 1, 600, 100, NULL, NULL, NULL, NULL );
541 ok( hList != NULL, "failed to create listbox\n");
543 id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
544 ok( id == 0, "item id wrong\n");
546 r = SendMessage( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 ));
547 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r);
549 r = SendMessage( hList, LB_GETITEMDATA, 0, 0);
550 ok( r == 20, "get item data failed\n");
552 DestroyWindow( hList );
555 static void test_listbox_LB_DIR()
557 HWND hList;
558 int res, itemCount;
559 int itemCount_justFiles;
560 int itemCount_justDrives;
561 int itemCount_allFiles;
562 int i;
563 char pathBuffer[MAX_PATH];
564 char * p;
565 char driveletter;
566 HANDLE file;
568 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
569 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
570 CloseHandle( file );
572 /* NOTE: for this test to succeed, there must be no subdirectories
573 under the current directory. In addition, there must be at least
574 one file that fits the wildcard w*.c . Normally, the test
575 directory itself satisfies both conditions.
577 hList = CreateWindow( "ListBox", "list test", WS_VISIBLE|WS_POPUP,
578 1, 1, 600, 100, NULL, NULL, NULL, NULL );
579 assert(hList);
581 /* Test for standard usage */
583 /* This should list all the files in the test directory. */
584 strcpy(pathBuffer, "*");
585 SendMessage(hList, LB_RESETCONTENT, 0, 0);
586 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
587 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError());
589 /* There should be some content in the listbox */
590 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
591 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
592 itemCount_allFiles = itemCount;
593 ok(res + 1 == itemCount,
594 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n",
595 itemCount - 1, res);
597 /* This tests behavior when no files match the wildcard */
598 strcpy(pathBuffer, BAD_EXTENSION);
599 SendMessage(hList, LB_RESETCONTENT, 0, 0);
600 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
601 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
603 /* There should be NO content in the listbox */
604 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
605 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
608 /* This should list all the w*.c files in the test directory
609 * As of this writing, this includes win.c, winstation.c, wsprintf.c
611 strcpy(pathBuffer, "w*.c");
612 SendMessage(hList, LB_RESETCONTENT, 0, 0);
613 res = SendMessage(hList, LB_DIR, 0, (LPARAM)pathBuffer);
614 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError());
616 /* Path specification does NOT converted to uppercase */
617 ok (!strcmp(pathBuffer, "w*.c"),
618 "expected no change to pathBuffer, got %s\n", pathBuffer);
620 /* There should be some content in the listbox */
621 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
622 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n");
623 itemCount_justFiles = itemCount;
624 ok(res + 1 == itemCount,
625 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n",
626 itemCount - 1, res);
628 /* Every single item in the control should start with a w and end in .c */
629 for (i = 0; i < itemCount; i++) {
630 memset(pathBuffer, 0, MAX_PATH);
631 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
632 p = pathBuffer + strlen(pathBuffer);
633 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
634 (*(p-1) == 'c' || *(p-1) == 'C') &&
635 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
638 /* Test DDL_DIRECTORY */
639 strcpy(pathBuffer, "*");
640 SendMessage(hList, LB_RESETCONTENT, 0, 0);
641 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
642 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError());
644 /* There should be some content in the listbox.
645 * All files plus "[..]"
647 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
648 ok (itemCount == itemCount_allFiles + 1,
649 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected %d\n",
650 itemCount, itemCount_allFiles + 1);
651 ok(res + 1 == itemCount,
652 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n",
653 itemCount - 1, res);
655 /* This tests behavior when no files match the wildcard */
656 strcpy(pathBuffer, BAD_EXTENSION);
657 SendMessage(hList, LB_RESETCONTENT, 0, 0);
658 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
659 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res);
661 /* There should be NO content in the listbox */
662 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
663 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n");
666 /* Test DDL_DIRECTORY */
667 strcpy(pathBuffer, "w*.c");
668 SendMessage(hList, LB_RESETCONTENT, 0, 0);
669 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer);
670 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError());
672 /* There should be some content in the listbox. Since the parent directory does not
673 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY
675 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
676 ok (itemCount == itemCount_justFiles,
677 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n",
678 itemCount, itemCount_justFiles);
679 ok(res + 1 == itemCount,
680 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n",
681 itemCount - 1, res);
683 /* Every single item in the control should start with a w and end in .c. */
684 for (i = 0; i < itemCount; i++) {
685 memset(pathBuffer, 0, MAX_PATH);
686 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
687 p = pathBuffer + strlen(pathBuffer);
689 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
690 (*(p-1) == 'c' || *(p-1) == 'C') &&
691 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
695 /* Test DDL_DRIVES|DDL_EXCLUSIVE */
696 strcpy(pathBuffer, "*");
697 SendMessage(hList, LB_RESETCONTENT, 0, 0);
698 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
699 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
701 /* There should be some content in the listbox. In particular, there should
702 * be at least one element before, since the string "[-c-]" should
703 * have been added. Depending on the user setting, more drives might have
704 * been added.
706 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
707 ok (itemCount >= 1,
708 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n",
709 itemCount, 1);
710 itemCount_justDrives = itemCount;
711 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n");
713 /* Every single item in the control should fit the format [-c-] */
714 for (i = 0; i < itemCount; i++) {
715 memset(pathBuffer, 0, MAX_PATH);
716 driveletter = '\0';
717 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
718 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
719 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
720 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
721 if (!(driveletter >= 'a' && driveletter <= 'z')) {
722 /* Correct after invalid entry is found */
723 trace("removing count of invalid entry %s\n", pathBuffer);
724 itemCount_justDrives--;
728 /* This tests behavior when no files match the wildcard */
729 strcpy(pathBuffer, BAD_EXTENSION);
730 SendMessage(hList, LB_RESETCONTENT, 0, 0);
731 res = SendMessage(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
732 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
733 BAD_EXTENSION, res, itemCount_justDrives -1);
735 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
736 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n",
737 itemCount, itemCount_justDrives);
739 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n",
740 itemCount_justFiles, itemCount_justDrives);
742 /* Test DDL_DRIVES. */
743 strcpy(pathBuffer, "*");
744 SendMessage(hList, LB_RESETCONTENT, 0, 0);
745 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
746 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
748 /* There should be some content in the listbox. In particular, there should
749 * be at least one element before, since the string "[-c-]" should
750 * have been added. Depending on the user setting, more drives might have
751 * been added.
753 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
754 ok (itemCount == itemCount_justDrives + itemCount_allFiles,
755 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
756 itemCount, itemCount_justDrives + itemCount_allFiles);
757 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
759 /* This tests behavior when no files match the wildcard */
760 strcpy(pathBuffer, BAD_EXTENSION);
761 SendMessage(hList, LB_RESETCONTENT, 0, 0);
762 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
763 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n",
764 BAD_EXTENSION, res, itemCount_justDrives -1);
766 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
767 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
770 /* Test DDL_DRIVES. */
771 strcpy(pathBuffer, "w*.c");
772 SendMessage(hList, LB_RESETCONTENT, 0, 0);
773 res = SendMessage(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer);
774 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
776 /* There should be some content in the listbox. In particular, there should
777 * be at least one element before, since the string "[-c-]" should
778 * have been added. Depending on the user setting, more drives might have
779 * been added.
781 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
782 ok (itemCount == itemCount_justDrives + itemCount_justFiles,
783 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n",
784 itemCount, itemCount_justDrives + itemCount_justFiles);
785 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n");
787 /* Every single item in the control should fit the format [-c-], or w*.c */
788 for (i = 0; i < itemCount; i++) {
789 memset(pathBuffer, 0, MAX_PATH);
790 driveletter = '\0';
791 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
792 p = pathBuffer + strlen(pathBuffer);
793 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
794 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
795 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
796 } else {
798 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
799 (*(p-1) == 'c' || *(p-1) == 'C') &&
800 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
805 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
806 strcpy(pathBuffer, "*");
807 SendMessage(hList, LB_RESETCONTENT, 0, 0);
808 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
809 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError());
811 /* There should be some content in the listbox. In particular, there should
812 * be exactly the number of plain files, plus the number of mapped drives.
814 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
815 ok (itemCount == itemCount_allFiles + itemCount_justDrives + 1,
816 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
817 itemCount, itemCount_allFiles + itemCount_justDrives + 1);
818 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
820 /* Every single item in the control should start with a w and end in .c,
821 * except for the "[..]" string, which should appear exactly as it is,
822 * and the mapped drives in the format "[-X-]".
824 for (i = 0; i < itemCount; i++) {
825 memset(pathBuffer, 0, MAX_PATH);
826 driveletter = '\0';
827 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
828 p = pathBuffer + strlen(pathBuffer);
829 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
830 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
834 /* This tests behavior when no files match the wildcard */
835 strcpy(pathBuffer, BAD_EXTENSION);
836 SendMessage(hList, LB_RESETCONTENT, 0, 0);
837 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
838 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n",
839 BAD_EXTENSION, res, itemCount_justDrives -1);
841 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
842 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
846 /* Test DDL_DIRECTORY|DDL_DRIVES. */
847 strcpy(pathBuffer, "w*.c");
848 SendMessage(hList, LB_RESETCONTENT, 0, 0);
849 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer);
850 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError());
852 /* There should be some content in the listbox. In particular, there should
853 * be exactly the number of plain files, plus the number of mapped drives.
855 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
856 ok (itemCount == itemCount_justFiles + itemCount_justDrives,
857 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
858 itemCount, itemCount_justFiles + itemCount_justDrives);
859 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n");
861 /* Every single item in the control should start with a w and end in .c,
862 * except the mapped drives in the format "[-X-]". The "[..]" directory
863 * should not appear.
865 for (i = 0; i < itemCount; i++) {
866 memset(pathBuffer, 0, MAX_PATH);
867 driveletter = '\0';
868 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
869 p = pathBuffer + strlen(pathBuffer);
870 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
871 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
872 } else {
874 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
875 (*(p-1) == 'c' || *(p-1) == 'C') &&
876 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
880 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
881 strcpy(pathBuffer, "*");
882 SendMessage(hList, LB_RESETCONTENT, 0, 0);
883 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
884 ok (res == 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError());
886 /* There should be exactly one element: "[..]" */
887 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
888 ok (itemCount == 1,
889 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
890 itemCount, 1);
891 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n");
893 memset(pathBuffer, 0, MAX_PATH);
894 SendMessage(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer);
895 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
897 /* This tests behavior when no files match the wildcard */
898 strcpy(pathBuffer, BAD_EXTENSION);
899 SendMessage(hList, LB_RESETCONTENT, 0, 0);
900 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
901 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
902 BAD_EXTENSION, res, -1);
904 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
905 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
908 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
909 strcpy(pathBuffer, "w*.c");
910 SendMessage(hList, LB_RESETCONTENT, 0, 0);
911 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
912 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR);
914 /* There should be no elements, since "[..]" does not fit w*.c */
915 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
916 ok (itemCount == 0,
917 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
918 itemCount, 0);
920 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
921 strcpy(pathBuffer, "*");
922 SendMessage(hList, LB_RESETCONTENT, 0, 0);
923 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
924 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
926 /* There should be no plain files on the listbox */
927 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
928 ok (itemCount == itemCount_justDrives + 1,
929 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
930 itemCount, itemCount_justDrives + 1);
931 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
933 for (i = 0; i < itemCount; i++) {
934 memset(pathBuffer, 0, MAX_PATH);
935 driveletter = '\0';
936 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
937 p = pathBuffer + strlen(pathBuffer);
938 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
939 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
940 } else {
941 ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit expected [..]\n", i, pathBuffer);
945 /* This tests behavior when no files match the wildcard */
946 strcpy(pathBuffer, BAD_EXTENSION);
947 SendMessage(hList, LB_RESETCONTENT, 0, 0);
948 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
949 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n",
950 BAD_EXTENSION, res, itemCount_justDrives -1);
952 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
953 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1);
955 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
956 strcpy(pathBuffer, "w*.c");
957 SendMessage(hList, LB_RESETCONTENT, 0, 0);
958 res = SendMessage(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer);
959 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError());
961 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */
962 itemCount = SendMessage(hList, LB_GETCOUNT, 0, 0);
963 ok (itemCount == itemCount_justDrives,
964 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
965 itemCount, itemCount_justDrives);
966 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n");
968 for (i = 0; i < itemCount; i++) {
969 memset(pathBuffer, 0, MAX_PATH);
970 driveletter = '\0';
971 SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer);
972 p = pathBuffer + strlen(pathBuffer);
973 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
974 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
976 DestroyWindow(hList);
978 DeleteFileA( "wtest1.tmp.c" );
981 HWND g_listBox;
982 HWND g_label;
984 #define ID_TEST_LABEL 1001
985 #define ID_TEST_LISTBOX 1002
987 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCT lpcs)
989 g_label = CreateWindow(
990 "Static",
991 "Contents of static control before DlgDirList.",
992 WS_CHILD | WS_VISIBLE,
993 10, 10, 512, 32,
994 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0);
995 if (!g_label) return FALSE;
996 g_listBox = CreateWindow(
997 "ListBox",
998 "DlgDirList test",
999 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL,
1000 10, 60, 256, 256,
1001 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0);
1002 if (!g_listBox) return FALSE;
1004 return TRUE;
1007 static LRESULT CALLBACK listbox_container_window_procA (
1008 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
1010 LRESULT result = 0;
1012 switch (uiMsg) {
1013 case WM_DESTROY:
1014 PostQuitMessage(0);
1015 break;
1016 case WM_CREATE:
1017 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam)
1018 ? 0 : (LRESULT)-1;
1019 break;
1020 default:
1021 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam);
1022 break;
1024 return result;
1027 static BOOL RegisterListboxWindowClass(HINSTANCE hInst)
1029 WNDCLASSA cls;
1031 cls.style = 0;
1032 cls.cbClsExtra = 0;
1033 cls.cbWndExtra = 0;
1034 cls.hInstance = hInst;
1035 cls.hIcon = NULL;
1036 cls.hCursor = LoadCursorA (NULL, IDC_ARROW);
1037 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1038 cls.lpszMenuName = NULL;
1039 cls.lpfnWndProc = listbox_container_window_procA;
1040 cls.lpszClassName = "ListboxContainerClass";
1041 if (!RegisterClassA (&cls)) return FALSE;
1043 return TRUE;
1046 static void test_listbox_dlgdir(void)
1048 HINSTANCE hInst;
1049 HWND hWnd;
1050 int res, itemCount;
1051 int itemCount_justFiles;
1052 int itemCount_justDrives;
1053 int i;
1054 char pathBuffer[MAX_PATH];
1055 char itemBuffer[MAX_PATH];
1056 char tempBuffer[MAX_PATH];
1057 char * p;
1058 char driveletter;
1059 HANDLE file;
1061 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
1062 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError());
1063 CloseHandle( file );
1065 /* NOTE: for this test to succeed, there must be no subdirectories
1066 under the current directory. In addition, there must be at least
1067 one file that fits the wildcard w*.c . Normally, the test
1068 directory itself satisfies both conditions.
1071 hInst = GetModuleHandleA(0);
1072 if (!RegisterListboxWindowClass(hInst)) assert(0);
1073 hWnd = CreateWindow("ListboxContainerClass", "ListboxContainerClass",
1074 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1075 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1076 NULL, NULL, hInst, 0);
1077 assert(hWnd);
1079 /* Test for standard usage */
1081 /* The following should be overwritten by the directory path */
1082 SendMessage(g_label, WM_SETTEXT, 0, (LPARAM)"default contents");
1084 /* This should list all the w*.c files in the test directory
1085 * As of this writing, this includes win.c, winstation.c, wsprintf.c
1087 strcpy(pathBuffer, "w*.c");
1088 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1089 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError());
1091 /* Path specification gets converted to uppercase */
1092 ok (!strcmp(pathBuffer, "W*.C"),
1093 "expected conversion to uppercase, got %s\n", pathBuffer);
1095 /* Loaded path should have overwritten the label text */
1096 SendMessage(g_label, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)pathBuffer);
1097 trace("Static control after DlgDirList: %s\n", pathBuffer);
1098 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n");
1100 /* There should be some content in the listbox */
1101 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1102 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n");
1103 itemCount_justFiles = itemCount;
1105 /* Every single item in the control should start with a w and end in .c */
1106 for (i = 0; i < itemCount; i++) {
1107 memset(pathBuffer, 0, MAX_PATH);
1108 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1109 p = pathBuffer + strlen(pathBuffer);
1110 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1111 (*(p-1) == 'c' || *(p-1) == 'C') &&
1112 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1115 /* Test behavior when no files match the wildcard */
1116 strcpy(pathBuffer, BAD_EXTENSION);
1117 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0);
1118 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res);
1120 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1121 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n");
1123 /* Test DDL_DIRECTORY */
1124 strcpy(pathBuffer, "w*.c");
1125 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1126 DDL_DIRECTORY);
1127 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError());
1129 /* There should be some content in the listbox. In particular, there should
1130 * be exactly one more element than before, since the string "[..]" should
1131 * have been added.
1133 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1134 ok (itemCount == itemCount_justFiles + 1,
1135 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected %d\n",
1136 itemCount, itemCount_justFiles + 1);
1138 /* Every single item in the control should start with a w and end in .c,
1139 * except for the "[..]" string, which should appear exactly as it is.
1141 for (i = 0; i < itemCount; i++) {
1142 memset(pathBuffer, 0, MAX_PATH);
1143 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1144 p = pathBuffer + strlen(pathBuffer);
1145 ok( !strcmp(pathBuffer, "[..]") ||
1146 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1147 (*(p-1) == 'c' || *(p-1) == 'C') &&
1148 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1151 /* Test behavior when no files match the wildcard */
1152 strcpy(pathBuffer, BAD_EXTENSION);
1153 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1154 DDL_DIRECTORY);
1155 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res);
1157 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1158 ok (itemCount == 1, "DlgDirList() incorrectly filled the listbox! (expected 1 got %d)\n",
1159 itemCount);
1160 for (i = 0; i < itemCount; i++) {
1161 memset(pathBuffer, 0, MAX_PATH);
1162 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1163 p = pathBuffer + strlen(pathBuffer);
1164 ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit requested [..]\n", i, pathBuffer);
1168 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */
1169 strcpy(pathBuffer, "w*.c");
1170 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1171 DDL_DRIVES);
1172 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1174 /* There should be some content in the listbox. In particular, there should
1175 * be at least one element before, since the string "[-c-]" should
1176 * have been added. Depending on the user setting, more drives might have
1177 * been added.
1179 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1180 ok (itemCount >= 1,
1181 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n",
1182 itemCount, 1);
1183 itemCount_justDrives = itemCount;
1185 /* Every single item in the control should fit the format [-c-] */
1186 for (i = 0; i < itemCount; i++) {
1187 memset(pathBuffer, 0, MAX_PATH);
1188 driveletter = '\0';
1189 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1190 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" );
1191 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer);
1192 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1193 if (!(driveletter >= 'a' && driveletter <= 'z')) {
1194 /* Correct after invalid entry is found */
1195 trace("removing count of invalid entry %s\n", pathBuffer);
1196 itemCount_justDrives--;
1200 /* Test behavior when no files match the wildcard */
1201 strcpy(pathBuffer, BAD_EXTENSION);
1202 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1203 DDL_DRIVES);
1204 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1206 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1207 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n");
1210 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */
1211 strcpy(pathBuffer, "w*.c");
1212 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1213 DDL_DIRECTORY|DDL_DRIVES);
1214 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1216 /* There should be some content in the listbox. In particular, there should
1217 * be exactly the number of plain files, plus the number of mapped drives,
1218 * plus one "[..]"
1220 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1221 ok (itemCount == itemCount_justFiles + itemCount_justDrives + 1,
1222 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n",
1223 itemCount, itemCount_justFiles + itemCount_justDrives + 1);
1225 /* Every single item in the control should start with a w and end in .c,
1226 * except for the "[..]" string, which should appear exactly as it is,
1227 * and the mapped drives in the format "[-X-]".
1229 for (i = 0; i < itemCount; i++) {
1230 memset(pathBuffer, 0, MAX_PATH);
1231 driveletter = '\0';
1232 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1233 p = pathBuffer + strlen(pathBuffer);
1234 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1235 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1236 } else {
1237 ok( !strcmp(pathBuffer, "[..]") ||
1238 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') &&
1239 (*(p-1) == 'c' || *(p-1) == 'C') &&
1240 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer);
1244 /* Test behavior when no files match the wildcard */
1245 strcpy(pathBuffer, BAD_EXTENSION);
1246 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1247 DDL_DIRECTORY|DDL_DRIVES);
1248 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res);
1250 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1251 ok (itemCount == itemCount_justDrives + 1,
1252 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n",
1253 itemCount_justDrives + 1, itemCount);
1257 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */
1258 strcpy(pathBuffer, "w*.c");
1259 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1260 DDL_DIRECTORY|DDL_EXCLUSIVE);
1261 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1263 /* There should be exactly one element: "[..]" */
1264 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1265 ok (itemCount == 1,
1266 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1267 itemCount, 1);
1269 memset(pathBuffer, 0, MAX_PATH);
1270 SendMessage(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer);
1271 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n");
1274 /* Test behavior when no files match the wildcard */
1275 strcpy(pathBuffer, BAD_EXTENSION);
1276 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1277 DDL_DIRECTORY|DDL_EXCLUSIVE);
1278 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1280 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1281 ok (itemCount == 1, "DlgDirList() incorrectly filled the listbox!\n");
1284 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */
1285 strcpy(pathBuffer, "w*.c");
1286 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1287 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1288 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError());
1290 /* There should be no plain files on the listbox */
1291 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1292 ok (itemCount == itemCount_justDrives + 1,
1293 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n",
1294 itemCount, itemCount_justDrives + 1);
1296 for (i = 0; i < itemCount; i++) {
1297 memset(pathBuffer, 0, MAX_PATH);
1298 driveletter = '\0';
1299 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer);
1300 p = pathBuffer + strlen(pathBuffer);
1301 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) {
1302 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter);
1303 } else {
1304 ok( !strcmp(pathBuffer, "[..]"), "Element %d (%s) does not fit expected [..]\n", i, pathBuffer);
1308 /* Test behavior when no files match the wildcard */
1309 strcpy(pathBuffer, BAD_EXTENSION);
1310 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1311 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE);
1312 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res);
1314 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1315 ok (itemCount == itemCount_justDrives + 1, "DlgDirList() incorrectly filled the listbox!\n");
1318 /* Now test DlgDirSelectEx() in normal operation */
1319 /* Fill with everything - drives, directory and all plain files. */
1320 strcpy(pathBuffer, "*");
1321 res = DlgDirList(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL,
1322 DDL_DIRECTORY|DDL_DRIVES);
1323 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError());
1325 SendMessage(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */
1326 memset(pathBuffer, 0, MAX_PATH);
1327 SetLastError(0xdeadbeef);
1328 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1329 ok (GetLastError() == 0xdeadbeef,
1330 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n",
1331 GetLastError());
1332 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res);
1333 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */
1335 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer);
1337 /* Test proper drive/dir/file recognition */
1338 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1339 for (i = 0; i < itemCount; i++) {
1340 memset(itemBuffer, 0, MAX_PATH);
1341 memset(pathBuffer, 0, MAX_PATH);
1342 memset(tempBuffer, 0, MAX_PATH);
1343 driveletter = '\0';
1344 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1345 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1346 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1347 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1348 /* Current item is a drive letter */
1349 SetLastError(0xdeadbeef);
1350 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1351 ok (GetLastError() == 0xdeadbeef,
1352 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1353 i, GetLastError());
1354 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1356 /* For drive letters, DlgDirSelectEx tacks on a colon */
1357 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1358 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1359 } else if (itemBuffer[0] == '[') {
1360 /* Current item is the parent directory */
1361 SetLastError(0xdeadbeef);
1362 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1363 ok (GetLastError() == 0xdeadbeef,
1364 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1365 i, GetLastError());
1366 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1368 /* For directories, DlgDirSelectEx tacks on a backslash */
1369 p = pathBuffer + strlen(pathBuffer);
1370 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1372 tempBuffer[0] = '[';
1373 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1374 strcat(tempBuffer, "]");
1375 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1376 } else {
1377 /* Current item is a plain file */
1378 SetLastError(0xdeadbeef);
1379 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1380 ok (GetLastError() == 0xdeadbeef,
1381 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1382 i, GetLastError());
1383 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1385 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects
1386 * for example, "Makefile", which gets reported as "Makefile."
1388 strcpy(tempBuffer, itemBuffer);
1389 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1390 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1394 /* Now test DlgDirSelectEx() in abnormal operation */
1395 /* Fill list with bogus entries, that look somewhat valid */
1396 SendMessage(g_listBox, LB_RESETCONTENT, 0, 0);
1397 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]");
1398 SendMessage(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil");
1399 itemCount = SendMessage(g_listBox, LB_GETCOUNT, 0, 0);
1400 for (i = 0; i < itemCount; i++) {
1401 memset(itemBuffer, 0, MAX_PATH);
1402 memset(pathBuffer, 0, MAX_PATH);
1403 memset(tempBuffer, 0, MAX_PATH);
1404 driveletter = '\0';
1405 SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer);
1406 res = SendMessage(g_listBox, LB_SETCURSEL, i, 0);
1407 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i);
1408 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) {
1409 /* Current item is a drive letter */
1410 SetLastError(0xdeadbeef);
1411 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1412 ok (GetLastError() == 0xdeadbeef,
1413 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1414 i, GetLastError());
1415 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1417 /* For drive letters, DlgDirSelectEx tacks on a colon */
1418 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0',
1419 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter);
1420 } else if (itemBuffer[0] == '[') {
1421 /* Current item is the parent directory */
1422 SetLastError(0xdeadbeef);
1423 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1424 ok (GetLastError() == 0xdeadbeef,
1425 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1426 i, GetLastError());
1427 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer);
1429 /* For directories, DlgDirSelectEx tacks on a backslash */
1430 p = pathBuffer + strlen(pathBuffer);
1431 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer);
1433 tempBuffer[0] = '[';
1434 strncpy(tempBuffer + 1, pathBuffer, strlen(pathBuffer) - 1);
1435 strcat(tempBuffer, "]");
1436 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer);
1437 } else {
1438 /* Current item is a plain file */
1439 SetLastError(0xdeadbeef);
1440 res = DlgDirSelectEx(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX);
1441 ok (GetLastError() == 0xdeadbeef,
1442 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n",
1443 i, GetLastError());
1444 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer);
1446 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension.
1447 * This affects for example, "Makefile", which gets reported as "Makefile."
1449 strcpy(tempBuffer, itemBuffer);
1450 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, ".");
1451 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer);
1454 DestroyWindow(hWnd);
1456 DeleteFileA( "wtest1.tmp.c" );
1459 START_TEST(listbox)
1461 const struct listbox_test SS =
1462 /* {add_style} */
1463 {{0},
1464 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1465 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1466 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1467 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1468 /* {selected, anchor, caret, selcount}{TODO fields} */
1469 const struct listbox_test SS_NS =
1470 {{LBS_NOSEL},
1471 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1472 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1473 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1474 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1475 const struct listbox_test MS =
1476 {{LBS_MULTIPLESEL},
1477 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1478 { 1, 1, 1, 1}, {0,0,0,0},
1479 { 2, 1, 2, 1}, {0,0,0,0},
1480 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1481 const struct listbox_test MS_NS =
1482 {{LBS_MULTIPLESEL | LBS_NOSEL},
1483 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1484 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1485 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1486 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1487 const struct listbox_test ES =
1488 {{LBS_EXTENDEDSEL},
1489 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1490 { 1, 1, 1, 1}, {0,0,0,0},
1491 { 2, 2, 2, 1}, {0,0,0,0},
1492 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1493 const struct listbox_test ES_NS =
1494 {{LBS_EXTENDEDSEL | LBS_NOSEL},
1495 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1496 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1497 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1498 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1499 const struct listbox_test EMS =
1500 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL},
1501 { 0, LB_ERR, 0, 0}, {0,0,0,0},
1502 { 1, 1, 1, 1}, {0,0,0,0},
1503 { 2, 2, 2, 1}, {0,0,0,0},
1504 { 0, LB_ERR, 0, 2}, {0,0,0,0}};
1505 const struct listbox_test EMS_NS =
1506 {{LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL},
1507 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
1508 { 1, 1, 1, LB_ERR}, {0,0,0,0},
1509 { 2, 2, 2, LB_ERR}, {0,0,0,0},
1510 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}};
1512 trace (" Testing single selection...\n");
1513 check (SS);
1514 trace (" ... with NOSEL\n");
1515 check (SS_NS);
1516 trace (" Testing multiple selection...\n");
1517 check (MS);
1518 trace (" ... with NOSEL\n");
1519 check (MS_NS);
1520 trace (" Testing extended selection...\n");
1521 check (ES);
1522 trace (" ... with NOSEL\n");
1523 check (ES_NS);
1524 trace (" Testing extended and multiple selection...\n");
1525 check (EMS);
1526 trace (" ... with NOSEL\n");
1527 check (EMS_NS);
1529 check_item_height();
1530 test_ownerdraw();
1531 test_selection();
1532 test_listbox_height();
1533 test_itemfrompoint();
1534 test_listbox_item_data();
1535 test_listbox_LB_DIR();
1536 test_listbox_dlgdir();