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 <assert.h> 21 #include <stdarg.h> 22 #include <stdio.h> 23 24 #include "windef.h" 25 #include "winbase.h" 26 #include "wingdi.h" 27 #include "winuser.h" 28 #include "winnls.h" 29 30 #include "wine/test.h" 31 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 39 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." 45 }; 46 47 static const char BAD_EXTENSION[] = "*.badtxt"; 48 49 static int strcmp_aw(LPCWSTR strw, const char *stra) 50 { 51 WCHAR buf[1024]; 52 53 if (!stra) return 1; 54 MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf)); 55 return lstrcmpW(strw, buf); 56 } 57 58 static HWND 59 create_listbox (DWORD add_style, HWND parent) 60 { 61 HWND handle; 62 INT_PTR ctl_id=0; 63 if (parent) 64 ctl_id=1; 65 handle=CreateWindowA("LISTBOX", "TestList", 66 (LBS_STANDARD & ~LBS_SORT) | add_style, 67 0, 0, 100, 100, 68 parent, (HMENU)ctl_id, NULL, 0); 69 70 assert (handle); 71 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[0]); 72 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[1]); 73 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[2]); 74 SendMessageA(handle, LB_ADDSTRING, 0, (LPARAM) strings[3]); 75 76 #ifdef VISIBLE 77 ShowWindow (handle, SW_SHOW); 78 #endif 79 REDRAW; 80 81 return handle; 82 } 83 84 struct listbox_prop { 85 DWORD add_style; 86 }; 87 88 struct listbox_stat { 89 int selected, anchor, caret, selcount; 90 }; 91 92 struct listbox_test { 93 struct listbox_stat init, init_todo; 94 struct listbox_stat click, click_todo; 95 struct listbox_stat step, step_todo; 96 struct listbox_stat sel, sel_todo; 97 }; 98 99 static void 100 listbox_query (HWND handle, struct listbox_stat *results) 101 { 102 results->selected = SendMessageA(handle, LB_GETCURSEL, 0, 0); 103 results->anchor = SendMessageA(handle, LB_GETANCHORINDEX, 0, 0); 104 results->caret = SendMessageA(handle, LB_GETCARETINDEX, 0, 0); 105 results->selcount = SendMessageA(handle, LB_GETSELCOUNT, 0, 0); 106 } 107 108 static void 109 buttonpress (HWND handle, WORD x, WORD y) 110 { 111 LPARAM lp=x+(y<<16); 112 113 WAIT; 114 SendMessageA(handle, WM_LBUTTONDOWN, MK_LBUTTON, lp); 115 SendMessageA(handle, WM_LBUTTONUP, 0, lp); 116 REDRAW; 117 } 118 119 static void 120 keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended) 121 { 122 LPARAM lp=1+(scancode<<16)+(extended?KEYEVENTF_EXTENDEDKEY:0); 123 124 WAIT; 125 SendMessageA(handle, WM_KEYDOWN, keycode, lp); 126 SendMessageA(handle, WM_KEYUP , keycode, lp | 0xc000000); 127 REDRAW; 128 } 129 130 #define listbox_field_ok(t, s, f, got) \ 131 ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \ 132 ": expected %d, got %d\n", style, t.s.f, got.f) 133 134 #define listbox_todo_field_ok(t, s, f, got) \ 135 todo_wine_if (t.s##_todo.f) { listbox_field_ok(t, s, f, got); } 136 137 #define listbox_ok(t, s, got) \ 138 listbox_todo_field_ok(t, s, selected, got); \ 139 listbox_todo_field_ok(t, s, anchor, got); \ 140 listbox_todo_field_ok(t, s, caret, got); \ 141 listbox_todo_field_ok(t, s, selcount, got) 142 143 static void 144 check (DWORD style, const struct listbox_test test) 145 { 146 struct listbox_stat answer; 147 RECT second_item; 148 int i; 149 int res; 150 HWND hLB; 151 152 hLB = create_listbox (style, 0); 153 154 listbox_query (hLB, &answer); 155 listbox_ok (test, init, answer); 156 157 SendMessageA(hLB, LB_GETITEMRECT, 1, (LPARAM) &second_item); 158 buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top); 159 160 listbox_query (hLB, &answer); 161 listbox_ok (test, click, answer); 162 163 keypress (hLB, VK_DOWN, 0x50, TRUE); 164 165 listbox_query (hLB, &answer); 166 listbox_ok (test, step, answer); 167 168 DestroyWindow (hLB); 169 hLB = create_listbox(style, 0); 170 171 SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2)); 172 listbox_query (hLB, &answer); 173 listbox_ok (test, sel, answer); 174 175 for (i = 0; i < 4 && !(style & LBS_NODATA); i++) { 176 DWORD size = SendMessageA(hLB, LB_GETTEXTLEN, i, 0); 177 CHAR *txt; 178 WCHAR *txtw; 179 int resA, resW; 180 181 txt = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, size+1); 182 resA=SendMessageA(hLB, LB_GETTEXT, i, (LPARAM)txt); 183 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]); 184 185 txtw = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, 2*size+2); 186 resW=SendMessageW(hLB, LB_GETTEXT, i, (LPARAM)txtw); 187 ok(resA == resW, "Unexpected text length.\n"); 188 WideCharToMultiByte( CP_ACP, 0, txtw, -1, txt, size, NULL, NULL ); 189 ok(!strcmp (txt, strings[i]), "returned string for item %d does not match %s vs %s\n", i, txt, strings[i]); 190 191 HeapFree (GetProcessHeap(), 0, txtw); 192 HeapFree (GetProcessHeap(), 0, txt); 193 } 194 195 /* Confirm the count of items, and that an invalid delete does not remove anything */ 196 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0); 197 ok((res==4), "Expected 4 items, got %d\n", res); 198 res = SendMessageA(hLB, LB_DELETESTRING, -1, 0); 199 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res); 200 res = SendMessageA(hLB, LB_DELETESTRING, 4, 0); 201 ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res); 202 res = SendMessageA(hLB, LB_GETCOUNT, 0, 0); 203 ok((res==4), "Expected 4 items, got %d\n", res); 204 205 WAIT; 206 DestroyWindow (hLB); 207 } 208 209 static void check_item_height(void) 210 { 211 HWND hLB; 212 HDC hdc; 213 HFONT font; 214 TEXTMETRICA tm; 215 INT itemHeight; 216 217 hLB = create_listbox (0, 0); 218 ok ((hdc = GetDCEx( hLB, 0, DCX_CACHE )) != 0, "Can't get hdc\n"); 219 ok ((font = GetCurrentObject(hdc, OBJ_FONT)) != 0, "Can't get the current font\n"); 220 ok (GetTextMetricsA( hdc, &tm ), "Can't read font metrics\n"); 221 ReleaseDC( hLB, hdc); 222 223 ok (SendMessageA(hLB, WM_SETFONT, (WPARAM)font, 0) == 0, "Can't set font\n"); 224 225 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0); 226 ok (itemHeight == tm.tmHeight, "Item height wrong, got %d, expecting %d\n", itemHeight, tm.tmHeight); 227 228 DestroyWindow (hLB); 229 230 hLB = CreateWindowA("LISTBOX", "TestList", LBS_OWNERDRAWVARIABLE, 231 0, 0, 100, 100, NULL, NULL, NULL, 0); 232 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0); 233 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight); 234 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, 5, 0); 235 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight); 236 itemHeight = SendMessageA(hLB, LB_GETITEMHEIGHT, -5, 0); 237 ok(itemHeight == tm.tmHeight, "itemHeight %d\n", itemHeight); 238 DestroyWindow (hLB); 239 } 240 241 static int got_selchange; 242 243 static LRESULT WINAPI main_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 244 { 245 switch (msg) 246 { 247 case WM_MEASUREITEM: 248 { 249 DWORD style = GetWindowLongA(GetWindow(hwnd, GW_CHILD), GWL_STYLE); 250 MEASUREITEMSTRUCT *mi = (void*)lparam; 251 252 ok(wparam == mi->CtlID, "got wParam=%08lx, expected %08x\n", wparam, mi->CtlID); 253 ok(mi->CtlType == ODT_LISTBOX, "mi->CtlType = %u\n", mi->CtlType); 254 ok(mi->CtlID == 1, "mi->CtlID = %u\n", mi->CtlID); 255 ok(mi->itemHeight, "mi->itemHeight = 0\n"); 256 257 if (mi->itemID > 4 || style & LBS_OWNERDRAWFIXED) 258 break; 259 260 if (style & LBS_HASSTRINGS) 261 { 262 ok(!strcmp_aw((WCHAR*)mi->itemData, strings[mi->itemID]), 263 "mi->itemData = %s (%d)\n", wine_dbgstr_w((WCHAR*)mi->itemData), mi->itemID); 264 } 265 else 266 { 267 ok((void*)mi->itemData == strings[mi->itemID], 268 "mi->itemData = %08lx, expected %p\n", mi->itemData, strings[mi->itemID]); 269 } 270 break; 271 } 272 case WM_DRAWITEM: 273 { 274 RECT rc_item, rc_client, rc_clip; 275 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lparam; 276 277 trace("%p WM_DRAWITEM %08lx %08lx\n", hwnd, wparam, lparam); 278 279 ok(wparam == dis->CtlID, "got wParam=%08lx instead of %08x\n", 280 wparam, dis->CtlID); 281 ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType); 282 283 GetClientRect(dis->hwndItem, &rc_client); 284 trace("hwndItem %p client rect %s\n", dis->hwndItem, wine_dbgstr_rect(&rc_client)); 285 GetClipBox(dis->hDC, &rc_clip); 286 trace("clip rect %s\n", wine_dbgstr_rect(&rc_clip)); 287 ok(EqualRect(&rc_client, &rc_clip) || IsRectEmpty(&rc_clip), 288 "client rect of the listbox should be equal to the clip box," 289 "or the clip box should be empty\n"); 290 291 trace("rcItem %s\n", wine_dbgstr_rect(&dis->rcItem)); 292 SendMessageA(dis->hwndItem, LB_GETITEMRECT, dis->itemID, (LPARAM)&rc_item); 293 trace("item rect %s\n", wine_dbgstr_rect(&rc_item)); 294 ok(EqualRect(&dis->rcItem, &rc_item), "item rects are not equal\n"); 295 296 break; 297 } 298 299 case WM_COMMAND: 300 if (HIWORD( wparam ) == LBN_SELCHANGE) got_selchange++; 301 break; 302 303 default: 304 break; 305 } 306 307 return DefWindowProcA(hwnd, msg, wparam, lparam); 308 } 309 310 static HWND create_parent( void ) 311 { 312 WNDCLASSA cls; 313 HWND parent; 314 static ATOM class; 315 316 if (!class) 317 { 318 cls.style = 0; 319 cls.lpfnWndProc = main_window_proc; 320 cls.cbClsExtra = 0; 321 cls.cbWndExtra = 0; 322 cls.hInstance = GetModuleHandleA(NULL); 323 cls.hIcon = 0; 324 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 325 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 326 cls.lpszMenuName = NULL; 327 cls.lpszClassName = "main_window_class"; 328 class = RegisterClassA( &cls ); 329 } 330 331 parent = CreateWindowExA(0, "main_window_class", NULL, 332 WS_POPUP | WS_VISIBLE, 333 100, 100, 400, 400, 334 GetDesktopWindow(), 0, 335 GetModuleHandleA(NULL), NULL); 336 return parent; 337 } 338 339 static void test_ownerdraw(void) 340 { 341 static const DWORD styles[] = 342 { 343 0, 344 LBS_NODATA 345 }; 346 HWND parent, hLB; 347 INT ret; 348 RECT rc; 349 UINT i; 350 351 parent = create_parent(); 352 assert(parent); 353 354 for (i = 0; i < ARRAY_SIZE(styles); i++) 355 { 356 hLB = create_listbox(LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE | styles[i], parent); 357 assert(hLB); 358 359 SetForegroundWindow(hLB); 360 UpdateWindow(hLB); 361 362 /* make height short enough */ 363 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc); 364 SetWindowPos(hLB, 0, 0, 0, 100, rc.bottom - rc.top + 1, 365 SWP_NOZORDER | SWP_NOMOVE); 366 367 /* make 0 item invisible */ 368 SendMessageA(hLB, LB_SETTOPINDEX, 1, 0); 369 ret = SendMessageA(hLB, LB_GETTOPINDEX, 0, 0); 370 ok(ret == 1, "wrong top index %d\n", ret); 371 372 SendMessageA(hLB, LB_GETITEMRECT, 0, (LPARAM)&rc); 373 trace("item 0 rect %s\n", wine_dbgstr_rect(&rc)); 374 ok(!IsRectEmpty(&rc), "empty item rect\n"); 375 ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top); 376 377 DestroyWindow(hLB); 378 379 /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */ 380 hLB = CreateWindowA("listbox", "TestList", LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE | styles[i], 381 0, 0, 100, 100, NULL, NULL, NULL, 0); 382 ok(hLB != NULL, "last error 0x%08x\n", GetLastError()); 383 384 ok(GetWindowLongA(hLB, GWL_STYLE) & LBS_OWNERDRAWVARIABLE, "Unexpected window style.\n"); 385 386 ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0); 387 ok(ret == 0, "Unexpected return value %d.\n", ret); 388 ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0); 389 ok(ret == 1, "Unexpected return value %d.\n", ret); 390 391 ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 13); 392 ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret); 393 394 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0); 395 ok(ret == 13, "Unexpected item height %d.\n", ret); 396 397 ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 1, 42); 398 ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret); 399 400 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0); 401 ok(ret == 42, "Unexpected item height %d.\n", ret); 402 403 ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 1, 0); 404 ok(ret == 42, "Unexpected item height %d.\n", ret); 405 406 DestroyWindow (hLB); 407 } 408 DestroyWindow(parent); 409 } 410 411 #define listbox_test_query(exp, got) \ 412 ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \ 413 ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \ 414 ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \ 415 ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount); 416 417 static void test_LB_SELITEMRANGE(void) 418 { 419 static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 }; 420 static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 }; 421 static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 }; 422 static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 }; 423 HWND hLB; 424 struct listbox_stat answer; 425 INT ret; 426 427 trace("testing LB_SELITEMRANGE\n"); 428 429 hLB = create_listbox(LBS_EXTENDEDSEL, 0); 430 assert(hLB); 431 432 listbox_query(hLB, &answer); 433 listbox_test_query(test_nosel, answer); 434 435 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2)); 436 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret); 437 listbox_query(hLB, &answer); 438 listbox_test_query(test_1, answer); 439 440 SendMessageA(hLB, LB_SETSEL, FALSE, -1); 441 listbox_query(hLB, &answer); 442 listbox_test_query(test_nosel, answer); 443 444 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4)); 445 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret); 446 listbox_query(hLB, &answer); 447 listbox_test_query(test_3, answer); 448 449 SendMessageA(hLB, LB_SETSEL, FALSE, -1); 450 listbox_query(hLB, &answer); 451 listbox_test_query(test_nosel, answer); 452 453 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5)); 454 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret); 455 listbox_query(hLB, &answer); 456 listbox_test_query(test_nosel, answer); 457 458 SendMessageA(hLB, LB_SETSEL, FALSE, -1); 459 listbox_query(hLB, &answer); 460 listbox_test_query(test_nosel, answer); 461 462 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10)); 463 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret); 464 listbox_query(hLB, &answer); 465 listbox_test_query(test_1, answer); 466 467 SendMessageA(hLB, LB_SETSEL, FALSE, -1); 468 listbox_query(hLB, &answer); 469 listbox_test_query(test_nosel, answer); 470 471 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10)); 472 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret); 473 listbox_query(hLB, &answer); 474 listbox_test_query(test_nosel, answer); 475 476 SendMessageA(hLB, LB_SETSEL, FALSE, -1); 477 listbox_query(hLB, &answer); 478 listbox_test_query(test_nosel, answer); 479 480 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1)); 481 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret); 482 listbox_query(hLB, &answer); 483 listbox_test_query(test_2, answer); 484 485 SendMessageA(hLB, LB_SETSEL, FALSE, -1); 486 listbox_query(hLB, &answer); 487 listbox_test_query(test_nosel, answer); 488 489 ret = SendMessageA(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1)); 490 ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret); 491 listbox_query(hLB, &answer); 492 listbox_test_query(test_2, answer); 493 494 DestroyWindow(hLB); 495 } 496 497 static void test_LB_SETCURSEL(void) 498 { 499 HWND parent, hLB; 500 INT ret; 501 502 trace("testing LB_SETCURSEL\n"); 503 504 parent = create_parent(); 505 assert(parent); 506 507 hLB = create_listbox(LBS_NOINTEGRALHEIGHT | WS_CHILD, parent); 508 assert(hLB); 509 510 SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 32); 511 512 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0); 513 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 514 515 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0); 516 ok(ret == 2, "LB_SETCURSEL returned %d instead of 2\n", ret); 517 ret = GetScrollPos(hLB, SB_VERT); 518 ok(ret == 0, "expected vscroll 0, got %d\n", ret); 519 520 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0); 521 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 522 523 ret = SendMessageA(hLB, LB_SETCURSEL, 3, 0); 524 ok(ret == 3, "LB_SETCURSEL returned %d instead of 3\n", ret); 525 ret = GetScrollPos(hLB, SB_VERT); 526 ok(ret == 1, "expected vscroll 1, got %d\n", ret); 527 528 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0); 529 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 530 531 DestroyWindow(hLB); 532 533 hLB = create_listbox(0, 0); 534 ok(hLB != NULL, "Failed to create ListBox window.\n"); 535 536 ret = SendMessageA(hLB, LB_SETCURSEL, 1, 0); 537 ok(ret == 1, "Unexpected return value %d.\n", ret); 538 539 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0); 540 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 541 542 DestroyWindow(hLB); 543 544 /* LBS_EXTENDEDSEL */ 545 hLB = create_listbox(LBS_EXTENDEDSEL, 0); 546 ok(hLB != NULL, "Failed to create ListBox window.\n"); 547 548 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0); 549 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 550 551 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0); 552 ok(ret == -1, "Unexpected return value %d.\n", ret); 553 554 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0); 555 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 556 557 DestroyWindow(hLB); 558 559 /* LBS_MULTIPLESEL */ 560 hLB = create_listbox(LBS_MULTIPLESEL, 0); 561 ok(hLB != NULL, "Failed to create ListBox window.\n"); 562 563 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0); 564 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 565 566 ret = SendMessageA(hLB, LB_SETCURSEL, 2, 0); 567 ok(ret == -1, "Unexpected return value %d.\n", ret); 568 569 ret = SendMessageA(hLB, LB_GETANCHORINDEX, 0, 0); 570 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 571 572 DestroyWindow(hLB); 573 } 574 575 static void test_LB_SETSEL(void) 576 { 577 HWND list; 578 int ret; 579 580 /* LBS_EXTENDEDSEL */ 581 list = create_listbox(LBS_EXTENDEDSEL, 0); 582 ok(list != NULL, "Failed to create ListBox window.\n"); 583 584 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0); 585 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 586 587 ret = SendMessageA(list, LB_SETSEL, TRUE, 0); 588 ok(ret == 0, "Unexpected return value %d.\n", ret); 589 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0); 590 ok(ret == 0, "Unexpected anchor index %d.\n", ret); 591 592 ret = SendMessageA(list, LB_SETSEL, TRUE, 1); 593 ok(ret == 0, "Unexpected return value %d.\n", ret); 594 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0); 595 ok(ret == 1, "Unexpected anchor index %d.\n", ret); 596 597 ret = SendMessageA(list, LB_SETSEL, FALSE, 1); 598 ok(ret == 0, "Unexpected return value %d.\n", ret); 599 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0); 600 ok(ret == 1, "Unexpected anchor index %d.\n", ret); 601 602 DestroyWindow(list); 603 604 /* LBS_MULTIPLESEL */ 605 list = create_listbox(LBS_MULTIPLESEL, 0); 606 ok(list != NULL, "Failed to create ListBox window.\n"); 607 608 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0); 609 ok(ret == -1, "Unexpected anchor index %d.\n", ret); 610 611 ret = SendMessageA(list, LB_SETSEL, TRUE, 0); 612 ok(ret == 0, "Unexpected return value %d.\n", ret); 613 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0); 614 ok(ret == 0, "Unexpected anchor index %d.\n", ret); 615 616 ret = SendMessageA(list, LB_SETSEL, TRUE, 1); 617 ok(ret == 0, "Unexpected return value %d.\n", ret); 618 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0); 619 ok(ret == 1, "Unexpected anchor index %d.\n", ret); 620 621 ret = SendMessageA(list, LB_SETSEL, FALSE, 1); 622 ok(ret == 0, "Unexpected return value %d.\n", ret); 623 ret = SendMessageA(list, LB_GETANCHORINDEX, 0, 0); 624 ok(ret == 1, "Unexpected anchor index %d.\n", ret); 625 626 DestroyWindow(list); 627 } 628 629 static void test_listbox_height(void) 630 { 631 HWND hList; 632 int r, id; 633 634 hList = CreateWindowA( "ListBox", "list test", 0, 635 1, 1, 600, 100, NULL, NULL, NULL, NULL ); 636 ok( hList != NULL, "failed to create listbox\n"); 637 638 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi"); 639 ok( id == 0, "item id wrong\n"); 640 641 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 )); 642 ok( r == 0, "send message failed\n"); 643 644 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 ); 645 ok( r == 20, "height wrong\n"); 646 647 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 )); 648 ok( r == -1, "send message failed\n"); 649 650 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 ); 651 ok( r == 20, "height wrong\n"); 652 653 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 )); 654 ok( r == -1, "send message failed\n"); 655 656 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 ); 657 ok( r == 20, "height wrong\n"); 658 659 r = SendMessageA( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 )); 660 ok( r == 0, "send message failed\n"); 661 662 r = SendMessageA(hList, LB_GETITEMHEIGHT, 0, 0 ); 663 ok( r == 0xff, "height wrong\n"); 664 665 DestroyWindow( hList ); 666 } 667 668 static void test_changing_selection_styles(void) 669 { 670 static const DWORD styles[] = 671 { 672 0, 673 LBS_NODATA | LBS_OWNERDRAWFIXED 674 }; 675 static const DWORD selstyles[] = 676 { 677 0, 678 LBS_MULTIPLESEL, 679 LBS_EXTENDEDSEL, 680 LBS_MULTIPLESEL | LBS_EXTENDEDSEL 681 }; 682 static const LONG selexpect_single[] = { 0, 0, 1 }; 683 static const LONG selexpect_single2[] = { 1, 0, 0 }; 684 static const LONG selexpect_multi[] = { 1, 0, 1 }; 685 static const LONG selexpect_multi2[] = { 1, 1, 0 }; 686 687 HWND parent, listbox; 688 DWORD style; 689 LONG ret; 690 UINT i, j, k; 691 692 parent = create_parent(); 693 ok(parent != NULL, "Failed to create parent window.\n"); 694 for (i = 0; i < ARRAY_SIZE(styles); i++) 695 { 696 /* Test if changing selection styles affects selection storage */ 697 for (j = 0; j < ARRAY_SIZE(selstyles); j++) 698 { 699 LONG setcursel_expect, selitemrange_expect, getselcount_expect; 700 const LONG *selexpect; 701 702 listbox = CreateWindowA("listbox", "TestList", styles[i] | selstyles[j] | WS_CHILD | WS_VISIBLE, 703 0, 0, 100, 100, parent, (HMENU)1, NULL, 0); 704 ok(listbox != NULL, "%u: Failed to create ListBox window.\n", j); 705 706 if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) 707 { 708 setcursel_expect = LB_ERR; 709 selitemrange_expect = LB_OKAY; 710 getselcount_expect = 2; 711 selexpect = selexpect_multi; 712 } 713 else 714 { 715 setcursel_expect = 2; 716 selitemrange_expect = LB_ERR; 717 getselcount_expect = LB_ERR; 718 selexpect = selexpect_single; 719 } 720 721 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++) 722 { 723 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"x"); 724 ok(ret == k, "%u: Unexpected return value %d, expected %d.\n", j, ret, k); 725 } 726 ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0); 727 ok(ret == ARRAY_SIZE(selexpect_multi), "%u: Unexpected count %d.\n", j, ret); 728 729 /* Select items with different methods */ 730 ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0); 731 ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret); 732 ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 0)); 733 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret); 734 ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 2)); 735 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret); 736 737 /* Verify that the proper items are selected */ 738 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++) 739 { 740 ret = SendMessageA(listbox, LB_GETSEL, k, 0); 741 ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n", 742 j, ret, selexpect[k]); 743 } 744 745 /* Now change the selection style */ 746 style = GetWindowLongA(listbox, GWL_STYLE); 747 ok((style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == selstyles[j], 748 "%u: unexpected window styles %#x.\n", j, style); 749 if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) 750 style &= ~selstyles[j]; 751 else 752 style |= LBS_MULTIPLESEL | LBS_EXTENDEDSEL; 753 SetWindowLongA(listbox, GWL_STYLE, style); 754 style = GetWindowLongA(listbox, GWL_STYLE); 755 ok(!(style & selstyles[j]), "%u: unexpected window styles %#x.\n", j, style); 756 757 /* Verify that the same items are selected */ 758 ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0); 759 ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n", 760 j, getselcount_expect, ret); 761 762 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++) 763 { 764 ret = SendMessageA(listbox, LB_GETSEL, k, 0); 765 ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n", 766 j, ret, selexpect[k]); 767 } 768 769 /* Lastly see if we can still change the selection as before with old style */ 770 if (setcursel_expect != LB_ERR) setcursel_expect = 0; 771 ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0); 772 ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret); 773 ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 1)); 774 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret); 775 ret = SendMessageA(listbox, LB_SELITEMRANGE, FALSE, MAKELPARAM(2, 2)); 776 ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret); 777 778 /* And verify the selections */ 779 selexpect = (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) ? selexpect_multi2 : selexpect_single2; 780 ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0); 781 ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n", 782 j, getselcount_expect, ret); 783 784 for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++) 785 { 786 ret = SendMessageA(listbox, LB_GETSEL, k, 0); 787 ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n", 788 j, ret, selexpect[k]); 789 } 790 791 DestroyWindow(listbox); 792 } 793 } 794 DestroyWindow(parent); 795 } 796 797 static void test_itemfrompoint(void) 798 { 799 /* WS_POPUP is required in order to have a more accurate size calculation ( 800 without caption). LBS_NOINTEGRALHEIGHT is required in order to test 801 behavior of partially-displayed item. 802 */ 803 HWND hList = CreateWindowA( "ListBox", "list test", 804 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT, 805 1, 1, 600, 100, NULL, NULL, NULL, NULL ); 806 ULONG r, id; 807 RECT rc; 808 809 /* For an empty listbox win2k returns 0x1ffff, win98 returns 0x10000, nt4 returns 0xffffffff */ 810 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 )); 811 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r ); 812 813 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 )); 814 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r ); 815 816 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 )); 817 ok( r == 0x1ffff || r == 0x10000 || r == 0xffffffff, "ret %x\n", r ); 818 819 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi"); 820 ok( id == 0, "item id wrong\n"); 821 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi1"); 822 ok( id == 1, "item id wrong\n"); 823 824 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 )); 825 ok( r == 0x1, "ret %x\n", r ); 826 827 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 )); 828 ok( r == 0x10001 || broken(r == 1), /* nt4 */ 829 "ret %x\n", r ); 830 831 /* Resize control so that below assertions about sizes are valid */ 832 r = SendMessageA( hList, LB_GETITEMRECT, 0, (LPARAM)&rc); 833 ok( r == 1, "ret %x\n", r); 834 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE); 835 ok( r != 0, "ret %x\n", r); 836 837 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi2"); 838 ok( id == 2, "item id wrong\n"); 839 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi3"); 840 ok( id == 3, "item id wrong\n"); 841 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi4"); 842 ok( id == 4, "item id wrong\n"); 843 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi5"); 844 ok( id == 5, "item id wrong\n"); 845 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi6"); 846 ok( id == 6, "item id wrong\n"); 847 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi7"); 848 ok( id == 7, "item id wrong\n"); 849 850 /* Set the listbox up so that id 1 is at the top, this leaves 5 851 partially visible at the bottom and 6, 7 are invisible */ 852 853 SendMessageA( hList, LB_SETTOPINDEX, 1, 0); 854 r = SendMessageA( hList, LB_GETTOPINDEX, 0, 0); 855 ok( r == 1, "top %d\n", r); 856 857 r = SendMessageA( hList, LB_GETITEMRECT, 5, (LPARAM)&rc); 858 ok( r == 1, "ret %x\n", r); 859 r = SendMessageA( hList, LB_GETITEMRECT, 6, (LPARAM)&rc); 860 ok( r == 0, "ret %x\n", r); 861 862 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) ); 863 ok( r == 1, "ret %x\n", r); 864 865 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) ); 866 ok( r == 0x10001 || broken(r == 1), /* nt4 */ 867 "ret %x\n", r ); 868 869 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) ); 870 ok( r == 0x10001 || broken(r == 1), /* nt4 */ 871 "ret %x\n", r ); 872 873 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) ); 874 ok( r == 0x10005 || broken(r == 5), /* nt4 */ 875 "item %x\n", r ); 876 877 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) ); 878 ok( r == 0x10005 || broken(r == 5), /* nt4 */ 879 "item %x\n", r ); 880 881 DestroyWindow( hList ); 882 } 883 884 static void test_listbox_item_data(void) 885 { 886 HWND hList; 887 int r, id; 888 889 hList = CreateWindowA( "ListBox", "list test", 0, 890 1, 1, 600, 100, NULL, NULL, NULL, NULL ); 891 ok( hList != NULL, "failed to create listbox\n"); 892 893 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi"); 894 ok( id == 0, "item id wrong\n"); 895 896 r = SendMessageA( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 )); 897 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r); 898 899 r = SendMessageA( hList, LB_GETITEMDATA, 0, 0); 900 ok( r == 20, "get item data failed\n"); 901 902 DestroyWindow( hList ); 903 } 904 905 static void test_listbox_LB_DIR(void) 906 { 907 char path[MAX_PATH], curdir[MAX_PATH]; 908 HWND hList; 909 int res, itemCount; 910 int itemCount_justFiles; 911 int itemCount_justDrives; 912 int itemCount_allFiles; 913 int itemCount_allDirs; 914 int i; 915 char pathBuffer[MAX_PATH]; 916 char * p; 917 char driveletter; 918 const char *wildcard = "*"; 919 HANDLE file; 920 BOOL ret; 921 922 GetCurrentDirectoryA(ARRAY_SIZE(curdir), curdir); 923 924 GetTempPathA(ARRAY_SIZE(path), path); 925 ret = SetCurrentDirectoryA(path); 926 ok(ret, "Failed to set current directory.\n"); 927 928 ret = CreateDirectoryA("lb_dir_test", NULL); 929 ok(ret, "Failed to create test directory.\n"); 930 931 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL ); 932 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError()); 933 CloseHandle( file ); 934 935 /* NOTE: for this test to succeed, there must be no subdirectories 936 under the current directory. In addition, there must be at least 937 one file that fits the wildcard w*.c . Normally, the test 938 directory itself satisfies both conditions. 939 */ 940 hList = CreateWindowA( "ListBox", "list test", WS_VISIBLE|WS_POPUP, 941 1, 1, 600, 100, NULL, NULL, NULL, NULL ); 942 assert(hList); 943 944 /* Test for standard usage */ 945 946 /* This should list all the files in the test directory. */ 947 strcpy(pathBuffer, wildcard); 948 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 949 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer); 950 if (res == -1) /* "*" wildcard doesn't work on win9x */ 951 { 952 wildcard = "*.*"; 953 strcpy(pathBuffer, wildcard); 954 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer); 955 } 956 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError()); 957 958 /* There should be some content in the listbox */ 959 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 960 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n"); 961 itemCount_allFiles = itemCount; 962 ok(res + 1 == itemCount, 963 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n", 964 itemCount - 1, res); 965 966 /* This tests behavior when no files match the wildcard */ 967 strcpy(pathBuffer, BAD_EXTENSION); 968 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 969 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer); 970 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res); 971 972 /* There should be NO content in the listbox */ 973 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 974 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n"); 975 976 977 /* This should list all the w*.c files in the test directory 978 * As of this writing, this includes win.c, winstation.c, wsprintf.c 979 */ 980 strcpy(pathBuffer, "w*.c"); 981 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 982 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer); 983 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError()); 984 985 /* Path specification does NOT converted to uppercase */ 986 ok (!strcmp(pathBuffer, "w*.c"), 987 "expected no change to pathBuffer, got %s\n", pathBuffer); 988 989 /* There should be some content in the listbox */ 990 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 991 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n"); 992 itemCount_justFiles = itemCount; 993 ok(res + 1 == itemCount, 994 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n", 995 itemCount - 1, res); 996 997 /* Every single item in the control should start with a w and end in .c */ 998 for (i = 0; i < itemCount; i++) { 999 memset(pathBuffer, 0, MAX_PATH); 1000 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1001 p = pathBuffer + strlen(pathBuffer); 1002 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1003 (*(p-1) == 'c' || *(p-1) == 'C') && 1004 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1005 } 1006 1007 /* Test DDL_DIRECTORY */ 1008 strcpy(pathBuffer, wildcard); 1009 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1010 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer); 1011 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError()); 1012 1013 /* There should be some content in the listbox. 1014 * All files plus "[..]" 1015 */ 1016 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1017 itemCount_allDirs = itemCount - itemCount_allFiles; 1018 ok (itemCount > itemCount_allFiles, 1019 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n", 1020 itemCount, itemCount_allFiles); 1021 ok(res + 1 == itemCount, 1022 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n", 1023 itemCount - 1, res); 1024 1025 /* This tests behavior when no files match the wildcard */ 1026 strcpy(pathBuffer, BAD_EXTENSION); 1027 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1028 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer); 1029 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res); 1030 1031 /* There should be NO content in the listbox */ 1032 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1033 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n"); 1034 1035 1036 /* Test DDL_DIRECTORY */ 1037 strcpy(pathBuffer, "w*.c"); 1038 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1039 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer); 1040 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError()); 1041 1042 /* There should be some content in the listbox. Since the parent directory does not 1043 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY 1044 */ 1045 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1046 ok (itemCount == itemCount_justFiles, 1047 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n", 1048 itemCount, itemCount_justFiles); 1049 ok(res + 1 == itemCount, 1050 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n", 1051 itemCount - 1, res); 1052 1053 /* Every single item in the control should start with a w and end in .c. */ 1054 for (i = 0; i < itemCount; i++) { 1055 memset(pathBuffer, 0, MAX_PATH); 1056 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1057 p = pathBuffer + strlen(pathBuffer); 1058 ok( 1059 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1060 (*(p-1) == 'c' || *(p-1) == 'C') && 1061 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1062 } 1063 1064 1065 /* Test DDL_DRIVES|DDL_EXCLUSIVE */ 1066 strcpy(pathBuffer, wildcard); 1067 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1068 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1069 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError()); 1070 1071 /* There should be some content in the listbox. In particular, there should 1072 * be at least one element before, since the string "[-c-]" should 1073 * have been added. Depending on the user setting, more drives might have 1074 * been added. 1075 */ 1076 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1077 ok (itemCount >= 1, 1078 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n", 1079 itemCount, 1); 1080 itemCount_justDrives = itemCount; 1081 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n"); 1082 1083 /* Every single item in the control should fit the format [-c-] */ 1084 for (i = 0; i < itemCount; i++) { 1085 memset(pathBuffer, 0, MAX_PATH); 1086 driveletter = '\0'; 1087 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1088 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" ); 1089 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer); 1090 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1091 if (!(driveletter >= 'a' && driveletter <= 'z')) { 1092 /* Correct after invalid entry is found */ 1093 trace("removing count of invalid entry %s\n", pathBuffer); 1094 itemCount_justDrives--; 1095 } 1096 } 1097 1098 /* This tests behavior when no files match the wildcard */ 1099 strcpy(pathBuffer, BAD_EXTENSION); 1100 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1101 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1102 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n", 1103 BAD_EXTENSION, res, itemCount_justDrives -1); 1104 1105 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1106 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n", 1107 itemCount, itemCount_justDrives); 1108 1109 trace("Files with w*.c: %d Mapped drives: %d Directories: 1\n", 1110 itemCount_justFiles, itemCount_justDrives); 1111 1112 /* Test DDL_DRIVES. */ 1113 strcpy(pathBuffer, wildcard); 1114 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1115 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer); 1116 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError()); 1117 1118 /* There should be some content in the listbox. In particular, there should 1119 * be at least one element before, since the string "[-c-]" should 1120 * have been added. Depending on the user setting, more drives might have 1121 * been added. 1122 */ 1123 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1124 ok (itemCount == itemCount_justDrives + itemCount_allFiles, 1125 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n", 1126 itemCount, itemCount_justDrives + itemCount_allFiles); 1127 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n"); 1128 1129 /* This tests behavior when no files match the wildcard */ 1130 strcpy(pathBuffer, BAD_EXTENSION); 1131 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1132 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer); 1133 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n", 1134 BAD_EXTENSION, res, itemCount_justDrives -1); 1135 1136 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1137 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1); 1138 1139 1140 /* Test DDL_DRIVES. */ 1141 strcpy(pathBuffer, "w*.c"); 1142 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1143 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer); 1144 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError()); 1145 1146 /* There should be some content in the listbox. In particular, there should 1147 * be at least one element before, since the string "[-c-]" should 1148 * have been added. Depending on the user setting, more drives might have 1149 * been added. 1150 */ 1151 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1152 ok (itemCount == itemCount_justDrives + itemCount_justFiles, 1153 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n", 1154 itemCount, itemCount_justDrives + itemCount_justFiles); 1155 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n"); 1156 1157 /* Every single item in the control should fit the format [-c-], or w*.c */ 1158 for (i = 0; i < itemCount; i++) { 1159 memset(pathBuffer, 0, MAX_PATH); 1160 driveletter = '\0'; 1161 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1162 p = pathBuffer + strlen(pathBuffer); 1163 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { 1164 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" ); 1165 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1166 } else { 1167 ok( 1168 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1169 (*(p-1) == 'c' || *(p-1) == 'C') && 1170 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1171 } 1172 } 1173 1174 1175 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */ 1176 strcpy(pathBuffer, wildcard); 1177 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1178 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer); 1179 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError()); 1180 1181 /* There should be some content in the listbox. In particular, there should 1182 * be exactly the number of plain files, plus the number of mapped drives. 1183 */ 1184 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1185 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs, 1186 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n", 1187 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs); 1188 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n"); 1189 1190 /* Every single item in the control should start with a w and end in .c, 1191 * except for the "[..]" string, which should appear exactly as it is, 1192 * and the mapped drives in the format "[-X-]". 1193 */ 1194 for (i = 0; i < itemCount; i++) { 1195 memset(pathBuffer, 0, MAX_PATH); 1196 driveletter = '\0'; 1197 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1198 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { 1199 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1200 } 1201 } 1202 1203 /* This tests behavior when no files match the wildcard */ 1204 strcpy(pathBuffer, BAD_EXTENSION); 1205 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1206 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer); 1207 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n", 1208 BAD_EXTENSION, res, itemCount_justDrives -1); 1209 1210 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1211 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1); 1212 1213 1214 1215 /* Test DDL_DIRECTORY|DDL_DRIVES. */ 1216 strcpy(pathBuffer, "w*.c"); 1217 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1218 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer); 1219 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError()); 1220 1221 /* There should be some content in the listbox. In particular, there should 1222 * be exactly the number of plain files, plus the number of mapped drives. 1223 */ 1224 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1225 ok (itemCount == itemCount_justFiles + itemCount_justDrives, 1226 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n", 1227 itemCount, itemCount_justFiles + itemCount_justDrives); 1228 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n"); 1229 1230 /* Every single item in the control should start with a w and end in .c, 1231 * except the mapped drives in the format "[-X-]". The "[..]" directory 1232 * should not appear. 1233 */ 1234 for (i = 0; i < itemCount; i++) { 1235 memset(pathBuffer, 0, MAX_PATH); 1236 driveletter = '\0'; 1237 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1238 p = pathBuffer + strlen(pathBuffer); 1239 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { 1240 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1241 } else { 1242 ok( 1243 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1244 (*(p-1) == 'c' || *(p-1) == 'C') && 1245 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1246 } 1247 } 1248 1249 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */ 1250 strcpy(pathBuffer, wildcard); 1251 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1252 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1253 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", GetLastError()); 1254 1255 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1256 ok (itemCount == itemCount_allDirs, 1257 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1258 itemCount, itemCount_allDirs); 1259 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n"); 1260 1261 if (itemCount) 1262 { 1263 memset(pathBuffer, 0, MAX_PATH); 1264 SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer); 1265 ok( !strcmp(pathBuffer, "[..]"), "First element is %s, not [..]\n", pathBuffer); 1266 } 1267 1268 /* This tests behavior when no files match the wildcard */ 1269 strcpy(pathBuffer, BAD_EXTENSION); 1270 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1271 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1272 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n", 1273 BAD_EXTENSION, res, -1); 1274 1275 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1276 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1); 1277 1278 1279 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */ 1280 strcpy(pathBuffer, "w*.c"); 1281 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1282 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1283 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR); 1284 1285 /* There should be no elements, since "[..]" does not fit w*.c */ 1286 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1287 ok (itemCount == 0, 1288 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1289 itemCount, 0); 1290 1291 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */ 1292 strcpy(pathBuffer, wildcard); 1293 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1294 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1295 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError()); 1296 1297 /* There should be no plain files on the listbox */ 1298 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1299 ok (itemCount == itemCount_justDrives + itemCount_allDirs, 1300 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1301 itemCount, itemCount_justDrives + itemCount_allDirs); 1302 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n"); 1303 1304 for (i = 0; i < itemCount; i++) { 1305 memset(pathBuffer, 0, MAX_PATH); 1306 driveletter = '\0'; 1307 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1308 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { 1309 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1310 } else { 1311 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', 1312 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer); 1313 } 1314 } 1315 1316 /* This tests behavior when no files match the wildcard */ 1317 strcpy(pathBuffer, BAD_EXTENSION); 1318 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1319 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1320 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n", 1321 BAD_EXTENSION, res, itemCount_justDrives -1); 1322 1323 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1324 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1); 1325 1326 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */ 1327 strcpy(pathBuffer, "w*.c"); 1328 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1329 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1330 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError()); 1331 1332 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */ 1333 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1334 ok (itemCount == itemCount_justDrives, 1335 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1336 itemCount, itemCount_justDrives); 1337 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n"); 1338 1339 for (i = 0; i < itemCount; i++) { 1340 memset(pathBuffer, 0, MAX_PATH); 1341 driveletter = '\0'; 1342 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1343 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer); 1344 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1345 } 1346 DestroyWindow(hList); 1347 1348 DeleteFileA( "wtest1.tmp.c" ); 1349 RemoveDirectoryA("lb_dir_test"); 1350 1351 SetCurrentDirectoryA(curdir); 1352 } 1353 1354 static HWND g_listBox; 1355 static HWND g_label; 1356 1357 #define ID_TEST_LABEL 1001 1358 #define ID_TEST_LISTBOX 1002 1359 1360 static BOOL on_listbox_container_create (HWND hwnd, LPCREATESTRUCTA lpcs) 1361 { 1362 g_label = CreateWindowA( 1363 "Static", 1364 "Contents of static control before DlgDirList.", 1365 WS_CHILD | WS_VISIBLE, 1366 10, 10, 512, 32, 1367 hwnd, (HMENU)ID_TEST_LABEL, NULL, 0); 1368 if (!g_label) return FALSE; 1369 g_listBox = CreateWindowA( 1370 "ListBox", 1371 "DlgDirList test", 1372 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL, 1373 10, 60, 256, 256, 1374 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0); 1375 if (!g_listBox) return FALSE; 1376 1377 return TRUE; 1378 } 1379 1380 static LRESULT CALLBACK listbox_container_window_procA ( 1381 HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) 1382 { 1383 LRESULT result = 0; 1384 1385 switch (uiMsg) { 1386 case WM_DESTROY: 1387 PostQuitMessage(0); 1388 break; 1389 case WM_CREATE: 1390 result = on_listbox_container_create(hwnd, (LPCREATESTRUCTA) lParam) 1391 ? 0 : (LRESULT)-1; 1392 break; 1393 default: 1394 result = DefWindowProcA (hwnd, uiMsg, wParam, lParam); 1395 break; 1396 } 1397 return result; 1398 } 1399 1400 static BOOL RegisterListboxWindowClass(HINSTANCE hInst) 1401 { 1402 WNDCLASSA cls; 1403 1404 cls.style = 0; 1405 cls.cbClsExtra = 0; 1406 cls.cbWndExtra = 0; 1407 cls.hInstance = hInst; 1408 cls.hIcon = NULL; 1409 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW); 1410 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 1411 cls.lpszMenuName = NULL; 1412 cls.lpfnWndProc = listbox_container_window_procA; 1413 cls.lpszClassName = "ListboxContainerClass"; 1414 if (!RegisterClassA (&cls)) return FALSE; 1415 1416 return TRUE; 1417 } 1418 1419 static void test_listbox_dlgdir(void) 1420 { 1421 HINSTANCE hInst; 1422 HWND hWnd; 1423 int res, itemCount; 1424 int itemCount_allDirs; 1425 int itemCount_justFiles; 1426 int itemCount_justDrives; 1427 int i; 1428 char pathBuffer[MAX_PATH]; 1429 char itemBuffer[MAX_PATH]; 1430 char tempBuffer[MAX_PATH]; 1431 char * p; 1432 char driveletter; 1433 HANDLE file; 1434 1435 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL ); 1436 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError()); 1437 CloseHandle( file ); 1438 1439 /* NOTE: for this test to succeed, there must be no subdirectories 1440 under the current directory. In addition, there must be at least 1441 one file that fits the wildcard w*.c . Normally, the test 1442 directory itself satisfies both conditions. 1443 */ 1444 1445 hInst = GetModuleHandleA(0); 1446 if (!RegisterListboxWindowClass(hInst)) assert(0); 1447 hWnd = CreateWindowA("ListboxContainerClass", "ListboxContainerClass", 1448 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 1449 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 1450 NULL, NULL, hInst, 0); 1451 assert(hWnd); 1452 1453 /* Test for standard usage */ 1454 1455 /* The following should be overwritten by the directory path */ 1456 SendMessageA(g_label, WM_SETTEXT, 0, (LPARAM)"default contents"); 1457 1458 /* This should list all the w*.c files in the test directory 1459 * As of this writing, this includes win.c, winstation.c, wsprintf.c 1460 */ 1461 strcpy(pathBuffer, "w*.c"); 1462 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0); 1463 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError()); 1464 1465 /* Path specification gets converted to uppercase */ 1466 ok (!strcmp(pathBuffer, "W*.C"), 1467 "expected conversion to uppercase, got %s\n", pathBuffer); 1468 1469 /* Loaded path should have overwritten the label text */ 1470 SendMessageA(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer); 1471 trace("Static control after DlgDirList: %s\n", pathBuffer); 1472 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n"); 1473 1474 /* There should be some content in the listbox */ 1475 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1476 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n"); 1477 itemCount_justFiles = itemCount; 1478 1479 /* Every single item in the control should start with a w and end in .c */ 1480 for (i = 0; i < itemCount; i++) { 1481 memset(pathBuffer, 0, MAX_PATH); 1482 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1483 p = pathBuffer + strlen(pathBuffer); 1484 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1485 (*(p-1) == 'c' || *(p-1) == 'C') && 1486 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1487 } 1488 1489 /* Test behavior when no files match the wildcard */ 1490 strcpy(pathBuffer, BAD_EXTENSION); 1491 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0); 1492 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res); 1493 1494 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1495 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n"); 1496 1497 /* Test DDL_DIRECTORY */ 1498 strcpy(pathBuffer, "w*.c"); 1499 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1500 DDL_DIRECTORY); 1501 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError()); 1502 1503 /* There should be some content in the listbox. In particular, there should 1504 * be exactly more elements than before, since the directories should 1505 * have been added. 1506 */ 1507 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1508 itemCount_allDirs = itemCount - itemCount_justFiles; 1509 ok (itemCount >= itemCount_justFiles, 1510 "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n", 1511 itemCount, itemCount_justFiles); 1512 1513 /* Every single item in the control should start with a w and end in .c, 1514 * except for the "[..]" string, which should appear exactly as it is. 1515 */ 1516 for (i = 0; i < itemCount; i++) { 1517 memset(pathBuffer, 0, MAX_PATH); 1518 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1519 p = pathBuffer + strlen(pathBuffer); 1520 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') || 1521 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1522 (*(p-1) == 'c' || *(p-1) == 'C') && 1523 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1524 } 1525 1526 /* Test behavior when no files match the wildcard */ 1527 strcpy(pathBuffer, BAD_EXTENSION); 1528 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1529 DDL_DIRECTORY); 1530 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res); 1531 1532 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1533 ok (itemCount == itemCount_allDirs, 1534 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n", 1535 itemCount_allDirs, itemCount); 1536 for (i = 0; i < itemCount; i++) { 1537 memset(pathBuffer, 0, MAX_PATH); 1538 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1539 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', 1540 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer); 1541 } 1542 1543 1544 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */ 1545 strcpy(pathBuffer, "w*.c"); 1546 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1547 DDL_DRIVES); 1548 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError()); 1549 1550 /* There should be some content in the listbox. In particular, there should 1551 * be at least one element before, since the string "[-c-]" should 1552 * have been added. Depending on the user setting, more drives might have 1553 * been added. 1554 */ 1555 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1556 ok (itemCount >= 1, 1557 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n", 1558 itemCount, 1); 1559 itemCount_justDrives = itemCount; 1560 1561 /* Every single item in the control should fit the format [-c-] */ 1562 for (i = 0; i < itemCount; i++) { 1563 memset(pathBuffer, 0, MAX_PATH); 1564 driveletter = '\0'; 1565 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1566 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" ); 1567 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer); 1568 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1569 if (!(driveletter >= 'a' && driveletter <= 'z')) { 1570 /* Correct after invalid entry is found */ 1571 trace("removing count of invalid entry %s\n", pathBuffer); 1572 itemCount_justDrives--; 1573 } 1574 } 1575 1576 /* Test behavior when no files match the wildcard */ 1577 strcpy(pathBuffer, BAD_EXTENSION); 1578 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1579 DDL_DRIVES); 1580 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res); 1581 1582 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1583 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n"); 1584 1585 1586 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */ 1587 strcpy(pathBuffer, "w*.c"); 1588 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1589 DDL_DIRECTORY|DDL_DRIVES); 1590 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError()); 1591 1592 /* There should be some content in the listbox. In particular, there should 1593 * be exactly the number of plain files, plus the number of mapped drives, 1594 * plus one "[..]" 1595 */ 1596 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1597 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs, 1598 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n", 1599 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs); 1600 1601 /* Every single item in the control should start with a w and end in .c, 1602 * except for the "[..]" string, which should appear exactly as it is, 1603 * and the mapped drives in the format "[-X-]". 1604 */ 1605 for (i = 0; i < itemCount; i++) { 1606 memset(pathBuffer, 0, MAX_PATH); 1607 driveletter = '\0'; 1608 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1609 p = pathBuffer + strlen(pathBuffer); 1610 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { 1611 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1612 } else { 1613 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') || 1614 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1615 (*(p-1) == 'c' || *(p-1) == 'C') && 1616 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1617 } 1618 } 1619 1620 /* Test behavior when no files match the wildcard */ 1621 strcpy(pathBuffer, BAD_EXTENSION); 1622 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1623 DDL_DIRECTORY|DDL_DRIVES); 1624 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res); 1625 1626 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1627 ok (itemCount == itemCount_justDrives + itemCount_allDirs, 1628 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n", 1629 itemCount_justDrives + itemCount_allDirs, itemCount); 1630 1631 1632 1633 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */ 1634 strcpy(pathBuffer, "w*.c"); 1635 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1636 DDL_DIRECTORY|DDL_EXCLUSIVE); 1637 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError()); 1638 1639 /* There should be exactly one element: "[..]" */ 1640 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1641 ok (itemCount == itemCount_allDirs, 1642 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1643 itemCount, itemCount_allDirs); 1644 1645 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */ 1646 { 1647 memset(pathBuffer, 0, MAX_PATH); 1648 SendMessageA(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer); 1649 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n"); 1650 } 1651 1652 /* Test behavior when no files match the wildcard */ 1653 strcpy(pathBuffer, BAD_EXTENSION); 1654 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1655 DDL_DIRECTORY|DDL_EXCLUSIVE); 1656 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res); 1657 1658 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1659 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n"); 1660 1661 1662 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */ 1663 strcpy(pathBuffer, "w*.c"); 1664 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1665 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE); 1666 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError()); 1667 1668 /* There should be no plain files on the listbox */ 1669 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1670 ok (itemCount == itemCount_justDrives + itemCount_allDirs, 1671 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1672 itemCount, itemCount_justDrives + itemCount_allDirs); 1673 1674 for (i = 0; i < itemCount; i++) { 1675 memset(pathBuffer, 0, MAX_PATH); 1676 driveletter = '\0'; 1677 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1678 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { 1679 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1680 } else { 1681 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', 1682 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer); 1683 } 1684 } 1685 1686 /* Test behavior when no files match the wildcard */ 1687 strcpy(pathBuffer, BAD_EXTENSION); 1688 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1689 DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE); 1690 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res); 1691 1692 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1693 ok (itemCount == itemCount_justDrives + itemCount_allDirs, 1694 "DlgDirList() incorrectly filled the listbox!\n"); 1695 1696 /* Now test DlgDirSelectEx() in normal operation */ 1697 /* Fill with everything - drives, directory and all plain files. */ 1698 strcpy(pathBuffer, "*"); 1699 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 1700 DDL_DIRECTORY|DDL_DRIVES); 1701 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError()); 1702 1703 SendMessageA(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */ 1704 memset(pathBuffer, 0, MAX_PATH); 1705 SetLastError(0xdeadbeef); 1706 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1707 ok (GetLastError() == 0xdeadbeef, 1708 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n", 1709 GetLastError()); 1710 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res); 1711 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */ 1712 /* 1713 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer); 1714 */ 1715 /* Test proper drive/dir/file recognition */ 1716 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1717 for (i = 0; i < itemCount; i++) { 1718 memset(itemBuffer, 0, MAX_PATH); 1719 memset(pathBuffer, 0, MAX_PATH); 1720 memset(tempBuffer, 0, MAX_PATH); 1721 driveletter = '\0'; 1722 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer); 1723 if (!strstr(itemBuffer, ".exe")) continue; // skip downloaded/generated files from other tests 1724 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0); 1725 ok (res == i, "SendMessageA(LB_SETCURSEL, %d) failed\n", i); 1726 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) { 1727 /* Current item is a drive letter */ 1728 SetLastError(0xdeadbeef); 1729 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1730 ok (GetLastError() == 0xdeadbeef, 1731 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1732 i, GetLastError()); 1733 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); 1734 1735 /* For drive letters, DlgDirSelectEx tacks on a colon */ 1736 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0', 1737 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter); 1738 } else if (itemBuffer[0] == '[') { 1739 /* Current item is the parent directory */ 1740 SetLastError(0xdeadbeef); 1741 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1742 ok (GetLastError() == 0xdeadbeef, 1743 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1744 i, GetLastError()); 1745 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); 1746 1747 /* For directories, DlgDirSelectEx tacks on a backslash */ 1748 p = pathBuffer + strlen(pathBuffer); 1749 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer); 1750 1751 tempBuffer[0] = '['; 1752 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer)); 1753 strcat(tempBuffer, "]"); 1754 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer); 1755 } else { 1756 /* Current item is a plain file */ 1757 SetLastError(0xdeadbeef); 1758 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1759 ok (GetLastError() == 0xdeadbeef, 1760 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1761 i, GetLastError()); 1762 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer); 1763 1764 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects 1765 * for example, "Makefile", which gets reported as "Makefile." 1766 */ 1767 strcpy(tempBuffer, itemBuffer); 1768 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, "."); 1769 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer); 1770 } 1771 } 1772 1773 DeleteFileA( "wtest1.tmp.c" ); 1774 1775 /* Now test DlgDirSelectEx() in abnormal operation */ 1776 /* Fill list with bogus entries, that look somewhat valid */ 1777 SendMessageA(g_listBox, LB_RESETCONTENT, 0, 0); 1778 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]"); 1779 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil"); 1780 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1781 for (i = 0; i < itemCount; i++) { 1782 memset(itemBuffer, 0, MAX_PATH); 1783 memset(pathBuffer, 0, MAX_PATH); 1784 memset(tempBuffer, 0, MAX_PATH); 1785 driveletter = '\0'; 1786 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer); 1787 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0); 1788 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i); 1789 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) { 1790 /* Current item is a drive letter */ 1791 SetLastError(0xdeadbeef); 1792 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1793 ok (GetLastError() == 0xdeadbeef, 1794 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1795 i, GetLastError()); 1796 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); 1797 1798 /* For drive letters, DlgDirSelectEx tacks on a colon */ 1799 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0', 1800 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter); 1801 } else if (itemBuffer[0] == '[') { 1802 /* Current item is the parent directory */ 1803 SetLastError(0xdeadbeef); 1804 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1805 ok (GetLastError() == 0xdeadbeef, 1806 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1807 i, GetLastError()); 1808 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); 1809 1810 /* For directories, DlgDirSelectEx tacks on a backslash */ 1811 p = pathBuffer + strlen(pathBuffer); 1812 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer); 1813 1814 tempBuffer[0] = '['; 1815 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer)); 1816 strcat(tempBuffer, "]"); 1817 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer); 1818 } else { 1819 /* Current item is a plain file */ 1820 SetLastError(0xdeadbeef); 1821 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1822 ok (GetLastError() == 0xdeadbeef, 1823 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1824 i, GetLastError()); 1825 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer); 1826 1827 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension. 1828 * This affects for example, "Makefile", which gets reported as "Makefile." 1829 */ 1830 strcpy(tempBuffer, itemBuffer); 1831 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, "."); 1832 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer); 1833 } 1834 } 1835 1836 /* Test behavior when loading folders from root with and without wildcard */ 1837 strcpy(pathBuffer, "C:\\"); 1838 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE); 1839 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\ folders\n"); 1840 ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */, 1841 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer); 1842 1843 strcpy(pathBuffer, "C:\\*"); 1844 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE); 1845 ok(res || broken(!res) /* NT4/W2K */, "DlgDirList failed to list C:\\* folders\n"); 1846 ok(!strcmp(pathBuffer, "*") || broken(!res) /* NT4/W2K */, 1847 "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer); 1848 1849 /* Try loading files from an invalid folder */ 1850 SetLastError(0xdeadbeef); 1851 strcpy(pathBuffer, "C:\\INVALID$$DIR"); 1852 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE); 1853 ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res); 1854 ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS, 1855 "GetLastError should return 0x589, got 0x%X\n",GetLastError()); 1856 1857 DestroyWindow(hWnd); 1858 } 1859 1860 static void test_set_count( void ) 1861 { 1862 static const DWORD styles[] = 1863 { 1864 LBS_OWNERDRAWFIXED, 1865 LBS_HASSTRINGS, 1866 }; 1867 HWND parent, listbox; 1868 unsigned int i; 1869 LONG ret; 1870 RECT r; 1871 1872 parent = create_parent(); 1873 listbox = create_listbox( LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VISIBLE, parent ); 1874 1875 UpdateWindow( listbox ); 1876 GetUpdateRect( listbox, &r, TRUE ); 1877 ok( IsRectEmpty( &r ), "got non-empty rect\n"); 1878 1879 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 ); 1880 ok( ret == 0, "got %d\n", ret ); 1881 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 ); 1882 ok( ret == 100, "got %d\n", ret ); 1883 1884 GetUpdateRect( listbox, &r, TRUE ); 1885 ok( !IsRectEmpty( &r ), "got empty rect\n"); 1886 1887 ValidateRect( listbox, NULL ); 1888 GetUpdateRect( listbox, &r, TRUE ); 1889 ok( IsRectEmpty( &r ), "got non-empty rect\n"); 1890 1891 ret = SendMessageA( listbox, LB_SETCOUNT, 99, 0 ); 1892 ok( ret == 0, "got %d\n", ret ); 1893 1894 GetUpdateRect( listbox, &r, TRUE ); 1895 ok( !IsRectEmpty( &r ), "got empty rect\n"); 1896 1897 ret = SendMessageA( listbox, LB_SETCOUNT, -5, 0 ); 1898 ok( ret == 0, "got %d\n", ret ); 1899 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 ); 1900 ok( ret == -5, "got %d\n", ret ); 1901 1902 DestroyWindow( listbox ); 1903 1904 for (i = 0; i < ARRAY_SIZE(styles); ++i) 1905 { 1906 listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent ); 1907 1908 SetLastError( 0xdeadbeef ); 1909 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 ); 1910 ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret ); 1911 ok( GetLastError() == ERROR_SETCOUNT_ON_BAD_LB, "Unexpected error %d.\n", GetLastError() ); 1912 1913 DestroyWindow( listbox ); 1914 } 1915 1916 DestroyWindow( parent ); 1917 } 1918 1919 static DWORD (WINAPI *pGetListBoxInfo)(HWND); 1920 static int lb_getlistboxinfo; 1921 1922 static LRESULT WINAPI listbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 1923 { 1924 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 1925 1926 if (message == LB_GETLISTBOXINFO) 1927 lb_getlistboxinfo++; 1928 1929 return CallWindowProcA(oldproc, hwnd, message, wParam, lParam); 1930 } 1931 1932 static void test_GetListBoxInfo(void) 1933 { 1934 HWND listbox, parent; 1935 WNDPROC oldproc; 1936 DWORD ret; 1937 1938 pGetListBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetListBoxInfo"); 1939 1940 if (!pGetListBoxInfo) 1941 { 1942 win_skip("GetListBoxInfo() not available\n"); 1943 return; 1944 } 1945 1946 parent = create_parent(); 1947 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent); 1948 1949 oldproc = (WNDPROC)SetWindowLongPtrA(listbox, GWLP_WNDPROC, (LONG_PTR)listbox_subclass_proc); 1950 SetWindowLongPtrA(listbox, GWLP_USERDATA, (LONG_PTR)oldproc); 1951 1952 lb_getlistboxinfo = 0; 1953 ret = pGetListBoxInfo(listbox); 1954 ok(ret > 0, "got %d\n", ret); 1955 todo_wine 1956 ok(lb_getlistboxinfo == 0, "got %d\n", lb_getlistboxinfo); 1957 1958 DestroyWindow(listbox); 1959 DestroyWindow(parent); 1960 } 1961 1962 static void test_init_storage( void ) 1963 { 1964 static const DWORD styles[] = 1965 { 1966 LBS_HASSTRINGS, 1967 LBS_NODATA | LBS_OWNERDRAWFIXED, 1968 }; 1969 HWND parent, listbox; 1970 LONG ret, items_size; 1971 int i, j; 1972 1973 parent = create_parent(); 1974 for (i = 0; i < ARRAY_SIZE(styles); i++) 1975 { 1976 listbox = CreateWindowA("listbox", "TestList", styles[i] | WS_CHILD, 1977 0, 0, 100, 100, parent, (HMENU)1, NULL, 0); 1978 1979 items_size = SendMessageA(listbox, LB_INITSTORAGE, 100, 0); 1980 ok(items_size >= 100, "expected at least 100, got %d\n", items_size); 1981 1982 ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0); 1983 ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 1984 1985 /* it doesn't grow since the space was already reserved */ 1986 ret = SendMessageA(listbox, LB_INITSTORAGE, items_size, 0); 1987 ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 1988 1989 /* it doesn't shrink the reserved space */ 1990 ret = SendMessageA(listbox, LB_INITSTORAGE, 42, 0); 1991 ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 1992 1993 /* now populate almost all of it so it's not reserved anymore */ 1994 if (styles[i] & LBS_NODATA) 1995 { 1996 ret = SendMessageA(listbox, LB_SETCOUNT, items_size - 1, 0); 1997 ok(ret == 0, "unexpected return value %d\n", ret); 1998 } 1999 else 2000 { 2001 for (j = 0; j < items_size - 1; j++) 2002 { 2003 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)""); 2004 ok(ret == j, "expected %d, got %d\n", j, ret); 2005 } 2006 } 2007 2008 /* we still have one more reserved slot, so it doesn't grow yet */ 2009 ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0); 2010 ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 2011 2012 /* fill the slot and check again, it should grow this time */ 2013 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)""); 2014 ok(ret == items_size - 1, "expected %d, got %d\n", items_size - 1, ret); 2015 ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0); 2016 ok(ret == items_size, "expected %d, got %d\n", items_size, ret); 2017 ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0); 2018 ok(ret > items_size, "expected it to grow past %d, got %d\n", items_size, ret); 2019 2020 DestroyWindow(listbox); 2021 } 2022 DestroyWindow(parent); 2023 } 2024 2025 static void test_missing_lbuttonup( void ) 2026 { 2027 HWND listbox, parent, capture; 2028 2029 parent = create_parent(); 2030 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent); 2031 2032 /* Send button down without a corresponding button up */ 2033 SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(10,10)); 2034 capture = GetCapture(); 2035 ok(capture == listbox, "got %p expected %p\n", capture, listbox); 2036 2037 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */ 2038 got_selchange = 0; 2039 SetFocus(NULL); 2040 capture = GetCapture(); 2041 ok(capture == NULL, "got %p\n", capture); 2042 ok(got_selchange, "got %d\n", got_selchange); 2043 2044 DestroyWindow(listbox); 2045 DestroyWindow(parent); 2046 } 2047 2048 static void test_extents(void) 2049 { 2050 HWND listbox, parent; 2051 DWORD res; 2052 SCROLLINFO sinfo; 2053 BOOL br; 2054 2055 parent = create_parent(); 2056 2057 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent); 2058 2059 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2060 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res); 2061 2062 sinfo.cbSize = sizeof(sinfo); 2063 sinfo.fMask = SIF_RANGE; 2064 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2065 ok(br == TRUE, "GetScrollInfo failed\n"); 2066 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2067 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax); 2068 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 2069 "List box should not have a horizontal scroll bar\n"); 2070 2071 /* horizontal extent < width */ 2072 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0); 2073 2074 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2075 ok(res == 64, "Got wrong horizontal extent: %u\n", res); 2076 2077 sinfo.cbSize = sizeof(sinfo); 2078 sinfo.fMask = SIF_RANGE; 2079 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2080 ok(br == TRUE, "GetScrollInfo failed\n"); 2081 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2082 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax); 2083 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 2084 "List box should not have a horizontal scroll bar\n"); 2085 2086 /* horizontal extent > width */ 2087 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0); 2088 2089 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2090 ok(res == 184, "Got wrong horizontal extent: %u\n", res); 2091 2092 sinfo.cbSize = sizeof(sinfo); 2093 sinfo.fMask = SIF_RANGE; 2094 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2095 ok(br == TRUE, "GetScrollInfo failed\n"); 2096 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2097 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax); 2098 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 2099 "List box should not have a horizontal scroll bar\n"); 2100 2101 DestroyWindow(listbox); 2102 2103 2104 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL, parent); 2105 2106 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2107 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res); 2108 2109 sinfo.cbSize = sizeof(sinfo); 2110 sinfo.fMask = SIF_RANGE; 2111 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2112 ok(br == TRUE, "GetScrollInfo failed\n"); 2113 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2114 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax); 2115 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 2116 "List box should not have a horizontal scroll bar\n"); 2117 2118 /* horizontal extent < width */ 2119 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0); 2120 2121 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2122 ok(res == 64, "Got wrong horizontal extent: %u\n", res); 2123 2124 sinfo.cbSize = sizeof(sinfo); 2125 sinfo.fMask = SIF_RANGE; 2126 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2127 ok(br == TRUE, "GetScrollInfo failed\n"); 2128 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2129 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax); 2130 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 2131 "List box should not have a horizontal scroll bar\n"); 2132 2133 /* horizontal extent > width */ 2134 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0); 2135 2136 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2137 ok(res == 184, "Got wrong horizontal extent: %u\n", res); 2138 2139 sinfo.cbSize = sizeof(sinfo); 2140 sinfo.fMask = SIF_RANGE; 2141 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2142 ok(br == TRUE, "GetScrollInfo failed\n"); 2143 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2144 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax); 2145 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2146 "List box should have a horizontal scroll bar\n"); 2147 2148 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0); 2149 2150 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2151 ok(res == 0, "Got wrong horizontal extent: %u\n", res); 2152 2153 sinfo.cbSize = sizeof(sinfo); 2154 sinfo.fMask = SIF_RANGE; 2155 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2156 ok(br == TRUE, "GetScrollInfo failed\n"); 2157 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2158 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax); 2159 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 2160 "List box should not have a horizontal scroll bar\n"); 2161 2162 DestroyWindow(listbox); 2163 2164 2165 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL | LBS_DISABLENOSCROLL, parent); 2166 2167 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2168 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res); 2169 2170 sinfo.cbSize = sizeof(sinfo); 2171 sinfo.fMask = SIF_RANGE; 2172 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2173 ok(br == TRUE, "GetScrollInfo failed\n"); 2174 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2175 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax); 2176 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2177 "List box should have a horizontal scroll bar\n"); 2178 2179 /* horizontal extent < width */ 2180 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0); 2181 2182 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2183 ok(res == 64, "Got wrong horizontal extent: %u\n", res); 2184 2185 sinfo.cbSize = sizeof(sinfo); 2186 sinfo.fMask = SIF_RANGE; 2187 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2188 ok(br == TRUE, "GetScrollInfo failed\n"); 2189 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2190 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax); 2191 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2192 "List box should have a horizontal scroll bar\n"); 2193 2194 /* horizontal extent > width */ 2195 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0); 2196 2197 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2198 ok(res == 184, "Got wrong horizontal extent: %u\n", res); 2199 2200 sinfo.cbSize = sizeof(sinfo); 2201 sinfo.fMask = SIF_RANGE; 2202 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2203 ok(br == TRUE, "GetScrollInfo failed\n"); 2204 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2205 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax); 2206 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2207 "List box should have a horizontal scroll bar\n"); 2208 2209 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0); 2210 2211 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2212 ok(res == 0, "Got wrong horizontal extent: %u\n", res); 2213 2214 sinfo.cbSize = sizeof(sinfo); 2215 sinfo.fMask = SIF_RANGE; 2216 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2217 ok(br == TRUE, "GetScrollInfo failed\n"); 2218 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2219 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax); 2220 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2221 "List box should have a horizontal scroll bar\n"); 2222 2223 DestroyWindow(listbox); 2224 2225 DestroyWindow(parent); 2226 } 2227 2228 static void test_WM_MEASUREITEM(void) 2229 { 2230 HWND parent, listbox; 2231 LRESULT data; 2232 2233 parent = create_parent(); 2234 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE, parent); 2235 2236 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0); 2237 ok(data == (LRESULT)strings[0], "data = %08lx, expected %p\n", data, strings[0]); 2238 DestroyWindow(parent); 2239 2240 parent = create_parent(); 2241 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS, parent); 2242 2243 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0); 2244 ok(!data, "data = %08lx\n", data); 2245 DestroyWindow(parent); 2246 } 2247 2248 static void test_LBS_NODATA(void) 2249 { 2250 static const DWORD invalid_styles[] = 2251 { 2252 0, 2253 LBS_OWNERDRAWVARIABLE, 2254 LBS_SORT, 2255 LBS_HASSTRINGS, 2256 LBS_OWNERDRAWFIXED | LBS_SORT, 2257 LBS_OWNERDRAWFIXED | LBS_HASSTRINGS, 2258 }; 2259 static const UINT invalid_idx[] = { -2, 2 }; 2260 static const UINT valid_idx[] = { 0, 1 }; 2261 static const ULONG_PTR zero_data; 2262 HWND listbox, parent; 2263 unsigned int i; 2264 ULONG_PTR data; 2265 INT ret; 2266 2267 listbox = CreateWindowA("listbox", "TestList", LBS_NODATA | LBS_OWNERDRAWFIXED | WS_VISIBLE, 2268 0, 0, 100, 100, NULL, NULL, NULL, 0); 2269 ok(listbox != NULL, "Failed to create ListBox window.\n"); 2270 2271 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0); 2272 ok(ret == 0, "Unexpected return value %d.\n", ret); 2273 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0); 2274 ok(ret == 1, "Unexpected return value %d.\n", ret); 2275 ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0); 2276 ok(ret == 2, "Unexpected return value %d.\n", ret); 2277 2278 /* Invalid indices. */ 2279 for (i = 0; i < ARRAY_SIZE(invalid_idx); ++i) 2280 { 2281 ret = SendMessageA(listbox, LB_SETITEMDATA, invalid_idx[i], 42); 2282 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2283 ret = SendMessageA(listbox, LB_GETTEXTLEN, invalid_idx[i], 0); 2284 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2285 if (ret == LB_ERR) 2286 { 2287 ret = SendMessageA(listbox, LB_GETTEXT, invalid_idx[i], (LPARAM)&data); 2288 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2289 } 2290 ret = SendMessageA(listbox, LB_GETITEMDATA, invalid_idx[i], 0); 2291 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2292 } 2293 2294 /* Valid indices. */ 2295 for (i = 0; i < ARRAY_SIZE(valid_idx); ++i) 2296 { 2297 ret = SendMessageA(listbox, LB_SETITEMDATA, valid_idx[i], 42); 2298 ok(ret == TRUE, "Unexpected return value %d.\n", ret); 2299 ret = SendMessageA(listbox, LB_GETTEXTLEN, valid_idx[i], 0); 2300 ok(ret == sizeof(data), "Unexpected return value %d.\n", ret); 2301 2302 memset(&data, 0xee, sizeof(data)); 2303 ret = SendMessageA(listbox, LB_GETTEXT, valid_idx[i], (LPARAM)&data); 2304 ok(ret == sizeof(data), "Unexpected return value %d.\n", ret); 2305 ok(!memcmp(&data, &zero_data, sizeof(data)), "Unexpected item data.\n"); 2306 2307 ret = SendMessageA(listbox, LB_GETITEMDATA, valid_idx[i], 0); 2308 ok(ret == 0, "Unexpected return value %d.\n", ret); 2309 } 2310 2311 /* More messages that don't work with LBS_NODATA. */ 2312 SetLastError(0xdeadbeef); 2313 ret = SendMessageA(listbox, LB_FINDSTRING, 1, 0); 2314 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2315 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError()); 2316 SetLastError(0xdeadbeef); 2317 ret = SendMessageA(listbox, LB_FINDSTRING, 1, 42); 2318 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2319 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError()); 2320 SetLastError(0xdeadbeef); 2321 ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 0); 2322 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2323 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError()); 2324 SetLastError(0xdeadbeef); 2325 ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 42); 2326 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2327 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError()); 2328 SetLastError(0xdeadbeef); 2329 ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 0); 2330 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2331 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError()); 2332 SetLastError(0xdeadbeef); 2333 ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 42); 2334 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2335 ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError should return 0x57, got 0x%X\n", GetLastError()); 2336 2337 DestroyWindow(listbox); 2338 2339 /* Invalid window style combinations. */ 2340 parent = create_parent(); 2341 ok(parent != NULL, "Failed to create parent window.\n"); 2342 2343 for (i = 0; i < ARRAY_SIZE(invalid_styles); ++i) 2344 { 2345 DWORD style; 2346 2347 listbox = CreateWindowA("listbox", "TestList", LBS_NODATA | WS_CHILD | invalid_styles[i], 2348 0, 0, 100, 100, parent, (HMENU)1, NULL, 0); 2349 ok(listbox != NULL, "Failed to create a listbox.\n"); 2350 2351 style = GetWindowLongA(listbox, GWL_STYLE); 2352 ok((style & invalid_styles[i]) == invalid_styles[i], "%u: unexpected window styles %#x.\n", i, style); 2353 ret = SendMessageA(listbox, LB_SETCOUNT, 100, 0); 2354 ok(ret == LB_ERR, "%u: unexpected return value %d.\n", i, ret); 2355 DestroyWindow(listbox); 2356 } 2357 2358 DestroyWindow(parent); 2359 } 2360 2361 START_TEST(listbox) 2362 { 2363 const struct listbox_test SS = 2364 /* {add_style} */ 2365 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2366 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2367 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2368 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2369 /* {selected, anchor, caret, selcount}{TODO fields} */ 2370 const struct listbox_test SS_NS = 2371 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2372 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2373 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2374 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2375 const struct listbox_test MS = 2376 {{ 0, LB_ERR, 0, 0}, {0,0,0,0}, 2377 { 1, 1, 1, 1}, {0,0,0,0}, 2378 { 2, 1, 2, 1}, {0,0,0,0}, 2379 { 0, LB_ERR, 0, 2}, {0,0,0,0}}; 2380 const struct listbox_test MS_NS = 2381 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2382 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2383 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2384 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2385 const struct listbox_test ES = 2386 {{ 0, LB_ERR, 0, 0}, {0,0,0,0}, 2387 { 1, 1, 1, 1}, {0,0,0,0}, 2388 { 2, 2, 2, 1}, {0,0,0,0}, 2389 { 0, LB_ERR, 0, 2}, {0,0,0,0}}; 2390 const struct listbox_test ES_NS = 2391 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2392 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2393 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2394 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2395 const struct listbox_test EMS = 2396 {{ 0, LB_ERR, 0, 0}, {0,0,0,0}, 2397 { 1, 1, 1, 1}, {0,0,0,0}, 2398 { 2, 2, 2, 1}, {0,0,0,0}, 2399 { 0, LB_ERR, 0, 2}, {0,0,0,0}}; 2400 const struct listbox_test EMS_NS = 2401 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2402 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2403 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2404 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2405 2406 trace (" Testing single selection...\n"); 2407 check (0, SS); 2408 trace (" ... with NOSEL\n"); 2409 check (LBS_NOSEL, SS_NS); 2410 trace (" ... LBS_NODATA variant ...\n"); 2411 check (LBS_NODATA | LBS_OWNERDRAWFIXED, SS); 2412 trace (" ... with NOSEL\n"); 2413 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOSEL, SS_NS); 2414 2415 trace (" Testing multiple selection...\n"); 2416 check (LBS_MULTIPLESEL, MS); 2417 trace (" ... with NOSEL\n"); 2418 check (LBS_MULTIPLESEL | LBS_NOSEL, MS_NS); 2419 trace (" ... LBS_NODATA variant ...\n"); 2420 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL, MS); 2421 trace (" ... with NOSEL\n"); 2422 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL | LBS_NOSEL, MS_NS); 2423 2424 trace (" Testing extended selection...\n"); 2425 check (LBS_EXTENDEDSEL, ES); 2426 trace (" ... with NOSEL\n"); 2427 check (LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS); 2428 trace (" ... LBS_NODATA variant ...\n"); 2429 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL, ES); 2430 trace (" ... with NOSEL\n"); 2431 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS); 2432 2433 trace (" Testing extended and multiple selection...\n"); 2434 check (LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS); 2435 trace (" ... with NOSEL\n"); 2436 check (LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS); 2437 trace (" ... LBS_NODATA variant ...\n"); 2438 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS); 2439 trace (" ... with NOSEL\n"); 2440 check (LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS); 2441 2442 check_item_height(); 2443 test_ownerdraw(); 2444 test_LB_SELITEMRANGE(); 2445 test_LB_SETCURSEL(); 2446 test_listbox_height(); 2447 test_changing_selection_styles(); 2448 test_itemfrompoint(); 2449 test_listbox_item_data(); 2450 test_listbox_LB_DIR(); 2451 test_listbox_dlgdir(); 2452 test_set_count(); 2453 test_init_storage(); 2454 test_GetListBoxInfo(); 2455 test_missing_lbuttonup(); 2456 test_extents(); 2457 test_WM_MEASUREITEM(); 2458 test_LB_SETSEL(); 2459 test_LBS_NODATA(); 2460 } 2461