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_itemfrompoint(void) 788 { 789 /* WS_POPUP is required in order to have a more accurate size calculation ( 790 without caption). LBS_NOINTEGRALHEIGHT is required in order to test 791 behavior of partially-displayed item. 792 */ 793 HWND hList = CreateWindowA( WC_LISTBOXA, "list test", 794 WS_VISIBLE|WS_POPUP|LBS_NOINTEGRALHEIGHT, 795 1, 1, 600, 100, NULL, NULL, NULL, NULL ); 796 ULONG r, id; 797 RECT rc; 798 799 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 )); 800 ok( r == MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r ); 801 802 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 700, 30 )); 803 ok( r == MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r ); 804 805 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( 30, 300 )); 806 ok( r == MAKELPARAM(0xffff, 1), "Unexpected ret value %#x.\n", r ); 807 808 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi"); 809 ok( id == 0, "item id wrong\n"); 810 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi1"); 811 ok( id == 1, "item id wrong\n"); 812 813 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 30 )); 814 ok( r == 0x1, "ret %x\n", r ); 815 816 r = SendMessageA(hList, LB_ITEMFROMPOINT, 0, MAKELPARAM( /* x */ 30, /* y */ 601 )); 817 ok( r == MAKELPARAM(1, 1), "Unexpected ret value %#x.\n", r ); 818 819 /* Resize control so that below assertions about sizes are valid */ 820 r = SendMessageA( hList, LB_GETITEMRECT, 0, (LPARAM)&rc); 821 ok( r == 1, "ret %x\n", r); 822 r = MoveWindow(hList, 1, 1, 600, (rc.bottom - rc.top + 1) * 9 / 2, TRUE); 823 ok( r != 0, "ret %x\n", r); 824 825 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi2"); 826 ok( id == 2, "item id wrong\n"); 827 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi3"); 828 ok( id == 3, "item id wrong\n"); 829 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi4"); 830 ok( id == 4, "item id wrong\n"); 831 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi5"); 832 ok( id == 5, "item id wrong\n"); 833 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi6"); 834 ok( id == 6, "item id wrong\n"); 835 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi7"); 836 ok( id == 7, "item id wrong\n"); 837 838 /* Set the listbox up so that id 1 is at the top, this leaves 5 839 partially visible at the bottom and 6, 7 are invisible */ 840 841 SendMessageA( hList, LB_SETTOPINDEX, 1, 0); 842 r = SendMessageA( hList, LB_GETTOPINDEX, 0, 0); 843 ok( r == 1, "top %d\n", r); 844 845 r = SendMessageA( hList, LB_GETITEMRECT, 5, (LPARAM)&rc); 846 ok( r == 1, "ret %x\n", r); 847 r = SendMessageA( hList, LB_GETITEMRECT, 6, (LPARAM)&rc); 848 ok( r == 0, "ret %x\n", r); 849 850 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(/* x */ 10, /* y */ 10) ); 851 ok( r == 1, "ret %x\n", r); 852 853 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(1000, 10) ); 854 ok( r == 0x10001, "ret %x\n", r ); 855 856 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, -10) ); 857 ok( r == 0x10001, "ret %x\n", r ); 858 859 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 100) ); 860 ok( r == 0x10005, "item %x\n", r ); 861 862 r = SendMessageA( hList, LB_ITEMFROMPOINT, 0, MAKELPARAM(10, 200) ); 863 ok( r == 0x10005, "item %x\n", r ); 864 865 DestroyWindow( hList ); 866 } 867 868 static void test_listbox_item_data(void) 869 { 870 HWND hList; 871 int r, id; 872 873 hList = CreateWindowA( WC_LISTBOXA, "list test", 0, 874 1, 1, 600, 100, NULL, NULL, NULL, NULL ); 875 ok( hList != NULL, "failed to create listbox\n"); 876 877 id = SendMessageA( hList, LB_ADDSTRING, 0, (LPARAM) "hi"); 878 ok( id == 0, "item id wrong\n"); 879 880 r = SendMessageA( hList, LB_SETITEMDATA, 0, MAKELPARAM( 20, 0 )); 881 ok(r == TRUE, "LB_SETITEMDATA returned %d instead of TRUE\n", r); 882 883 r = SendMessageA( hList, LB_GETITEMDATA, 0, 0); 884 ok( r == 20, "get item data failed\n"); 885 886 DestroyWindow( hList ); 887 } 888 889 static void test_listbox_LB_DIR(void) 890 { 891 char path[MAX_PATH], curdir[MAX_PATH]; 892 HWND hList; 893 int res, itemCount; 894 int itemCount_justFiles; 895 int itemCount_justDrives; 896 int itemCount_allFiles; 897 int itemCount_allDirs; 898 int i; 899 char pathBuffer[MAX_PATH]; 900 char * p; 901 char driveletter; 902 const char *wildcard = "*"; 903 HANDLE file; 904 BOOL ret; 905 906 GetCurrentDirectoryA(ARRAY_SIZE(curdir), curdir); 907 908 GetTempPathA(ARRAY_SIZE(path), path); 909 ret = SetCurrentDirectoryA(path); 910 ok(ret, "Failed to set current directory.\n"); 911 912 ret = CreateDirectoryA("lb_dir_test", NULL); 913 ok(ret, "Failed to create test directory.\n"); 914 915 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL ); 916 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError()); 917 CloseHandle( file ); 918 919 /* NOTE: for this test to succeed, there must be no subdirectories 920 under the current directory. In addition, there must be at least 921 one file that fits the wildcard w*.c . Normally, the test 922 directory itself satisfies both conditions. 923 */ 924 hList = CreateWindowA( WC_LISTBOXA, "list test", WS_VISIBLE|WS_POPUP, 925 1, 1, 600, 100, NULL, NULL, NULL, NULL ); 926 ok(hList != NULL, "Failed to create listbox window.\n"); 927 928 /* Test for standard usage */ 929 930 /* This should list all the files in the test directory. */ 931 strcpy(pathBuffer, wildcard); 932 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 933 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer); 934 if (res == -1) /* "*" wildcard doesn't work on win9x */ 935 { 936 wildcard = "*.*"; 937 strcpy(pathBuffer, wildcard); 938 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer); 939 } 940 ok (res >= 0, "SendMessage(LB_DIR, 0, *) failed - 0x%08x\n", GetLastError()); 941 942 /* There should be some content in the listbox */ 943 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 944 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n"); 945 itemCount_allFiles = itemCount; 946 ok(res + 1 == itemCount, 947 "SendMessage(LB_DIR, 0, *) returned incorrect index (expected %d got %d)!\n", 948 itemCount - 1, res); 949 950 /* This tests behavior when no files match the wildcard */ 951 strcpy(pathBuffer, BAD_EXTENSION); 952 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 953 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer); 954 ok (res == -1, "SendMessage(LB_DIR, 0, %s) returned %d, expected -1\n", BAD_EXTENSION, res); 955 956 /* There should be NO content in the listbox */ 957 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 958 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n"); 959 960 961 /* This should list all the w*.c files in the test directory 962 * As of this writing, this includes win.c, winstation.c, wsprintf.c 963 */ 964 strcpy(pathBuffer, "w*.c"); 965 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 966 res = SendMessageA(hList, LB_DIR, 0, (LPARAM)pathBuffer); 967 ok (res >= 0, "SendMessage(LB_DIR, 0, w*.c) failed - 0x%08x\n", GetLastError()); 968 969 /* Path specification does NOT converted to uppercase */ 970 ok (!strcmp(pathBuffer, "w*.c"), 971 "expected no change to pathBuffer, got %s\n", pathBuffer); 972 973 /* There should be some content in the listbox */ 974 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 975 ok (itemCount > 0, "SendMessage(LB_DIR) did NOT fill the listbox!\n"); 976 itemCount_justFiles = itemCount; 977 ok(res + 1 == itemCount, 978 "SendMessage(LB_DIR, 0, w*.c) returned incorrect index (expected %d got %d)!\n", 979 itemCount - 1, res); 980 981 /* Every single item in the control should start with a w and end in .c */ 982 for (i = 0; i < itemCount; i++) 983 { 984 memset(pathBuffer, 0, MAX_PATH); 985 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 986 p = pathBuffer + strlen(pathBuffer); 987 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 988 (*(p-1) == 'c' || *(p-1) == 'C') && 989 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 990 } 991 992 /* Test DDL_DIRECTORY */ 993 strcpy(pathBuffer, wildcard); 994 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 995 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer); 996 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY, *) failed - 0x%08x\n", GetLastError()); 997 998 /* There should be some content in the listbox. 999 * All files plus "[..]" 1000 */ 1001 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1002 itemCount_allDirs = itemCount - itemCount_allFiles; 1003 ok (itemCount >= itemCount_allFiles, 1004 "SendMessage(LB_DIR, DDL_DIRECTORY, *) filled with %d entries, expected > %d\n", 1005 itemCount, itemCount_allFiles); 1006 ok(res + 1 == itemCount, 1007 "SendMessage(LB_DIR, DDL_DIRECTORY, *) returned incorrect index (expected %d got %d)!\n", 1008 itemCount - 1, res); 1009 1010 /* This tests behavior when no files match the wildcard */ 1011 strcpy(pathBuffer, BAD_EXTENSION); 1012 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1013 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer); 1014 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY, %s) returned %d, expected -1\n", BAD_EXTENSION, res); 1015 1016 /* There should be NO content in the listbox */ 1017 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1018 ok (itemCount == 0, "SendMessage(LB_DIR) DID fill the listbox!\n"); 1019 1020 /* Test DDL_DIRECTORY */ 1021 strcpy(pathBuffer, "w*.c"); 1022 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1023 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY, (LPARAM)pathBuffer); 1024 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) failed - 0x%08x\n", GetLastError()); 1025 1026 /* There should be some content in the listbox. Since the parent directory does not 1027 * fit w*.c, there should be exactly the same number of items as without DDL_DIRECTORY 1028 */ 1029 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1030 ok (itemCount == itemCount_justFiles, 1031 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) filled with %d entries, expected %d\n", 1032 itemCount, itemCount_justFiles); 1033 ok(res + 1 == itemCount, 1034 "SendMessage(LB_DIR, DDL_DIRECTORY, w*.c) returned incorrect index (expected %d got %d)!\n", 1035 itemCount - 1, res); 1036 1037 /* Every single item in the control should start with a w and end in .c. */ 1038 for (i = 0; i < itemCount; i++) 1039 { 1040 memset(pathBuffer, 0, MAX_PATH); 1041 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1042 p = pathBuffer + strlen(pathBuffer); 1043 ok( 1044 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1045 (*(p-1) == 'c' || *(p-1) == 'C') && 1046 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1047 } 1048 1049 /* Test DDL_DRIVES|DDL_EXCLUSIVE */ 1050 strcpy(pathBuffer, wildcard); 1051 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1052 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1053 ok (res >= 0, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) failed - 0x%08x\n", GetLastError()); 1054 1055 /* There should be some content in the listbox. In particular, there should 1056 * be at least one element before, since the string "[-c-]" should 1057 * have been added. Depending on the user setting, more drives might have 1058 * been added. 1059 */ 1060 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1061 ok (itemCount >= 1, 1062 "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) filled with %d entries, expected at least %d\n", 1063 itemCount, 1); 1064 itemCount_justDrives = itemCount; 1065 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, *) returned incorrect index!\n"); 1066 1067 /* Every single item in the control should fit the format [-c-] */ 1068 for (i = 0; i < itemCount; i++) 1069 { 1070 memset(pathBuffer, 0, MAX_PATH); 1071 driveletter = '\0'; 1072 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1073 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" ); 1074 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer); 1075 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1076 if (!(driveletter >= 'a' && driveletter <= 'z')) 1077 { 1078 /* Correct after invalid entry is found */ 1079 itemCount_justDrives--; 1080 } 1081 } 1082 1083 /* This tests behavior when no files match the wildcard */ 1084 strcpy(pathBuffer, BAD_EXTENSION); 1085 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1086 res = SendMessageA(hList, LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1087 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n", 1088 BAD_EXTENSION, res, itemCount_justDrives -1); 1089 1090 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1091 ok (itemCount == itemCount_justDrives, "SendMessage(LB_DIR) returned %d expected %d\n", 1092 itemCount, itemCount_justDrives); 1093 1094 /* Test DDL_DRIVES. */ 1095 strcpy(pathBuffer, wildcard); 1096 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1097 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer); 1098 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, *) failed - 0x%08x\n", GetLastError()); 1099 1100 /* There should be some content in the listbox. In particular, there should 1101 * be at least one element before, since the string "[-c-]" should 1102 * have been added. Depending on the user setting, more drives might have 1103 * been added. 1104 */ 1105 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1106 ok (itemCount == itemCount_justDrives + itemCount_allFiles, 1107 "SendMessage(LB_DIR, DDL_DRIVES, *) filled with %d entries, expected %d\n", 1108 itemCount, itemCount_justDrives + itemCount_allFiles); 1109 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, *) returned incorrect index!\n"); 1110 1111 /* This tests behavior when no files match the wildcard */ 1112 strcpy(pathBuffer, BAD_EXTENSION); 1113 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1114 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer); 1115 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DRIVES, %s) returned %d, expected %d\n", 1116 BAD_EXTENSION, res, itemCount_justDrives -1); 1117 1118 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1119 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1); 1120 1121 /* Test DDL_DRIVES. */ 1122 strcpy(pathBuffer, "w*.c"); 1123 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1124 res = SendMessageA(hList, LB_DIR, DDL_DRIVES, (LPARAM)pathBuffer); 1125 ok (res > 0, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError()); 1126 1127 /* There should be some content in the listbox. In particular, there should 1128 * be at least one element before, since the string "[-c-]" should 1129 * have been added. Depending on the user setting, more drives might have 1130 * been added. 1131 */ 1132 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1133 ok (itemCount == itemCount_justDrives + itemCount_justFiles, 1134 "SendMessage(LB_DIR, DDL_DRIVES, w*.c) filled with %d entries, expected %d\n", 1135 itemCount, itemCount_justDrives + itemCount_justFiles); 1136 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DRIVES, w*.c) returned incorrect index!\n"); 1137 1138 /* Every single item in the control should fit the format [-c-], or w*.c */ 1139 for (i = 0; i < itemCount; i++) 1140 { 1141 memset(pathBuffer, 0, MAX_PATH); 1142 driveletter = '\0'; 1143 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1144 p = pathBuffer + strlen(pathBuffer); 1145 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) 1146 { 1147 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" ); 1148 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1149 } 1150 else 1151 { 1152 ok( 1153 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1154 (*(p-1) == 'c' || *(p-1) == 'C') && 1155 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1156 } 1157 } 1158 1159 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */ 1160 strcpy(pathBuffer, wildcard); 1161 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1162 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer); 1163 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, *) failed - 0x%08x\n", GetLastError()); 1164 1165 /* There should be some content in the listbox. In particular, there should 1166 * be exactly the number of plain files, plus the number of mapped drives. 1167 */ 1168 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1169 ok (itemCount == itemCount_allFiles + itemCount_justDrives + itemCount_allDirs, 1170 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n", 1171 itemCount, itemCount_allFiles + itemCount_justDrives + itemCount_allDirs); 1172 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n"); 1173 1174 /* Every single item in the control should start with a w and end in .c, 1175 * except for the "[..]" string, which should appear exactly as it is, 1176 * and the mapped drives in the format "[-X-]". 1177 */ 1178 for (i = 0; i < itemCount; i++) 1179 { 1180 memset(pathBuffer, 0, MAX_PATH); 1181 driveletter = '\0'; 1182 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1183 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) 1184 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1185 } 1186 1187 /* This tests behavior when no files match the wildcard */ 1188 strcpy(pathBuffer, BAD_EXTENSION); 1189 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1190 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer); 1191 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, %s) returned %d, expected %d\n", 1192 BAD_EXTENSION, res, itemCount_justDrives -1); 1193 1194 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1195 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1); 1196 1197 /* Test DDL_DIRECTORY|DDL_DRIVES. */ 1198 strcpy(pathBuffer, "w*.c"); 1199 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1200 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES, (LPARAM)pathBuffer); 1201 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) failed - 0x%08x\n", GetLastError()); 1202 1203 /* There should be some content in the listbox. In particular, there should 1204 * be exactly the number of plain files, plus the number of mapped drives. 1205 */ 1206 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1207 ok (itemCount == itemCount_justFiles + itemCount_justDrives, 1208 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n", 1209 itemCount, itemCount_justFiles + itemCount_justDrives); 1210 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES, w*.c) returned incorrect index!\n"); 1211 1212 /* Every single item in the control should start with a w and end in .c, 1213 * except the mapped drives in the format "[-X-]". The "[..]" directory 1214 * should not appear. 1215 */ 1216 for (i = 0; i < itemCount; i++) 1217 { 1218 memset(pathBuffer, 0, MAX_PATH); 1219 driveletter = '\0'; 1220 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1221 p = pathBuffer + strlen(pathBuffer); 1222 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) 1223 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1224 else 1225 ok( 1226 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1227 (*(p-1) == 'c' || *(p-1) == 'C') && 1228 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1229 } 1230 1231 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */ 1232 strcpy(pathBuffer, wildcard); 1233 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1234 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1235 ok (res != -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) failed err %u\n", 1236 GetLastError()); 1237 1238 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1239 ok (itemCount == itemCount_allDirs, 1240 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1241 itemCount, itemCount_allDirs); 1242 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, *) returned incorrect index!\n"); 1243 1244 if (itemCount) 1245 { 1246 memset(pathBuffer, 0, MAX_PATH); 1247 SendMessageA(hList, LB_GETTEXT, 0, (LPARAM)pathBuffer); 1248 ok( !strcmp(pathBuffer, "[..]"), "First element is %s, not [..]\n", pathBuffer); 1249 } 1250 1251 /* This tests behavior when no files match the wildcard */ 1252 strcpy(pathBuffer, BAD_EXTENSION); 1253 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1254 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1255 ok (res == -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, %s) returned %d, expected %d\n", 1256 BAD_EXTENSION, res, -1); 1257 1258 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1259 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1); 1260 1261 1262 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */ 1263 strcpy(pathBuffer, "w*.c"); 1264 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1265 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1266 ok (res == LB_ERR, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE, w*.c) returned %d expected %d\n", res, LB_ERR); 1267 1268 /* There should be no elements, since "[..]" does not fit w*.c */ 1269 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1270 ok (itemCount == 0, 1271 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1272 itemCount, 0); 1273 1274 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */ 1275 strcpy(pathBuffer, wildcard); 1276 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1277 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1278 ok (res > 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError()); 1279 1280 /* There should be no plain files on the listbox */ 1281 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1282 ok (itemCount == itemCount_justDrives + itemCount_allDirs, 1283 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1284 itemCount, itemCount_justDrives + itemCount_allDirs); 1285 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n"); 1286 1287 for (i = 0; i < itemCount; i++) 1288 { 1289 memset(pathBuffer, 0, MAX_PATH); 1290 driveletter = '\0'; 1291 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1292 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) 1293 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1294 else 1295 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', 1296 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer); 1297 } 1298 1299 /* This tests behavior when no files match the wildcard */ 1300 strcpy(pathBuffer, BAD_EXTENSION); 1301 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1302 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1303 ok (res == itemCount_justDrives -1, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, %s) returned %d, expected %d\n", 1304 BAD_EXTENSION, res, itemCount_justDrives -1); 1305 1306 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1307 ok (itemCount == res + 1, "SendMessage(LB_DIR) returned %d expected %d\n", itemCount, res + 1); 1308 1309 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */ 1310 strcpy(pathBuffer, "w*.c"); 1311 SendMessageA(hList, LB_RESETCONTENT, 0, 0); 1312 res = SendMessageA(hList, LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, (LPARAM)pathBuffer); 1313 ok (res >= 0, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c,) failed - 0x%08x\n", GetLastError()); 1314 1315 /* There should be no plain files on the listbox, and no [..], since it does not fit w*.c */ 1316 itemCount = SendMessageA(hList, LB_GETCOUNT, 0, 0); 1317 ok (itemCount == itemCount_justDrives, 1318 "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1319 itemCount, itemCount_justDrives); 1320 ok(res + 1 == itemCount, "SendMessage(LB_DIR, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE, w*.c) returned incorrect index!\n"); 1321 1322 for (i = 0; i < itemCount; i++) 1323 { 1324 memset(pathBuffer, 0, MAX_PATH); 1325 driveletter = '\0'; 1326 SendMessageA(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); 1327 ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer); 1328 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1329 } 1330 DestroyWindow(hList); 1331 1332 DeleteFileA( "wtest1.tmp.c" ); 1333 RemoveDirectoryA("lb_dir_test"); 1334 1335 SetCurrentDirectoryA(curdir); 1336 } 1337 1338 static HWND g_listBox; 1339 static HWND g_label; 1340 1341 #define ID_TEST_LABEL 1001 1342 #define ID_TEST_LISTBOX 1002 1343 1344 static BOOL on_listbox_container_create(HWND hwnd, CREATESTRUCTA *lpcs) 1345 { 1346 g_label = CreateWindowA(WC_STATICA, "Contents of static control before DlgDirList.", 1347 WS_CHILD | WS_VISIBLE, 10, 10, 512, 32, hwnd, (HMENU)ID_TEST_LABEL, NULL, 0); 1348 if (!g_label) return FALSE; 1349 1350 g_listBox = CreateWindowA(WC_LISTBOXA, "DlgDirList test", 1351 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_VSCROLL, 10, 60, 256, 256, 1352 hwnd, (HMENU)ID_TEST_LISTBOX, NULL, 0); 1353 if (!g_listBox) return FALSE; 1354 1355 return TRUE; 1356 } 1357 1358 static LRESULT CALLBACK listbox_container_window_procA(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) 1359 { 1360 LRESULT result = 0; 1361 1362 switch (uiMsg) 1363 { 1364 case WM_DESTROY: 1365 PostQuitMessage(0); 1366 break; 1367 case WM_CREATE: 1368 result = on_listbox_container_create(hwnd, (CREATESTRUCTA *)lParam) ? 0 : (LRESULT)-1; 1369 break; 1370 default: 1371 result = DefWindowProcA(hwnd, uiMsg, wParam, lParam); 1372 break; 1373 } 1374 return result; 1375 } 1376 1377 static BOOL RegisterListboxWindowClass(HINSTANCE hInst) 1378 { 1379 WNDCLASSA cls; 1380 1381 cls.style = 0; 1382 cls.cbClsExtra = 0; 1383 cls.cbWndExtra = 0; 1384 cls.hInstance = hInst; 1385 cls.hIcon = NULL; 1386 cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW); 1387 cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 1388 cls.lpszMenuName = NULL; 1389 cls.lpfnWndProc = listbox_container_window_procA; 1390 cls.lpszClassName = "ListboxContainerClass"; 1391 if (!RegisterClassA (&cls)) return FALSE; 1392 1393 return TRUE; 1394 } 1395 1396 static void test_listbox_dlgdir(void) 1397 { 1398 HINSTANCE hInst; 1399 HWND hWnd; 1400 int res, itemCount; 1401 int itemCount_allDirs; 1402 int itemCount_justFiles; 1403 int itemCount_justDrives; 1404 int i; 1405 char pathBuffer[MAX_PATH]; 1406 char itemBuffer[MAX_PATH]; 1407 char tempBuffer[MAX_PATH]; 1408 char * p; 1409 char driveletter; 1410 HANDLE file; 1411 BOOL ret; 1412 1413 file = CreateFileA( "wtest1.tmp.c", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL ); 1414 ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d\n", GetLastError()); 1415 CloseHandle( file ); 1416 1417 /* NOTE: for this test to succeed, there must be no subdirectories 1418 under the current directory. In addition, there must be at least 1419 one file that fits the wildcard w*.c . Normally, the test 1420 directory itself satisfies both conditions. 1421 */ 1422 1423 hInst = GetModuleHandleA(0); 1424 ret = RegisterListboxWindowClass(hInst); 1425 ok(ret, "Failed to register test class.\n"); 1426 1427 hWnd = CreateWindowA("ListboxContainerClass", "ListboxContainerClass", 1428 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 1429 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 1430 NULL, NULL, hInst, 0); 1431 ok(hWnd != NULL, "Failed to create container window.\n"); 1432 1433 /* Test for standard usage */ 1434 1435 /* The following should be overwritten by the directory path */ 1436 SendMessageA(g_label, WM_SETTEXT, 0, (LPARAM)"default contents"); 1437 1438 /* This should list all the w*.c files in the test directory 1439 * As of this writing, this includes win.c, winstation.c, wsprintf.c 1440 */ 1441 strcpy(pathBuffer, "w*.c"); 1442 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0); 1443 ok (res == 1, "DlgDirList(*.c, 0) returned %d - expected 1 - 0x%08x\n", res, GetLastError()); 1444 1445 /* Path specification gets converted to uppercase */ 1446 ok (!strcmp(pathBuffer, "W*.C"), 1447 "expected conversion to uppercase, got %s\n", pathBuffer); 1448 1449 /* Loaded path should have overwritten the label text */ 1450 SendMessageA(g_label, WM_GETTEXT, MAX_PATH, (LPARAM)pathBuffer); 1451 ok (strcmp("default contents", pathBuffer), "DlgDirList() did not modify static control!\n"); 1452 1453 /* There should be some content in the listbox */ 1454 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1455 ok (itemCount > 0, "DlgDirList() did NOT fill the listbox!\n"); 1456 itemCount_justFiles = itemCount; 1457 1458 /* Every single item in the control should start with a w and end in .c */ 1459 for (i = 0; i < itemCount; i++) 1460 { 1461 memset(pathBuffer, 0, MAX_PATH); 1462 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1463 p = pathBuffer + strlen(pathBuffer); 1464 ok(((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1465 (*(p-1) == 'c' || *(p-1) == 'C') && 1466 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1467 } 1468 1469 /* Test behavior when no files match the wildcard */ 1470 strcpy(pathBuffer, BAD_EXTENSION); 1471 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, 0); 1472 ok (res == 1, "DlgDirList(%s, 0) returned %d expected 1\n", BAD_EXTENSION, res); 1473 1474 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1475 ok (itemCount == 0, "DlgDirList() DID fill the listbox!\n"); 1476 1477 /* Test DDL_DIRECTORY */ 1478 strcpy(pathBuffer, "w*.c"); 1479 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY); 1480 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY) failed - 0x%08x\n", GetLastError()); 1481 1482 /* There should be some content in the listbox. In particular, there should 1483 * be exactly more elements than before, since the directories should 1484 * have been added. 1485 */ 1486 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1487 itemCount_allDirs = itemCount - itemCount_justFiles; 1488 ok (itemCount >= itemCount_justFiles, "DlgDirList(DDL_DIRECTORY) filled with %d entries, expected > %d\n", 1489 itemCount, itemCount_justFiles); 1490 1491 /* Every single item in the control should start with a w and end in .c, 1492 * except for the "[..]" string, which should appear exactly as it is. 1493 */ 1494 for (i = 0; i < itemCount; i++) 1495 { 1496 memset(pathBuffer, 0, MAX_PATH); 1497 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1498 p = pathBuffer + strlen(pathBuffer); 1499 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') || 1500 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1501 (*(p-1) == 'c' || *(p-1) == 'C') && 1502 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1503 } 1504 1505 /* Test behavior when no files match the wildcard */ 1506 strcpy(pathBuffer, BAD_EXTENSION); 1507 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY); 1508 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY) returned %d expected 1\n", BAD_EXTENSION, res); 1509 1510 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1511 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n", 1512 itemCount_allDirs, itemCount); 1513 for (i = 0; i < itemCount; i++) 1514 { 1515 memset(pathBuffer, 0, MAX_PATH); 1516 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1517 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', 1518 "Element %d (%s) does not fit requested [...]\n", i, pathBuffer); 1519 } 1520 1521 /* Test DDL_DRIVES. At least on WinXP-SP2, this implies DDL_EXCLUSIVE */ 1522 strcpy(pathBuffer, "w*.c"); 1523 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DRIVES); 1524 ok (res == 1, "DlgDirList(*.c, DDL_DRIVES) failed - 0x%08x\n", GetLastError()); 1525 1526 /* There should be some content in the listbox. In particular, there should 1527 * be at least one element before, since the string "[-c-]" should 1528 * have been added. Depending on the user setting, more drives might have 1529 * been added. 1530 */ 1531 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1532 ok (itemCount >= 1, 1533 "DlgDirList(DDL_DRIVES) filled with %d entries, expected at least %d\n", 1534 itemCount, 1); 1535 itemCount_justDrives = itemCount; 1536 1537 /* Every single item in the control should fit the format [-c-] */ 1538 for (i = 0; i < itemCount; i++) 1539 { 1540 memset(pathBuffer, 0, MAX_PATH); 1541 driveletter = '\0'; 1542 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1543 ok( strlen(pathBuffer) == 5, "Length of drive string is not 5\n" ); 1544 ok( sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer); 1545 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1546 if (!(driveletter >= 'a' && driveletter <= 'z')) { 1547 /* Correct after invalid entry is found */ 1548 trace("removing count of invalid entry %s\n", pathBuffer); 1549 itemCount_justDrives--; 1550 } 1551 } 1552 1553 /* Test behavior when no files match the wildcard */ 1554 strcpy(pathBuffer, BAD_EXTENSION); 1555 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DRIVES); 1556 ok (res == 1, "DlgDirList(%s, DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res); 1557 1558 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1559 ok (itemCount == itemCount_justDrives, "DlgDirList() incorrectly filled the listbox!\n"); 1560 1561 /* Test DDL_DIRECTORY|DDL_DRIVES. This does *not* imply DDL_EXCLUSIVE */ 1562 strcpy(pathBuffer, "w*.c"); 1563 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES); 1564 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError()); 1565 1566 /* There should be some content in the listbox. In particular, there should 1567 * be exactly the number of plain files, plus the number of mapped drives, 1568 * plus one "[..]" 1569 */ 1570 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1571 ok (itemCount == itemCount_justFiles + itemCount_justDrives + itemCount_allDirs, 1572 "DlgDirList(DDL_DIRECTORY|DDL_DRIVES) filled with %d entries, expected %d\n", 1573 itemCount, itemCount_justFiles + itemCount_justDrives + itemCount_allDirs); 1574 1575 /* Every single item in the control should start with a w and end in .c, 1576 * except for the "[..]" string, which should appear exactly as it is, 1577 * and the mapped drives in the format "[-X-]". 1578 */ 1579 for (i = 0; i < itemCount; i++) 1580 { 1581 memset(pathBuffer, 0, MAX_PATH); 1582 driveletter = '\0'; 1583 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1584 p = pathBuffer + strlen(pathBuffer); 1585 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) 1586 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1587 else 1588 ok( (pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']') || 1589 ((pathBuffer[0] == 'w' || pathBuffer[0] == 'W') && 1590 (*(p-1) == 'c' || *(p-1) == 'C') && 1591 (*(p-2) == '.')), "Element %d (%s) does not fit requested w*.c\n", i, pathBuffer); 1592 } 1593 1594 /* Test behavior when no files match the wildcard */ 1595 strcpy(pathBuffer, BAD_EXTENSION); 1596 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES); 1597 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES) returned %d expected 1\n", BAD_EXTENSION, res); 1598 1599 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1600 ok (itemCount == itemCount_justDrives + itemCount_allDirs, 1601 "DlgDirList() incorrectly filled the listbox! (expected %d got %d)\n", 1602 itemCount_justDrives + itemCount_allDirs, itemCount); 1603 1604 /* Test DDL_DIRECTORY|DDL_EXCLUSIVE. */ 1605 strcpy(pathBuffer, "w*.c"); 1606 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_EXCLUSIVE); 1607 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError()); 1608 1609 /* There should be exactly one element: "[..]" */ 1610 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1611 ok (itemCount == itemCount_allDirs, 1612 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1613 itemCount, itemCount_allDirs); 1614 1615 if (itemCount && GetCurrentDirectoryA( MAX_PATH, pathBuffer ) > 3) /* there's no [..] in drive root */ 1616 { 1617 memset(pathBuffer, 0, MAX_PATH); 1618 SendMessageA(g_listBox, LB_GETTEXT, 0, (LPARAM)pathBuffer); 1619 ok( !strcmp(pathBuffer, "[..]"), "First (and only) element is not [..]\n"); 1620 } 1621 1622 /* Test behavior when no files match the wildcard */ 1623 strcpy(pathBuffer, BAD_EXTENSION); 1624 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_EXCLUSIVE); 1625 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res); 1626 1627 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1628 ok (itemCount == itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n"); 1629 1630 /* Test DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE. */ 1631 strcpy(pathBuffer, "w*.c"); 1632 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE); 1633 ok (res == 1, "DlgDirList(*.c, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) failed - 0x%08x\n", GetLastError()); 1634 1635 /* There should be no plain files on the listbox */ 1636 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1637 ok (itemCount == itemCount_justDrives + itemCount_allDirs, 1638 "DlgDirList(DDL_DIRECTORY|DDL_EXCLUSIVE) filled with %d entries, expected %d\n", 1639 itemCount, itemCount_justDrives + itemCount_allDirs); 1640 1641 for (i = 0; i < itemCount; i++) 1642 { 1643 memset(pathBuffer, 0, MAX_PATH); 1644 driveletter = '\0'; 1645 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); 1646 if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) 1647 ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); 1648 else 1649 ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', 1650 "Element %d (%s) does not fit expected [...]\n", i, pathBuffer); 1651 } 1652 1653 /* Test behavior when no files match the wildcard */ 1654 strcpy(pathBuffer, BAD_EXTENSION); 1655 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE); 1656 ok (res == 1, "DlgDirList(%s, DDL_DIRECTORY|DDL_DRIVES|DDL_EXCLUSIVE) returned %d expected 1\n", BAD_EXTENSION, res); 1657 1658 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1659 ok (itemCount == itemCount_justDrives + itemCount_allDirs, "DlgDirList() incorrectly filled the listbox!\n"); 1660 1661 /* Now test DlgDirSelectEx() in normal operation */ 1662 /* Fill with everything - drives, directory and all plain files. */ 1663 strcpy(pathBuffer, "*"); 1664 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, ID_TEST_LABEL, DDL_DIRECTORY|DDL_DRIVES); 1665 ok (res != 0, "DlgDirList(*, DDL_DIRECTORY|DDL_DRIVES) failed - 0x%08x\n", GetLastError()); 1666 1667 SendMessageA(g_listBox, LB_SETCURSEL, -1, 0); /* Unselect any current selection */ 1668 memset(pathBuffer, 0, MAX_PATH); 1669 SetLastError(0xdeadbeef); 1670 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1671 ok (GetLastError() == 0xdeadbeef, 1672 "DlgDirSelectEx() with no selection modified last error code from 0xdeadbeef to 0x%08x\n", 1673 GetLastError()); 1674 ok (res == 0, "DlgDirSelectEx() with no selection returned %d, expected 0\n", res); 1675 /* WinXP-SP2 leaves pathBuffer untouched, but Win98 fills it with garbage. */ 1676 /* 1677 ok (strlen(pathBuffer) == 0, "DlgDirSelectEx() with no selection filled buffer with %s\n", pathBuffer); 1678 */ 1679 /* Test proper drive/dir/file recognition */ 1680 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1681 for (i = 0; i < itemCount; i++) 1682 { 1683 memset(itemBuffer, 0, MAX_PATH); 1684 memset(pathBuffer, 0, MAX_PATH); 1685 memset(tempBuffer, 0, MAX_PATH); 1686 driveletter = '\0'; 1687 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer); 1688 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0); 1689 ok (res == i, "SendMessageA(LB_SETCURSEL, %d) failed\n", i); 1690 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) 1691 { 1692 /* Current item is a drive letter */ 1693 SetLastError(0xdeadbeef); 1694 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1695 ok (GetLastError() == 0xdeadbeef, 1696 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1697 i, GetLastError()); 1698 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); 1699 1700 /* For drive letters, DlgDirSelectEx tacks on a colon */ 1701 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0', 1702 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter); 1703 } 1704 else if (itemBuffer[0] == '[') 1705 { 1706 /* Current item is the parent directory */ 1707 SetLastError(0xdeadbeef); 1708 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1709 ok (GetLastError() == 0xdeadbeef, 1710 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1711 i, GetLastError()); 1712 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); 1713 1714 /* For directories, DlgDirSelectEx tacks on a backslash */ 1715 p = pathBuffer + strlen(pathBuffer); 1716 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer); 1717 1718 tempBuffer[0] = '['; 1719 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer)); 1720 strcat(tempBuffer, "]"); 1721 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer); 1722 } 1723 else 1724 { 1725 /* Current item is a plain file */ 1726 SetLastError(0xdeadbeef); 1727 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1728 ok (GetLastError() == 0xdeadbeef, 1729 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1730 i, GetLastError()); 1731 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer); 1732 1733 /* NOTE: WinXP tacks a period on all files that lack an extension. This affects 1734 * for example, "Makefile", which gets reported as "Makefile." 1735 */ 1736 strcpy(tempBuffer, itemBuffer); 1737 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, "."); 1738 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer); 1739 } 1740 } 1741 1742 DeleteFileA( "wtest1.tmp.c" ); 1743 1744 /* Now test DlgDirSelectEx() in abnormal operation */ 1745 /* Fill list with bogus entries, that look somewhat valid */ 1746 SendMessageA(g_listBox, LB_RESETCONTENT, 0, 0); 1747 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"[notexist.dir]"); 1748 SendMessageA(g_listBox, LB_ADDSTRING, 0, (LPARAM)"notexist.fil"); 1749 itemCount = SendMessageA(g_listBox, LB_GETCOUNT, 0, 0); 1750 for (i = 0; i < itemCount; i++) 1751 { 1752 memset(itemBuffer, 0, MAX_PATH); 1753 memset(pathBuffer, 0, MAX_PATH); 1754 memset(tempBuffer, 0, MAX_PATH); 1755 driveletter = '\0'; 1756 SendMessageA(g_listBox, LB_GETTEXT, i, (LPARAM)itemBuffer); 1757 res = SendMessageA(g_listBox, LB_SETCURSEL, i, 0); 1758 ok (res == i, "SendMessage(LB_SETCURSEL, %d) failed\n", i); 1759 if (sscanf(itemBuffer, "[-%c-]", &driveletter) == 1) 1760 { 1761 /* Current item is a drive letter */ 1762 SetLastError(0xdeadbeef); 1763 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1764 ok (GetLastError() == 0xdeadbeef, 1765 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1766 i, GetLastError()); 1767 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); 1768 1769 /* For drive letters, DlgDirSelectEx tacks on a colon */ 1770 ok (pathBuffer[0] == driveletter && pathBuffer[1] == ':' && pathBuffer[2] == '\0', 1771 "%d: got \"%s\" expected \"%c:\"\n", i, pathBuffer, driveletter); 1772 } 1773 else if (itemBuffer[0] == '[') 1774 { 1775 /* Current item is the parent directory */ 1776 SetLastError(0xdeadbeef); 1777 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1778 ok (GetLastError() == 0xdeadbeef, 1779 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1780 i, GetLastError()); 1781 ok(res == 1, "DlgDirSelectEx() thinks %s (%s) is not a drive/directory!\n", itemBuffer, pathBuffer); 1782 1783 /* For directories, DlgDirSelectEx tacks on a backslash */ 1784 p = pathBuffer + strlen(pathBuffer); 1785 ok (*(p-1) == '\\', "DlgDirSelectEx did NOT tack on a backslash to dir, got %s\n", pathBuffer); 1786 1787 tempBuffer[0] = '['; 1788 lstrcpynA(tempBuffer + 1, pathBuffer, strlen(pathBuffer)); 1789 strcat(tempBuffer, "]"); 1790 ok (!strcmp(tempBuffer, itemBuffer), "Formatted directory should be %s, got %s\n", tempBuffer, itemBuffer); 1791 } 1792 else 1793 { 1794 /* Current item is a plain file */ 1795 SetLastError(0xdeadbeef); 1796 res = DlgDirSelectExA(hWnd, pathBuffer, MAX_PATH, ID_TEST_LISTBOX); 1797 ok (GetLastError() == 0xdeadbeef, 1798 "DlgDirSelectEx() with selection at %d modified last error code from 0xdeadbeef to 0x%08x\n", 1799 i, GetLastError()); 1800 ok(res == 0, "DlgDirSelectEx() thinks %s (%s) is a drive/directory!\n", itemBuffer, pathBuffer); 1801 1802 /* NOTE: WinXP and Win98 tack a period on all files that lack an extension. 1803 * This affects for example, "Makefile", which gets reported as "Makefile." 1804 */ 1805 strcpy(tempBuffer, itemBuffer); 1806 if (strchr(tempBuffer, '.') == NULL) strcat(tempBuffer, "."); 1807 ok (!strcmp(pathBuffer, tempBuffer), "Formatted file should be %s, got %s\n", tempBuffer, pathBuffer); 1808 } 1809 } 1810 1811 /* Test behavior when loading folders from root with and without wildcard */ 1812 strcpy(pathBuffer, "C:\\"); 1813 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE); 1814 ok(res, "DlgDirList failed to list C:\\ folders\n"); 1815 todo_wine ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer); 1816 1817 strcpy(pathBuffer, "C:\\*"); 1818 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE); 1819 ok(res, "DlgDirList failed to list C:\\* folders\n"); 1820 ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer); 1821 1822 /* Try loading files from an invalid folder */ 1823 SetLastError(0xdeadbeef); 1824 strcpy(pathBuffer, "C:\\INVALID$$DIR"); 1825 res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE); 1826 todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res); 1827 todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS, 1828 "GetLastError should return 0x589, got 0x%X\n",GetLastError()); 1829 1830 DestroyWindow(hWnd); 1831 } 1832 1833 static void test_set_count( void ) 1834 { 1835 static const DWORD styles[] = 1836 { 1837 LBS_OWNERDRAWFIXED, 1838 LBS_HASSTRINGS, 1839 }; 1840 HWND parent, listbox; 1841 unsigned int i; 1842 LONG ret; 1843 RECT r; 1844 1845 parent = create_parent(); 1846 listbox = create_listbox( LBS_OWNERDRAWFIXED | LBS_NODATA | WS_CHILD | WS_VISIBLE, parent ); 1847 1848 UpdateWindow( listbox ); 1849 GetUpdateRect( listbox, &r, TRUE ); 1850 ok( IsRectEmpty( &r ), "got non-empty rect\n"); 1851 1852 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 ); 1853 ok( ret == 0, "got %d\n", ret ); 1854 ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 ); 1855 ok( ret == 100, "got %d\n", ret ); 1856 1857 GetUpdateRect( listbox, &r, TRUE ); 1858 ok( !IsRectEmpty( &r ), "got empty rect\n"); 1859 1860 ValidateRect( listbox, NULL ); 1861 GetUpdateRect( listbox, &r, TRUE ); 1862 ok( IsRectEmpty( &r ), "got non-empty rect\n"); 1863 1864 ret = SendMessageA( listbox, LB_SETCOUNT, 99, 0 ); 1865 ok( ret == 0, "got %d\n", ret ); 1866 1867 GetUpdateRect( listbox, &r, TRUE ); 1868 ok( !IsRectEmpty( &r ), "got empty rect\n"); 1869 1870 DestroyWindow( listbox ); 1871 1872 for (i = 0; i < ARRAY_SIZE(styles); ++i) 1873 { 1874 listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent ); 1875 1876 SetLastError( 0xdeadbeef ); 1877 ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 ); 1878 ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret ); 1879 ok( GetLastError() == 0xdeadbeef, "Unexpected error %d.\n", GetLastError() ); 1880 1881 DestroyWindow( listbox ); 1882 } 1883 1884 DestroyWindow( parent ); 1885 } 1886 1887 static void test_GetListBoxInfo(void) 1888 { 1889 static const struct message getlistboxinfo_seq[] = 1890 { 1891 { LB_GETLISTBOXINFO, sent }, 1892 { 0 } 1893 }; 1894 HWND listbox, parent; 1895 DWORD ret; 1896 1897 parent = create_parent(); 1898 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent); 1899 1900 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1901 ret = GetListBoxInfo(listbox); 1902 ok(ret > 0, "got %d\n", ret); 1903 ok_sequence(sequences, LB_SEQ_INDEX, getlistboxinfo_seq, "GetListBoxInfo()", FALSE); 1904 1905 DestroyWindow(listbox); 1906 DestroyWindow(parent); 1907 } 1908 1909 static void test_missing_lbuttonup(void) 1910 { 1911 HWND listbox, parent, capture; 1912 1913 parent = create_parent(); 1914 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent); 1915 1916 /* Send button down without a corresponding button up */ 1917 SendMessageA(listbox, WM_LBUTTONDOWN, 0, MAKELPARAM(10, 10)); 1918 capture = GetCapture(); 1919 ok(capture == listbox, "got %p expected %p\n", capture, listbox); 1920 1921 /* Capture is released and LBN_SELCHANGE sent during WM_KILLFOCUS */ 1922 got_selchange = 0; 1923 SetFocus(NULL); 1924 capture = GetCapture(); 1925 ok(capture == NULL, "got %p\n", capture); 1926 ok(got_selchange, "got %d\n", got_selchange); 1927 1928 DestroyWindow(listbox); 1929 DestroyWindow(parent); 1930 } 1931 1932 static void test_extents(void) 1933 { 1934 HWND listbox, parent; 1935 SCROLLINFO sinfo; 1936 DWORD res; 1937 BOOL br; 1938 1939 parent = create_parent(); 1940 1941 listbox = create_listbox(WS_CHILD | WS_VISIBLE, parent); 1942 1943 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 1944 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res); 1945 1946 sinfo.cbSize = sizeof(sinfo); 1947 sinfo.fMask = SIF_RANGE; 1948 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 1949 ok(br == TRUE, "GetScrollInfo failed\n"); 1950 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 1951 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax); 1952 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 1953 "List box should not have a horizontal scroll bar\n"); 1954 1955 /* horizontal extent < width */ 1956 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0); 1957 1958 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 1959 ok(res == 64, "Got wrong horizontal extent: %u\n", res); 1960 1961 sinfo.cbSize = sizeof(sinfo); 1962 sinfo.fMask = SIF_RANGE; 1963 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 1964 ok(br == TRUE, "GetScrollInfo failed\n"); 1965 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 1966 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax); 1967 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 1968 "List box should not have a horizontal scroll bar\n"); 1969 1970 /* horizontal extent > width */ 1971 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0); 1972 1973 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 1974 ok(res == 184, "Got wrong horizontal extent: %u\n", res); 1975 1976 sinfo.cbSize = sizeof(sinfo); 1977 sinfo.fMask = SIF_RANGE; 1978 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 1979 ok(br == TRUE, "GetScrollInfo failed\n"); 1980 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 1981 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax); 1982 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 1983 "List box should not have a horizontal scroll bar\n"); 1984 1985 DestroyWindow(listbox); 1986 1987 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL, parent); 1988 1989 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 1990 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res); 1991 1992 sinfo.cbSize = sizeof(sinfo); 1993 sinfo.fMask = SIF_RANGE; 1994 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 1995 ok(br == TRUE, "GetScrollInfo failed\n"); 1996 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 1997 ok(sinfo.nMax == 100, "got wrong max: %u\n", sinfo.nMax); 1998 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 1999 "List box should not have a horizontal scroll bar\n"); 2000 2001 /* horizontal extent < width */ 2002 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0); 2003 2004 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2005 ok(res == 64, "Got wrong horizontal extent: %u\n", res); 2006 2007 sinfo.cbSize = sizeof(sinfo); 2008 sinfo.fMask = SIF_RANGE; 2009 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2010 ok(br == TRUE, "GetScrollInfo failed\n"); 2011 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2012 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax); 2013 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 2014 "List box should not have a horizontal scroll bar\n"); 2015 2016 /* horizontal extent > width */ 2017 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0); 2018 2019 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2020 ok(res == 184, "Got wrong horizontal extent: %u\n", res); 2021 2022 sinfo.cbSize = sizeof(sinfo); 2023 sinfo.fMask = SIF_RANGE; 2024 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2025 ok(br == TRUE, "GetScrollInfo failed\n"); 2026 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2027 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax); 2028 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2029 "List box should have a horizontal scroll bar\n"); 2030 2031 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0); 2032 2033 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2034 ok(res == 0, "Got wrong horizontal extent: %u\n", res); 2035 2036 sinfo.cbSize = sizeof(sinfo); 2037 sinfo.fMask = SIF_RANGE; 2038 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2039 ok(br == TRUE, "GetScrollInfo failed\n"); 2040 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2041 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax); 2042 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) == 0, 2043 "List box should not have a horizontal scroll bar\n"); 2044 2045 DestroyWindow(listbox); 2046 2047 2048 listbox = create_listbox(WS_CHILD | WS_VISIBLE | WS_HSCROLL | LBS_DISABLENOSCROLL, parent); 2049 2050 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2051 ok(res == 0, "Got wrong initial horizontal extent: %u\n", res); 2052 2053 sinfo.cbSize = sizeof(sinfo); 2054 sinfo.fMask = SIF_RANGE; 2055 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2056 ok(br == TRUE, "GetScrollInfo failed\n"); 2057 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2058 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax); 2059 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2060 "List box should have a horizontal scroll bar\n"); 2061 2062 /* horizontal extent < width */ 2063 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 64, 0); 2064 2065 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2066 ok(res == 64, "Got wrong horizontal extent: %u\n", res); 2067 2068 sinfo.cbSize = sizeof(sinfo); 2069 sinfo.fMask = SIF_RANGE; 2070 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2071 ok(br == TRUE, "GetScrollInfo failed\n"); 2072 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2073 ok(sinfo.nMax == 63, "got wrong max: %u\n", sinfo.nMax); 2074 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2075 "List box should have a horizontal scroll bar\n"); 2076 2077 /* horizontal extent > width */ 2078 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 184, 0); 2079 2080 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2081 ok(res == 184, "Got wrong horizontal extent: %u\n", res); 2082 2083 sinfo.cbSize = sizeof(sinfo); 2084 sinfo.fMask = SIF_RANGE; 2085 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2086 ok(br == TRUE, "GetScrollInfo failed\n"); 2087 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2088 ok(sinfo.nMax == 183, "got wrong max: %u\n", sinfo.nMax); 2089 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2090 "List box should have a horizontal scroll bar\n"); 2091 2092 SendMessageA(listbox, LB_SETHORIZONTALEXTENT, 0, 0); 2093 2094 res = SendMessageA(listbox, LB_GETHORIZONTALEXTENT, 0, 0); 2095 ok(res == 0, "Got wrong horizontal extent: %u\n", res); 2096 2097 sinfo.cbSize = sizeof(sinfo); 2098 sinfo.fMask = SIF_RANGE; 2099 br = GetScrollInfo(listbox, SB_HORZ, &sinfo); 2100 ok(br == TRUE, "GetScrollInfo failed\n"); 2101 ok(sinfo.nMin == 0, "got wrong min: %u\n", sinfo.nMin); 2102 ok(sinfo.nMax == 0, "got wrong max: %u\n", sinfo.nMax); 2103 ok((GetWindowLongA(listbox, GWL_STYLE) & WS_HSCROLL) != 0, 2104 "List box should have a horizontal scroll bar\n"); 2105 2106 DestroyWindow(listbox); 2107 2108 DestroyWindow(parent); 2109 } 2110 2111 static void test_listbox(void) 2112 { 2113 static const struct listbox_test SS = 2114 /* {add_style} */ 2115 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2116 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2117 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2118 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2119 2120 /* {selected, anchor, caret, selcount}{TODO fields} */ 2121 static const struct listbox_test SS_NS = 2122 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2123 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2124 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2125 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2126 2127 static const struct listbox_test MS = 2128 {{ 0, LB_ERR, 0, 0}, {0,0,0,0}, 2129 { 1, 1, 1, 1}, {0,0,0,0}, 2130 { 2, 1, 2, 1}, {0,0,0,0}, 2131 { 0, LB_ERR, 0, 2}, {0,0,0,0}}; 2132 2133 static const struct listbox_test MS_NS = 2134 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2135 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2136 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2137 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2138 2139 static const struct listbox_test ES = 2140 {{ 0, LB_ERR, 0, 0}, {0,0,0,0}, 2141 { 1, 1, 1, 1}, {0,0,0,0}, 2142 { 2, 2, 2, 1}, {0,0,0,0}, 2143 { 0, LB_ERR, 0, 2}, {0,0,0,0}}; 2144 2145 static const struct listbox_test ES_NS = 2146 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2147 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2148 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2149 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2150 2151 static const struct listbox_test EMS = 2152 {{ 0, LB_ERR, 0, 0}, {0,0,0,0}, 2153 { 1, 1, 1, 1}, {0,0,0,0}, 2154 { 2, 2, 2, 1}, {0,0,0,0}, 2155 { 0, LB_ERR, 0, 2}, {0,0,0,0}}; 2156 2157 static const struct listbox_test EMS_NS = 2158 {{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, 2159 { 1, 1, 1, LB_ERR}, {0,0,0,0}, 2160 { 2, 2, 2, LB_ERR}, {0,0,0,0}, 2161 {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}}; 2162 2163 run_test(0, SS); 2164 run_test(LBS_NOSEL, SS_NS); 2165 run_test(LBS_MULTIPLESEL, MS); 2166 run_test(LBS_MULTIPLESEL | LBS_NOSEL, MS_NS); 2167 run_test(LBS_EXTENDEDSEL, ES); 2168 run_test(LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS); 2169 run_test(LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS); 2170 run_test(LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS); 2171 2172 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED, SS); 2173 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_NOSEL, SS_NS); 2174 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL, MS); 2175 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_MULTIPLESEL | LBS_NOSEL, MS_NS); 2176 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL, ES); 2177 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_NOSEL, ES_NS); 2178 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL, EMS); 2179 run_test(LBS_NODATA | LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL | LBS_MULTIPLESEL | LBS_NOSEL, EMS_NS); 2180 } 2181 2182 static const struct message lb_addstring_ownerdraw_parent_seq[] = 2183 { 2184 { WM_MEASUREITEM, sent|wparam|lparam, 0x1012, 0xf30604ed }, 2185 { WM_MEASUREITEM, sent|wparam|lparam, 0x1112, 0xf30604ee }, 2186 { WM_MEASUREITEM, sent|wparam|lparam, 0x1212, 0xf30604ef }, 2187 { 0 } 2188 }; 2189 2190 static const struct message lb_addstring_sort_parent_seq[] = 2191 { 2192 { WM_MEASUREITEM, sent|wparam|lparam, 0x1012, 0xf30604ed }, 2193 { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ed, 0xf30604ee }, 2194 { WM_MEASUREITEM, sent|wparam|lparam, 0x1112, 0xf30604ee }, 2195 { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ed, 0xf30604ef }, 2196 { WM_COMPAREITEM, sent|wparam|lparam, 0xf30604ee, 0xf30604ef }, 2197 { WM_MEASUREITEM, sent|wparam|lparam, 0x1212, 0xf30604ef }, 2198 { 0 } 2199 }; 2200 2201 static const struct message empty_seq[] = 2202 { 2203 { 0 } 2204 }; 2205 2206 static void test_WM_MEASUREITEM(void) 2207 { 2208 HWND parent, listbox; 2209 LRESULT data, ret; 2210 2211 parent = create_parent(); 2212 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE, parent); 2213 2214 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0); 2215 ok(data == (LRESULT)strings[0], "data = %08lx, expected %p\n", data, strings[0]); 2216 DestroyWindow(parent); 2217 2218 parent = create_parent(); 2219 listbox = create_listbox(WS_CHILD | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS, parent); 2220 2221 data = SendMessageA(listbox, LB_GETITEMDATA, 0, 0); 2222 ok(!data, "data = %08lx\n", data); 2223 2224 /* LBS_HASSTRINGS */ 2225 parent = create_parent(); 2226 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL, 2227 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | WS_VISIBLE, 2228 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 2229 2230 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2231 2232 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 2233 ok(ret == 0, "expected 0, got %ld\n", ret); 2234 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 2235 ok(ret == 1, "expected 1, got %ld\n", ret); 2236 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 2237 ok(ret == 2, "expected 2, got %ld\n", ret); 2238 2239 ok_sequence(sequences, PARENT_SEQ_INDEX, lb_addstring_ownerdraw_parent_seq, 2240 "LB_ADDSTRING (LBS_HASSTRINGS, ownerdraw)", FALSE); 2241 DestroyWindow(listbox); 2242 2243 /* LBS_SORT, no LBS_HASSTRINGS */ 2244 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL, 2245 WS_CHILD | LBS_NOTIFY | LBS_OWNERDRAWVARIABLE | LBS_SORT | WS_VISIBLE, 2246 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 2247 2248 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2249 2250 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 2251 ok(ret == 0, "expected 0, got %ld\n", ret); 2252 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 2253 ok(ret == 1, "expected 1, got %ld\n", ret); 2254 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 2255 ok(ret == 2, "expected 2, got %ld\n", ret); 2256 2257 ok_sequence(sequences, PARENT_SEQ_INDEX, lb_addstring_sort_parent_seq, "LB_ADDSTRING (LBS_SORT)", FALSE); 2258 DestroyWindow(listbox); 2259 2260 /* LBS_HASSTRINGS */ 2261 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL, 2262 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | WS_VISIBLE, 2263 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 2264 2265 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2266 2267 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 2268 ok(ret == 0, "expected 0, got %ld\n", ret); 2269 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 2270 ok(ret == 1, "expected 1, got %ld\n", ret); 2271 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 2272 ok(ret == 2, "expected 2, got %ld\n", ret); 2273 2274 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "LB_ADDSTRING (LBS_HASSTRINGS)", FALSE); 2275 DestroyWindow(listbox); 2276 2277 /* LBS_HASSTRINGS, LBS_SORT */ 2278 listbox = CreateWindowExA(WS_EX_NOPARENTNOTIFY, WC_LISTBOXA, NULL, 2279 WS_CHILD | LBS_NOTIFY | LBS_HASSTRINGS | LBS_SORT | WS_VISIBLE, 2280 10, 10, 80, 80, parent, (HMENU)ID_LISTBOX, 0, NULL); 2281 2282 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2283 2284 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 2"); 2285 ok(ret == 0, "expected 0, got %ld\n", ret); 2286 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 0"); 2287 ok(ret == 0, "expected 0, got %ld\n", ret); 2288 ret = SendMessageA(listbox, LB_ADDSTRING, 0, (LPARAM)"item 1"); 2289 ok(ret == 1, "expected 1, got %ld\n", ret); 2290 2291 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "LB_ADDSTRING (LBS_HASSTRINGS, LBS_SORT)", FALSE); 2292 DestroyWindow(listbox); 2293 2294 DestroyWindow(parent); 2295 } 2296 2297 static void test_LBS_NODATA(void) 2298 { 2299 static const DWORD invalid_styles[] = 2300 { 2301 0, 2302 LBS_OWNERDRAWVARIABLE, 2303 LBS_SORT, 2304 LBS_HASSTRINGS, 2305 LBS_OWNERDRAWFIXED | LBS_SORT, 2306 LBS_OWNERDRAWFIXED | LBS_HASSTRINGS, 2307 }; 2308 static const UINT invalid_idx[] = { -2, 2 }; 2309 static const UINT valid_idx[] = { 0, 1 }; 2310 static const ULONG_PTR zero_data; 2311 HWND listbox, parent; 2312 INT ret, text_len; 2313 unsigned int i; 2314 ULONG_PTR data; 2315 BOOL is_wow64; 2316 2317 listbox = CreateWindowA(WC_LISTBOXA, "TestList", LBS_NODATA | LBS_OWNERDRAWFIXED | WS_VISIBLE, 2318 0, 0, 100, 100, NULL, NULL, NULL, 0); 2319 ok(listbox != NULL, "Failed to create ListBox window.\n"); 2320 2321 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0); 2322 ok(ret == 0, "Unexpected return value %d.\n", ret); 2323 ret = SendMessageA(listbox, LB_INSERTSTRING, -1, 0); 2324 ok(ret == 1, "Unexpected return value %d.\n", ret); 2325 ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0); 2326 ok(ret == 2, "Unexpected return value %d.\n", ret); 2327 2328 /* Invalid indices. */ 2329 for (i = 0; i < ARRAY_SIZE(invalid_idx); ++i) 2330 { 2331 ret = SendMessageA(listbox, LB_SETITEMDATA, invalid_idx[i], 42); 2332 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2333 ret = SendMessageA(listbox, LB_GETTEXTLEN, invalid_idx[i], 0); 2334 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2335 if (ret == LB_ERR) 2336 { 2337 ret = SendMessageA(listbox, LB_GETTEXT, invalid_idx[i], (LPARAM)&data); 2338 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2339 } 2340 ret = SendMessageA(listbox, LB_GETITEMDATA, invalid_idx[i], 0); 2341 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2342 } 2343 2344 IsWow64Process(GetCurrentProcess(), &is_wow64); 2345 #ifdef _WIN64 2346 text_len = 8; 2347 #else 2348 text_len = is_wow64 ? 8 : 4; 2349 #endif 2350 2351 /* Valid indices. */ 2352 for (i = 0; i < ARRAY_SIZE(valid_idx); ++i) 2353 { 2354 ret = SendMessageA(listbox, LB_SETITEMDATA, valid_idx[i], 42); 2355 ok(ret == TRUE, "Unexpected return value %d.\n", ret); 2356 ret = SendMessageA(listbox, LB_GETTEXTLEN, valid_idx[i], 0); 2357 todo_wine_if(is_wow64) 2358 ok(ret == text_len, "Unexpected return value %d.\n", ret); 2359 2360 memset(&data, 0xee, sizeof(data)); 2361 ret = SendMessageA(listbox, LB_GETTEXT, valid_idx[i], (LPARAM)&data); 2362 ok(ret == sizeof(data), "Unexpected return value %d.\n", ret); 2363 ok(!memcmp(&data, &zero_data, sizeof(data)), "Unexpected item data.\n"); 2364 2365 ret = SendMessageA(listbox, LB_GETITEMDATA, valid_idx[i], 0); 2366 ok(ret == 0, "Unexpected return value %d.\n", ret); 2367 } 2368 2369 /* More messages that don't work with LBS_NODATA. */ 2370 ret = SendMessageA(listbox, LB_FINDSTRING, 1, 0); 2371 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2372 ret = SendMessageA(listbox, LB_FINDSTRING, 1, 42); 2373 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2374 ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 0); 2375 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2376 ret = SendMessageA(listbox, LB_FINDSTRINGEXACT, 1, 42); 2377 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2378 ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 0); 2379 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2380 ret = SendMessageA(listbox, LB_SELECTSTRING, 1, 42); 2381 ok(ret == LB_ERR, "Unexpected return value %d.\n", ret); 2382 2383 DestroyWindow(listbox); 2384 2385 /* Invalid window style combinations. */ 2386 parent = create_parent(); 2387 ok(parent != NULL, "Failed to create parent window.\n"); 2388 2389 for (i = 0; i < ARRAY_SIZE(invalid_styles); ++i) 2390 { 2391 DWORD style; 2392 2393 listbox = CreateWindowA(WC_LISTBOXA, "TestList", LBS_NODATA | WS_CHILD | invalid_styles[i], 2394 0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0); 2395 ok(listbox != NULL, "Failed to create a listbox.\n"); 2396 2397 style = GetWindowLongA(listbox, GWL_STYLE); 2398 ok((style & invalid_styles[i]) == invalid_styles[i], "%u: unexpected window styles %#x.\n", i, style); 2399 ret = SendMessageA(listbox, LB_SETCOUNT, 100, 0); 2400 ok(ret == LB_ERR, "%u: unexpected return value %d.\n", i, ret); 2401 DestroyWindow(listbox); 2402 } 2403 2404 DestroyWindow(parent); 2405 } 2406 2407 START_TEST(listbox) 2408 { 2409 ULONG_PTR ctx_cookie; 2410 HANDLE hCtx; 2411 2412 if (!load_v6_module(&ctx_cookie, &hCtx)) 2413 return; 2414 2415 init_msg_sequences(sequences, NUM_MSG_SEQUENCES); 2416 2417 test_listbox(); 2418 test_item_height(); 2419 test_ownerdraw(); 2420 test_LB_SELITEMRANGE(); 2421 test_LB_SETCURSEL(); 2422 test_listbox_height(); 2423 test_itemfrompoint(); 2424 test_listbox_item_data(); 2425 test_listbox_LB_DIR(); 2426 test_listbox_dlgdir(); 2427 test_set_count(); 2428 test_GetListBoxInfo(); 2429 test_missing_lbuttonup(); 2430 test_extents(); 2431 test_WM_MEASUREITEM(); 2432 test_LB_SETSEL(); 2433 test_LBS_NODATA(); 2434 2435 unload_v6_module(ctx_cookie, hCtx); 2436 } 2437