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