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