1 /* 2 * ListView tests 3 * 4 * Copyright 2006 Mike McCormack for CodeWeavers 5 * Copyright 2007 George Gov 6 * Copyright 2009-2014 Nikolay Sivov 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include <stdio.h> 24 #include <windows.h> 25 #include <commctrl.h> 26 27 #include "wine/test.h" 28 #include "v6util.h" 29 #include "msg.h" 30 31 static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int); 32 static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST); 33 static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP); 34 static BOOL (WINAPI *p_TrackMouseEvent)(TRACKMOUSEEVENT *); 35 36 enum seq_index { 37 PARENT_SEQ_INDEX, 38 PARENT_FULL_SEQ_INDEX, 39 PARENT_CD_SEQ_INDEX, 40 LISTVIEW_SEQ_INDEX, 41 EDITBOX_SEQ_INDEX, 42 COMBINED_SEQ_INDEX, 43 NUM_MSG_SEQUENCES 44 }; 45 46 #define LISTVIEW_ID 0 47 #define HEADER_ID 1 48 49 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got) 50 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \ 51 "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2) 52 53 static const WCHAR testparentclassW[] = 54 {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0}; 55 56 static HWND hwndparent, hwndparentW; 57 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */ 58 static BOOL blockEdit; 59 /* return nonzero on NM_HOVER */ 60 static BOOL g_block_hover; 61 /* notification data for LVN_ITEMCHANGED */ 62 static NMLISTVIEW g_nmlistview; 63 /* notification data for LVN_ITEMCHANGING */ 64 static NMLISTVIEW g_nmlistview_changing; 65 /* format reported to control: 66 -1 falls to defproc, anything else returned */ 67 static INT notifyFormat; 68 /* indicates we're running < 5.80 version */ 69 static BOOL g_is_below_5; 70 /* item data passed to LVN_GETDISPINFOA */ 71 static LVITEMA g_itema; 72 /* alter notification code A->W */ 73 static BOOL g_disp_A_to_W; 74 /* dispinfo data sent with LVN_LVN_ENDLABELEDIT */ 75 static NMLVDISPINFOA g_editbox_disp_info; 76 /* when this is set focus will be tested on LVN_DELETEITEM */ 77 static BOOL g_focus_test_LVN_DELETEITEM; 78 79 static HWND subclass_editbox(HWND hwndListview); 80 81 static void init_functions(void) 82 { 83 HMODULE hComCtl32 = LoadLibraryA("comctl32.dll"); 84 85 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f); 86 X(ImageList_Create); 87 X(ImageList_Destroy); 88 X(ImageList_Add); 89 X(_TrackMouseEvent); 90 #undef X 91 } 92 93 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES]; 94 95 static const struct message create_ownerdrawfixed_parent_seq[] = { 96 { WM_NOTIFYFORMAT, sent }, 97 { WM_QUERYUISTATE, sent|optional }, /* Win2K and higher */ 98 { WM_MEASUREITEM, sent }, 99 { WM_PARENTNOTIFY, sent }, 100 { 0 } 101 }; 102 103 static const struct message redraw_listview_seq[] = { 104 { WM_PAINT, sent|id, 0, 0, LISTVIEW_ID }, 105 { WM_PAINT, sent|id, 0, 0, HEADER_ID }, 106 { WM_NCPAINT, sent|id|defwinproc, 0, 0, HEADER_ID }, 107 { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, HEADER_ID }, 108 { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID }, 109 { WM_NCPAINT, sent|id|defwinproc, 0, 0, LISTVIEW_ID }, 110 { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, LISTVIEW_ID }, 111 { 0 } 112 }; 113 114 static const struct message listview_icon_spacing_seq[] = { 115 { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) }, 116 { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) }, 117 { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) }, 118 { 0 } 119 }; 120 121 static const struct message listview_color_seq[] = { 122 { LVM_SETBKCOLOR, sent|lparam, 0, RGB(0,0,0) }, 123 { LVM_GETBKCOLOR, sent }, 124 { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(0,0,0) }, 125 { LVM_GETTEXTCOLOR, sent }, 126 { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) }, 127 { LVM_GETTEXTBKCOLOR, sent }, 128 129 { LVM_SETBKCOLOR, sent|lparam, 0, RGB(100,50,200) }, 130 { LVM_GETBKCOLOR, sent }, 131 { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(100,50,200) }, 132 { LVM_GETTEXTCOLOR, sent }, 133 { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) }, 134 { LVM_GETTEXTBKCOLOR, sent }, 135 136 { LVM_SETBKCOLOR, sent|lparam, 0, CLR_NONE }, 137 { LVM_GETBKCOLOR, sent }, 138 { LVM_SETTEXTCOLOR, sent|lparam, 0, CLR_NONE }, 139 { LVM_GETTEXTCOLOR, sent }, 140 { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE }, 141 { LVM_GETTEXTBKCOLOR, sent }, 142 143 { LVM_SETBKCOLOR, sent|lparam, 0, RGB(255,255,255) }, 144 { LVM_GETBKCOLOR, sent }, 145 { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(255,255,255) }, 146 { LVM_GETTEXTCOLOR, sent }, 147 { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) }, 148 { LVM_GETTEXTBKCOLOR, sent }, 149 { 0 } 150 }; 151 152 static const struct message listview_item_count_seq[] = { 153 { LVM_GETITEMCOUNT, sent }, 154 { LVM_INSERTITEMA, sent }, 155 { LVM_INSERTITEMA, sent }, 156 { LVM_INSERTITEMA, sent }, 157 { LVM_GETITEMCOUNT, sent }, 158 { LVM_DELETEITEM, sent|wparam, 2 }, 159 { WM_NCPAINT, sent|optional }, 160 { WM_ERASEBKGND, sent|optional }, 161 { LVM_GETITEMCOUNT, sent }, 162 { LVM_DELETEALLITEMS, sent }, 163 { LVM_GETITEMCOUNT, sent }, 164 { LVM_INSERTITEMA, sent }, 165 { LVM_INSERTITEMA, sent }, 166 { LVM_GETITEMCOUNT, sent }, 167 { LVM_INSERTITEMA, sent }, 168 { LVM_GETITEMCOUNT, sent }, 169 { 0 } 170 }; 171 172 static const struct message listview_itempos_seq[] = { 173 { LVM_INSERTITEMA, sent }, 174 { LVM_INSERTITEMA, sent }, 175 { LVM_INSERTITEMA, sent }, 176 { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) }, 177 { WM_NCPAINT, sent|optional }, 178 { WM_ERASEBKGND, sent|optional }, 179 { LVM_GETITEMPOSITION, sent|wparam, 1 }, 180 { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) }, 181 { LVM_GETITEMPOSITION, sent|wparam, 2 }, 182 { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) }, 183 { LVM_GETITEMPOSITION, sent|wparam, 0 }, 184 { 0 } 185 }; 186 187 static const struct message listview_ownerdata_switchto_seq[] = { 188 { WM_STYLECHANGING, sent }, 189 { WM_STYLECHANGED, sent }, 190 { 0 } 191 }; 192 193 static const struct message listview_getorderarray_seq[] = { 194 { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID }, 195 { HDM_GETORDERARRAY, sent|id|wparam, 2, 0, HEADER_ID }, 196 { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 0, 0, LISTVIEW_ID }, 197 { HDM_GETORDERARRAY, sent|id|wparam, 0, 0, HEADER_ID }, 198 { 0 } 199 }; 200 201 static const struct message listview_setorderarray_seq[] = { 202 { LVM_SETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID }, 203 { HDM_SETORDERARRAY, sent|id|wparam, 2, 0, HEADER_ID }, 204 { LVM_SETCOLUMNORDERARRAY, sent|id|wparam, 0, 0, LISTVIEW_ID }, 205 { HDM_SETORDERARRAY, sent|id|wparam, 0, 0, HEADER_ID }, 206 { 0 } 207 }; 208 209 static const struct message empty_seq[] = { 210 { 0 } 211 }; 212 213 static const struct message parent_focus_change_ownerdata_seq[] = { 214 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 215 { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA }, 216 { 0 } 217 }; 218 219 static const struct message forward_erasebkgnd_parent_seq[] = { 220 { WM_ERASEBKGND, sent }, 221 { 0 } 222 }; 223 224 static const struct message ownerdata_select_focus_parent_seq[] = { 225 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 226 { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA }, 227 { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, /* version 4.7x */ 228 { 0 } 229 }; 230 231 static const struct message ownerdata_setstate_all_parent_seq[] = { 232 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 233 { 0 } 234 }; 235 236 static const struct message ownerdata_defocus_all_parent_seq[] = { 237 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 238 { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA }, 239 { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, 240 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 241 { 0 } 242 }; 243 244 static const struct message ownerdata_deselect_all_parent_seq[] = { 245 { WM_NOTIFY, sent|id, 0, 0, LVN_ODCACHEHINT }, 246 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 247 { 0 } 248 }; 249 250 static const struct message change_all_parent_seq[] = { 251 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 252 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 253 254 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 255 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 256 257 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 258 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 259 260 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 261 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 262 263 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 264 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 265 { 0 } 266 }; 267 268 static const struct message changing_all_parent_seq[] = { 269 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 270 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 271 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 272 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 273 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 274 { 0 } 275 }; 276 277 static const struct message textcallback_set_again_parent_seq[] = { 278 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 279 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 280 { 0 } 281 }; 282 283 static const struct message single_getdispinfo_parent_seq[] = { 284 { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA }, 285 { 0 } 286 }; 287 288 static const struct message getitemposition_seq1[] = { 289 { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID }, 290 { 0 } 291 }; 292 293 static const struct message getitemposition_seq2[] = { 294 { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID }, 295 { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, 296 { 0 } 297 }; 298 299 static const struct message getsubitemrect_seq[] = { 300 { LVM_GETSUBITEMRECT, sent|id|wparam, -1, 0, LISTVIEW_ID }, 301 { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, 302 { LVM_GETSUBITEMRECT, sent|id|wparam, 0, 0, LISTVIEW_ID }, 303 { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, 304 { LVM_GETSUBITEMRECT, sent|id|wparam, -10, 0, LISTVIEW_ID }, 305 { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, 306 { LVM_GETSUBITEMRECT, sent|id|wparam, 20, 0, LISTVIEW_ID }, 307 { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID }, 308 { 0 } 309 }; 310 311 static const struct message editbox_create_pos[] = { 312 /* sequence sent after LVN_BEGINLABELEDIT */ 313 /* next two are 4.7x specific */ 314 { WM_WINDOWPOSCHANGING, sent }, 315 { WM_WINDOWPOSCHANGED, sent|optional }, 316 317 { WM_WINDOWPOSCHANGING, sent|optional }, 318 { WM_NCCALCSIZE, sent }, 319 { WM_WINDOWPOSCHANGED, sent }, 320 { WM_MOVE, sent|defwinproc }, 321 { WM_SIZE, sent|defwinproc }, 322 /* the rest is todo, skipped in 4.7x */ 323 { WM_WINDOWPOSCHANGING, sent|optional }, 324 { WM_WINDOWPOSCHANGED, sent|optional }, 325 { 0 } 326 }; 327 328 static const struct message scroll_parent_seq[] = { 329 { WM_NOTIFY, sent|id, 0, 0, LVN_BEGINSCROLL }, 330 { WM_NOTIFY, sent|id, 0, 0, LVN_ENDSCROLL }, 331 { 0 } 332 }; 333 334 static const struct message setredraw_seq[] = { 335 { WM_SETREDRAW, sent|id|wparam, FALSE, 0, LISTVIEW_ID }, 336 { 0 } 337 }; 338 339 static const struct message lvs_ex_transparentbkgnd_seq[] = { 340 { WM_PRINTCLIENT, sent|lparam, 0, PRF_ERASEBKGND }, 341 { 0 } 342 }; 343 344 static const struct message edit_end_nochange[] = { 345 { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA }, 346 { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW }, /* todo */ 347 { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS }, 348 { 0 } 349 }; 350 351 static const struct message hover_parent[] = { 352 { WM_GETDLGCODE, sent }, /* todo_wine */ 353 { WM_NOTIFY, sent|id, 0, 0, NM_HOVER }, 354 { 0 } 355 }; 356 357 static const struct message listview_destroy[] = { 358 { 0x0090, sent|optional }, /* Vista */ 359 { WM_PARENTNOTIFY, sent }, 360 { WM_SHOWWINDOW, sent }, 361 { WM_WINDOWPOSCHANGING, sent }, 362 { WM_WINDOWPOSCHANGED, sent|optional }, 363 { WM_DESTROY, sent }, 364 { WM_NOTIFY, sent|id, 0, 0, LVN_DELETEALLITEMS }, 365 { WM_NCDESTROY, sent }, 366 { 0 } 367 }; 368 369 static const struct message listview_ownerdata_destroy[] = { 370 { 0x0090, sent|optional }, /* Vista */ 371 { WM_PARENTNOTIFY, sent }, 372 { WM_SHOWWINDOW, sent }, 373 { WM_WINDOWPOSCHANGING, sent }, 374 { WM_WINDOWPOSCHANGED, sent|optional }, 375 { WM_DESTROY, sent }, 376 { WM_NCDESTROY, sent }, 377 { 0 } 378 }; 379 380 static const struct message listview_ownerdata_deleteall[] = { 381 { LVM_DELETEALLITEMS, sent }, 382 { WM_NOTIFY, sent|id, 0, 0, LVN_DELETEALLITEMS }, 383 { 0 } 384 }; 385 386 static const struct message listview_header_changed_seq[] = { 387 { LVM_SETCOLUMNA, sent }, 388 { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID }, 389 { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID }, 390 { 0 } 391 }; 392 393 static const struct message parent_header_click_seq[] = { 394 { WM_NOTIFY, sent|id, 0, 0, LVN_COLUMNCLICK }, 395 { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCLICKA }, 396 { 0 } 397 }; 398 399 static const struct message parent_header_divider_dclick_seq[] = { 400 { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCHANGINGA }, 401 { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW }, 402 { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW }, 403 { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCHANGEDA }, 404 { WM_NOTIFY, sent|id, 0, 0, HDN_DIVIDERDBLCLICKA }, 405 { 0 } 406 }; 407 408 static const struct message listview_set_imagelist[] = { 409 { LVM_SETIMAGELIST, sent|id, 0, 0, LISTVIEW_ID }, 410 { 0 } 411 }; 412 413 static const struct message listview_header_set_imagelist[] = { 414 { LVM_SETIMAGELIST, sent|id, 0, 0, LISTVIEW_ID }, 415 { HDM_SETIMAGELIST, sent|id, 0, 0, HEADER_ID }, 416 { 0 } 417 }; 418 419 static const struct message parent_insert_focused_seq[] = { 420 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 421 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING }, 422 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 423 { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED }, 424 { WM_NOTIFY, sent|id, 0, 0, LVN_INSERTITEM }, 425 { 0 } 426 }; 427 428 static const struct message parent_report_cd_seq[] = { 429 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, 430 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT }, 431 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT|CDDS_SUBITEM }, 432 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT|CDDS_SUBITEM }, 433 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT|CDDS_SUBITEM }, 434 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT|CDDS_SUBITEM }, 435 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT }, 436 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT }, 437 { 0 } 438 }; 439 440 static const struct message parent_list_cd_seq[] = { 441 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT }, 442 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT }, 443 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT }, 444 { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT }, 445 { 0 } 446 }; 447 448 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 449 { 450 static LONG defwndproc_counter = 0; 451 LRESULT ret; 452 struct message msg; 453 454 msg.message = message; 455 msg.flags = sent|wparam|lparam; 456 if (defwndproc_counter) msg.flags |= defwinproc; 457 msg.wParam = wParam; 458 msg.lParam = lParam; 459 if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code; 460 461 /* log system messages, except for painting */ 462 if (message < WM_USER && 463 message != WM_PAINT && 464 message != WM_ERASEBKGND && 465 message != WM_NCPAINT && 466 message != WM_NCHITTEST && 467 message != WM_GETTEXT && 468 message != WM_GETICON && 469 message != WM_DEVICECHANGE) 470 { 471 add_message(sequences, PARENT_SEQ_INDEX, &msg); 472 add_message(sequences, COMBINED_SEQ_INDEX, &msg); 473 } 474 add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg); 475 476 switch (message) 477 { 478 case WM_NOTIFY: 479 { 480 switch (((NMHDR*)lParam)->code) 481 { 482 case LVN_BEGINLABELEDITA: 483 { 484 HWND edit = NULL; 485 486 /* subclass edit box */ 487 if (!blockEdit) 488 edit = subclass_editbox(((NMHDR*)lParam)->hwndFrom); 489 490 if (edit) 491 { 492 INT len = SendMessageA(edit, EM_GETLIMITTEXT, 0, 0); 493 ok(len == 259 || broken(len == 260) /* includes NULL in NT4 */, 494 "text limit %d, expected 259\n", len); 495 } 496 497 return blockEdit; 498 } 499 case LVN_ENDLABELEDITA: 500 { 501 HWND edit; 502 503 /* always accept new item text */ 504 NMLVDISPINFOA *di = (NMLVDISPINFOA*)lParam; 505 g_editbox_disp_info = *di; 506 trace("LVN_ENDLABELEDIT: text=%s\n", di->item.pszText ? di->item.pszText : "(null)"); 507 508 /* edit control still available from this notification */ 509 edit = (HWND)SendMessageA(((NMHDR*)lParam)->hwndFrom, LVM_GETEDITCONTROL, 0, 0); 510 ok(IsWindow(edit), "expected valid edit control handle\n"); 511 ok((GetWindowLongA(edit, GWL_STYLE) & ES_MULTILINE) == 0, "edit is multiline\n"); 512 513 return TRUE; 514 } 515 case LVN_BEGINSCROLL: 516 case LVN_ENDSCROLL: 517 { 518 NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam; 519 520 trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code == LVN_BEGINSCROLL ? 521 "BEGIN" : "END", pScroll->dx, pScroll->dy); 522 } 523 break; 524 case LVN_ITEMCHANGING: 525 { 526 NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam; 527 g_nmlistview_changing = *nmlv; 528 } 529 break; 530 case LVN_ITEMCHANGED: 531 { 532 NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam; 533 g_nmlistview = *nmlv; 534 } 535 break; 536 case LVN_GETDISPINFOA: 537 { 538 NMLVDISPINFOA *dispinfo = (NMLVDISPINFOA*)lParam; 539 g_itema = dispinfo->item; 540 541 if (g_disp_A_to_W && (dispinfo->item.mask & LVIF_TEXT)) 542 { 543 static const WCHAR testW[] = {'T','E','S','T',0}; 544 dispinfo->hdr.code = LVN_GETDISPINFOW; 545 memcpy(dispinfo->item.pszText, testW, sizeof(testW)); 546 } 547 548 /* test control buffer size for text, 10 used to mask cases when control 549 is using caller buffer to process LVM_GETITEM for example */ 550 if (dispinfo->item.mask & LVIF_TEXT && dispinfo->item.cchTextMax > 10) 551 ok(dispinfo->item.cchTextMax == 260 || 552 broken(dispinfo->item.cchTextMax == 264) /* NT4 reports aligned size */, 553 "buffer size %d\n", dispinfo->item.cchTextMax); 554 } 555 break; 556 case LVN_DELETEITEM: 557 if (g_focus_test_LVN_DELETEITEM) 558 { 559 NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam; 560 UINT state; 561 562 state = SendMessageA(((NMHDR*)lParam)->hwndFrom, LVM_GETITEMSTATE, nmlv->iItem, LVIS_FOCUSED); 563 ok(state == 0, "got state %x\n", state); 564 } 565 break; 566 case NM_HOVER: 567 if (g_block_hover) return 1; 568 break; 569 } 570 break; 571 } 572 case WM_NOTIFYFORMAT: 573 { 574 /* force to return format */ 575 if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat; 576 break; 577 } 578 } 579 580 defwndproc_counter++; 581 if (IsWindowUnicode(hwnd)) 582 ret = DefWindowProcW(hwnd, message, wParam, lParam); 583 else 584 ret = DefWindowProcA(hwnd, message, wParam, lParam); 585 defwndproc_counter--; 586 587 return ret; 588 } 589 590 static BOOL register_parent_wnd_class(BOOL Unicode) 591 { 592 WNDCLASSA clsA; 593 WNDCLASSW clsW; 594 595 if (Unicode) 596 { 597 clsW.style = 0; 598 clsW.lpfnWndProc = parent_wnd_proc; 599 clsW.cbClsExtra = 0; 600 clsW.cbWndExtra = 0; 601 clsW.hInstance = GetModuleHandleW(NULL); 602 clsW.hIcon = 0; 603 clsW.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 604 clsW.hbrBackground = GetStockObject(WHITE_BRUSH); 605 clsW.lpszMenuName = NULL; 606 clsW.lpszClassName = testparentclassW; 607 } 608 else 609 { 610 clsA.style = 0; 611 clsA.lpfnWndProc = parent_wnd_proc; 612 clsA.cbClsExtra = 0; 613 clsA.cbWndExtra = 0; 614 clsA.hInstance = GetModuleHandleA(NULL); 615 clsA.hIcon = 0; 616 clsA.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 617 clsA.hbrBackground = GetStockObject(WHITE_BRUSH); 618 clsA.lpszMenuName = NULL; 619 clsA.lpszClassName = "Listview test parent class"; 620 } 621 622 return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA); 623 } 624 625 static HWND create_parent_window(BOOL Unicode) 626 { 627 static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W',0}; 628 HWND hwnd; 629 630 if (!register_parent_wnd_class(Unicode)) 631 return NULL; 632 633 blockEdit = FALSE; 634 notifyFormat = -1; 635 636 if (Unicode) 637 hwnd = CreateWindowExW(0, testparentclassW, nameW, 638 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 639 WS_MAXIMIZEBOX | WS_VISIBLE, 640 0, 0, 100, 100, 641 GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL); 642 else 643 hwnd = CreateWindowExA(0, "Listview test parent class", 644 "Listview test parent window", 645 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 646 WS_MAXIMIZEBOX | WS_VISIBLE, 647 0, 0, 100, 100, 648 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL); 649 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); 650 return hwnd; 651 } 652 653 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 654 { 655 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 656 static LONG defwndproc_counter = 0; 657 LRESULT ret; 658 struct message msg; 659 660 msg.message = message; 661 msg.flags = sent|wparam|lparam; 662 if (defwndproc_counter) msg.flags |= defwinproc; 663 msg.wParam = wParam; 664 msg.lParam = lParam; 665 msg.id = LISTVIEW_ID; 666 add_message(sequences, LISTVIEW_SEQ_INDEX, &msg); 667 add_message(sequences, COMBINED_SEQ_INDEX, &msg); 668 669 defwndproc_counter++; 670 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam); 671 defwndproc_counter--; 672 return ret; 673 } 674 675 static HWND create_listview_control(DWORD style) 676 { 677 WNDPROC oldproc; 678 HWND hwnd; 679 RECT rect; 680 681 GetClientRect(hwndparent, &rect); 682 hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", 683 WS_CHILD | WS_BORDER | WS_VISIBLE | style, 684 0, 0, rect.right, rect.bottom, 685 hwndparent, NULL, GetModuleHandleA(NULL), NULL); 686 ok(hwnd != NULL, "gle=%d\n", GetLastError()); 687 688 if (!hwnd) return NULL; 689 690 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, 691 (LONG_PTR)listview_subclass_proc); 692 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc); 693 694 return hwnd; 695 } 696 697 /* unicode listview window with specified parent */ 698 static HWND create_listview_controlW(DWORD style, HWND parent) 699 { 700 WNDPROC oldproc; 701 HWND hwnd; 702 RECT rect; 703 static const WCHAR nameW[] = {'f','o','o',0}; 704 705 GetClientRect(parent, &rect); 706 hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW, 707 WS_CHILD | WS_BORDER | WS_VISIBLE | style, 708 0, 0, rect.right, rect.bottom, 709 parent, NULL, GetModuleHandleW(NULL), NULL); 710 ok(hwnd != NULL, "gle=%d\n", GetLastError()); 711 712 if (!hwnd) return NULL; 713 714 oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC, 715 (LONG_PTR)listview_subclass_proc); 716 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc); 717 718 return hwnd; 719 } 720 721 static BOOL is_win_xp(void) 722 { 723 HWND hwnd, header; 724 BOOL ret; 725 726 hwnd = create_listview_control(LVS_ICON); 727 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, LVS_EX_HEADERINALLVIEWS); 728 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 729 ret = !IsWindow(header); 730 731 DestroyWindow(hwnd); 732 733 return ret; 734 } 735 736 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 737 { 738 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 739 static LONG defwndproc_counter = 0; 740 struct message msg = { 0 }; 741 LRESULT ret; 742 743 msg.message = message; 744 msg.flags = sent|wparam|lparam; 745 if (defwndproc_counter) msg.flags |= defwinproc; 746 msg.wParam = wParam; 747 msg.lParam = lParam; 748 msg.id = HEADER_ID; 749 add_message(sequences, LISTVIEW_SEQ_INDEX, &msg); 750 751 defwndproc_counter++; 752 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam); 753 defwndproc_counter--; 754 return ret; 755 } 756 757 static HWND subclass_header(HWND hwndListview) 758 { 759 WNDPROC oldproc; 760 HWND hwnd; 761 762 hwnd = (HWND)SendMessageA(hwndListview, LVM_GETHEADER, 0, 0); 763 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, 764 (LONG_PTR)header_subclass_proc); 765 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc); 766 767 return hwnd; 768 } 769 770 static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 771 { 772 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 773 static LONG defwndproc_counter = 0; 774 struct message msg = { 0 }; 775 LRESULT ret; 776 777 msg.message = message; 778 msg.flags = sent|wparam|lparam; 779 if (defwndproc_counter) msg.flags |= defwinproc; 780 msg.wParam = wParam; 781 msg.lParam = lParam; 782 783 /* all we need is sizing */ 784 if (message == WM_WINDOWPOSCHANGING || 785 message == WM_NCCALCSIZE || 786 message == WM_WINDOWPOSCHANGED || 787 message == WM_MOVE || 788 message == WM_SIZE) 789 { 790 add_message(sequences, EDITBOX_SEQ_INDEX, &msg); 791 } 792 793 defwndproc_counter++; 794 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam); 795 defwndproc_counter--; 796 return ret; 797 } 798 799 static HWND subclass_editbox(HWND hwndListview) 800 { 801 WNDPROC oldproc; 802 HWND hwnd; 803 804 hwnd = (HWND)SendMessageA(hwndListview, LVM_GETEDITCONTROL, 0, 0); 805 oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, 806 (LONG_PTR)editbox_subclass_proc); 807 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc); 808 809 return hwnd; 810 } 811 812 /* Performs a single LVM_HITTEST test */ 813 static void test_lvm_hittest_(HWND hwnd, INT x, INT y, INT item, UINT flags, UINT broken_flags, 814 BOOL todo_item, BOOL todo_flags, int line) 815 { 816 LVHITTESTINFO lpht; 817 INT ret; 818 819 lpht.pt.x = x; 820 lpht.pt.y = y; 821 lpht.iSubItem = 10; 822 823 ret = SendMessageA(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht); 824 825 todo_wine_if(todo_item) 826 { 827 ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret); 828 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem); 829 ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n"); 830 } 831 832 if (todo_flags) 833 { 834 todo_wine 835 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags); 836 } 837 else if (broken_flags) 838 ok_(__FILE__, line)(lpht.flags == flags || broken(lpht.flags == broken_flags), 839 "Expected flags %x, got %x\n", flags, lpht.flags); 840 else 841 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags); 842 } 843 844 #define test_lvm_hittest(a,b,c,d,e,f,g,h) test_lvm_hittest_(a,b,c,d,e,f,g,h,__LINE__) 845 846 /* Performs a single LVM_SUBITEMHITTEST test */ 847 static void test_lvm_subitemhittest_(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags, 848 BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line) 849 { 850 LVHITTESTINFO lpht; 851 INT ret; 852 853 lpht.pt.x = x; 854 lpht.pt.y = y; 855 856 ret = SendMessageA(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht); 857 858 todo_wine_if(todo_item) 859 { 860 ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret); 861 ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem); 862 } 863 864 todo_wine_if(todo_subitem) 865 ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem); 866 867 todo_wine_if(todo_flags) 868 ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags); 869 } 870 871 #define test_lvm_subitemhittest(a,b,c,d,e,f,g,h,i) test_lvm_subitemhittest_(a,b,c,d,e,f,g,h,i,__LINE__) 872 873 static void test_images(void) 874 { 875 HWND hwnd; 876 INT r; 877 LVITEMA item; 878 HIMAGELIST himl; 879 HBITMAP hbmp; 880 RECT r1, r2; 881 static CHAR hello[] = "hello"; 882 883 himl = pImageList_Create(40, 40, 0, 4, 4); 884 ok(himl != NULL, "failed to create imagelist\n"); 885 886 hbmp = CreateBitmap(40, 40, 1, 1, NULL); 887 ok(hbmp != NULL, "failed to create bitmap\n"); 888 889 r = pImageList_Add(himl, hbmp, 0); 890 ok(r == 0, "should be zero\n"); 891 892 hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_OWNERDRAWFIXED, 893 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); 894 ok(hwnd != NULL, "failed to create listview window\n"); 895 896 r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, 897 LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE); 898 899 ok(r == 0, "should return zero\n"); 900 901 r = SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl); 902 ok(r == 0, "should return zero\n"); 903 904 r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50)); 905 ok(r != 0, "got 0\n"); 906 907 /* returns dimensions */ 908 909 r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 910 ok(r == 0, "should be zero items\n"); 911 912 item.mask = LVIF_IMAGE | LVIF_TEXT; 913 item.iItem = 0; 914 item.iSubItem = 1; 915 item.iImage = 0; 916 item.pszText = 0; 917 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 918 ok(r == -1, "should fail\n"); 919 920 item.iSubItem = 0; 921 item.pszText = hello; 922 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 923 ok(r == 0, "should not fail\n"); 924 925 SetRect(&r1, LVIR_ICON, 0, 0, 0); 926 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1); 927 expect(1, r); 928 929 r = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0); 930 ok(r == TRUE, "should not fail\n"); 931 932 item.iSubItem = 0; 933 item.pszText = hello; 934 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 935 ok(r == 0, "should not fail\n"); 936 937 SetRect(&r2, LVIR_ICON, 0, 0, 0); 938 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2); 939 expect(1, r); 940 941 ok(EqualRect(&r1, &r2), "rectangle should be the same\n"); 942 943 DestroyWindow(hwnd); 944 } 945 946 static void test_checkboxes(void) 947 { 948 HWND hwnd; 949 LVITEMA item; 950 DWORD r; 951 static CHAR text[] = "Text", 952 text2[] = "Text2", 953 text3[] = "Text3"; 954 955 hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT, 956 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); 957 ok(hwnd != NULL, "failed to create listview window\n"); 958 959 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */ 960 item.mask = LVIF_TEXT | LVIF_STATE; 961 item.stateMask = 0xffff; 962 item.state = 0xfccc; 963 item.iItem = 0; 964 item.iSubItem = 0; 965 item.pszText = text; 966 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 967 expect(0, r); 968 969 item.iItem = 0; 970 item.mask = LVIF_STATE; 971 item.stateMask = 0xffff; 972 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 973 expect(1, r); 974 ok(item.state == 0xfccc, "state %x\n", item.state); 975 976 /* Don't set LVIF_STATE */ 977 item.mask = LVIF_TEXT; 978 item.stateMask = 0xffff; 979 item.state = 0xfccc; 980 item.iItem = 1; 981 item.iSubItem = 0; 982 item.pszText = text; 983 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 984 expect(1, r); 985 986 item.iItem = 1; 987 item.mask = LVIF_STATE; 988 item.stateMask = 0xffff; 989 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 990 expect(1, r); 991 ok(item.state == 0, "state %x\n", item.state); 992 993 r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); 994 expect(0, r); 995 996 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */ 997 item.iItem = 0; 998 item.mask = LVIF_STATE; 999 item.stateMask = 0xffff; 1000 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1001 expect(1, r); 1002 if (item.state != 0x1ccc) 1003 { 1004 win_skip("LVS_EX_CHECKBOXES style is unavailable. Skipping.\n"); 1005 DestroyWindow(hwnd); 1006 return; 1007 } 1008 1009 /* Now add an item without specifying a state and check that its state goes to 0x1000 */ 1010 item.iItem = 2; 1011 item.mask = LVIF_TEXT; 1012 item.state = 0; 1013 item.pszText = text2; 1014 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 1015 expect(2, r); 1016 1017 item.iItem = 2; 1018 item.mask = LVIF_STATE; 1019 item.stateMask = 0xffff; 1020 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1021 expect(1, r); 1022 ok(item.state == 0x1000, "state %x\n", item.state); 1023 1024 /* Add a further item this time specifying a state and still its state goes to 0x1000 */ 1025 item.iItem = 3; 1026 item.mask = LVIF_TEXT | LVIF_STATE; 1027 item.stateMask = 0xffff; 1028 item.state = 0x2aaa; 1029 item.pszText = text3; 1030 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 1031 expect(3, r); 1032 1033 item.iItem = 3; 1034 item.mask = LVIF_STATE; 1035 item.stateMask = 0xffff; 1036 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1037 expect(1, r); 1038 ok(item.state == 0x1aaa, "state %x\n", item.state); 1039 1040 /* Set an item's state to checked */ 1041 item.iItem = 3; 1042 item.mask = LVIF_STATE; 1043 item.stateMask = 0xf000; 1044 item.state = 0x2000; 1045 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); 1046 expect(1, r); 1047 1048 item.iItem = 3; 1049 item.mask = LVIF_STATE; 1050 item.stateMask = 0xffff; 1051 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1052 expect(1, r); 1053 ok(item.state == 0x2aaa, "state %x\n", item.state); 1054 1055 /* Check that only the bits we asked for are returned, 1056 * and that all the others are set to zero 1057 */ 1058 item.iItem = 3; 1059 item.mask = LVIF_STATE; 1060 item.stateMask = 0xf000; 1061 item.state = 0xffff; 1062 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1063 expect(1, r); 1064 ok(item.state == 0x2000, "state %x\n", item.state); 1065 1066 /* Set the style again and check that doesn't change an item's state */ 1067 r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); 1068 ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r); 1069 1070 item.iItem = 3; 1071 item.mask = LVIF_STATE; 1072 item.stateMask = 0xffff; 1073 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1074 expect(1, r); 1075 ok(item.state == 0x2aaa, "state %x\n", item.state); 1076 1077 /* Unsetting the checkbox extended style doesn't change an item's state */ 1078 r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0); 1079 ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r); 1080 1081 item.iItem = 3; 1082 item.mask = LVIF_STATE; 1083 item.stateMask = 0xffff; 1084 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1085 expect(1, r); 1086 ok(item.state == 0x2aaa, "state %x\n", item.state); 1087 1088 /* Now setting the style again will change an item's state */ 1089 r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); 1090 expect(0, r); 1091 1092 item.iItem = 3; 1093 item.mask = LVIF_STATE; 1094 item.stateMask = 0xffff; 1095 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1096 expect(1, r); 1097 ok(item.state == 0x1aaa, "state %x\n", item.state); 1098 1099 /* Toggle checkbox tests (bug 9934) */ 1100 memset (&item, 0xcc, sizeof(item)); 1101 item.mask = LVIF_STATE; 1102 item.iItem = 3; 1103 item.iSubItem = 0; 1104 item.state = LVIS_FOCUSED; 1105 item.stateMask = LVIS_FOCUSED; 1106 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); 1107 expect(1, r); 1108 1109 item.iItem = 3; 1110 item.mask = LVIF_STATE; 1111 item.stateMask = 0xffff; 1112 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1113 expect(1, r); 1114 ok(item.state == 0x1aab, "state %x\n", item.state); 1115 1116 r = SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0); 1117 expect(0, r); 1118 r = SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0); 1119 expect(0, r); 1120 1121 item.iItem = 3; 1122 item.mask = LVIF_STATE; 1123 item.stateMask = 0xffff; 1124 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1125 expect(1, r); 1126 ok(item.state == 0x2aab, "state %x\n", item.state); 1127 1128 r = SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0); 1129 expect(0, r); 1130 r = SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0); 1131 expect(0, r); 1132 1133 item.iItem = 3; 1134 item.mask = LVIF_STATE; 1135 item.stateMask = 0xffff; 1136 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1137 expect(1, r); 1138 ok(item.state == 0x1aab, "state %x\n", item.state); 1139 1140 DestroyWindow(hwnd); 1141 } 1142 1143 static void insert_column(HWND hwnd, int idx) 1144 { 1145 LVCOLUMNA column; 1146 INT rc; 1147 1148 memset(&column, 0xcc, sizeof(column)); 1149 column.mask = LVCF_SUBITEM; 1150 column.iSubItem = idx; 1151 1152 rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, idx, (LPARAM)&column); 1153 expect(idx, rc); 1154 } 1155 1156 static void insert_item(HWND hwnd, int idx) 1157 { 1158 static CHAR text[] = "foo"; 1159 1160 LVITEMA item; 1161 INT rc; 1162 1163 memset(&item, 0xcc, sizeof (item)); 1164 item.mask = LVIF_TEXT; 1165 item.iItem = idx; 1166 item.iSubItem = 0; 1167 item.pszText = text; 1168 1169 rc = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 1170 expect(idx, rc); 1171 } 1172 1173 static void test_items(void) 1174 { 1175 const LPARAM lparamTest = 0x42; 1176 static CHAR text[] = "Text"; 1177 char buffA[5]; 1178 HWND hwnd; 1179 LVITEMA item; 1180 DWORD r; 1181 1182 hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT, 1183 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); 1184 ok(hwnd != NULL, "failed to create listview window\n"); 1185 1186 /* 1187 * Test setting/getting item params 1188 */ 1189 1190 /* Set up two columns */ 1191 insert_column(hwnd, 0); 1192 insert_column(hwnd, 1); 1193 1194 /* LVIS_SELECTED with zero stateMask */ 1195 /* set */ 1196 memset (&item, 0, sizeof (item)); 1197 item.mask = LVIF_STATE; 1198 item.state = LVIS_SELECTED; 1199 item.stateMask = 0; 1200 item.iItem = 0; 1201 item.iSubItem = 0; 1202 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 1203 expect(0, r); 1204 /* get */ 1205 memset (&item, 0xcc, sizeof (item)); 1206 item.mask = LVIF_STATE; 1207 item.stateMask = LVIS_SELECTED; 1208 item.state = 0; 1209 item.iItem = 0; 1210 item.iSubItem = 0; 1211 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1212 expect(1, r); 1213 ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n"); 1214 r = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); 1215 ok(r, "got %d\n", r); 1216 1217 /* LVIS_SELECTED with zero stateMask */ 1218 /* set */ 1219 memset (&item, 0, sizeof (item)); 1220 item.mask = LVIF_STATE; 1221 item.state = LVIS_FOCUSED; 1222 item.stateMask = 0; 1223 item.iItem = 0; 1224 item.iSubItem = 0; 1225 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 1226 expect(0, r); 1227 /* get */ 1228 memset (&item, 0xcc, sizeof (item)); 1229 item.mask = LVIF_STATE; 1230 item.stateMask = LVIS_FOCUSED; 1231 item.state = 0; 1232 item.iItem = 0; 1233 item.iSubItem = 0; 1234 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1235 expect(1, r); 1236 ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n"); 1237 r = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); 1238 ok(r, "got %d\n", r); 1239 1240 /* LVIS_CUT with LVIS_FOCUSED stateMask */ 1241 /* set */ 1242 memset (&item, 0, sizeof (item)); 1243 item.mask = LVIF_STATE; 1244 item.state = LVIS_CUT; 1245 item.stateMask = LVIS_FOCUSED; 1246 item.iItem = 0; 1247 item.iSubItem = 0; 1248 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 1249 expect(0, r); 1250 /* get */ 1251 memset (&item, 0xcc, sizeof (item)); 1252 item.mask = LVIF_STATE; 1253 item.stateMask = LVIS_CUT; 1254 item.state = 0; 1255 item.iItem = 0; 1256 item.iSubItem = 0; 1257 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1258 expect(1, r); 1259 ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n"); 1260 r = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); 1261 ok(r, "got %d\n", r); 1262 1263 /* Insert an item with just a param */ 1264 memset (&item, 0xcc, sizeof (item)); 1265 item.mask = LVIF_PARAM; 1266 item.iItem = 0; 1267 item.iSubItem = 0; 1268 item.lParam = lparamTest; 1269 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 1270 expect(0, r); 1271 1272 /* Test getting of the param */ 1273 memset (&item, 0xcc, sizeof (item)); 1274 item.mask = LVIF_PARAM; 1275 item.iItem = 0; 1276 item.iSubItem = 0; 1277 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1278 expect(1, r); 1279 ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest); 1280 1281 /* Set up a subitem */ 1282 memset (&item, 0xcc, sizeof (item)); 1283 item.mask = LVIF_TEXT; 1284 item.iItem = 0; 1285 item.iSubItem = 1; 1286 item.pszText = text; 1287 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); 1288 expect(1, r); 1289 1290 item.mask = LVIF_TEXT; 1291 item.iItem = 0; 1292 item.iSubItem = 1; 1293 item.pszText = buffA; 1294 item.cchTextMax = sizeof(buffA); 1295 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1296 expect(1, r); 1297 ok(!memcmp(item.pszText, text, sizeof(text)), "got text %s, expected %s\n", item.pszText, text); 1298 1299 /* set up with extra flag */ 1300 /* 1. reset subitem text */ 1301 item.mask = LVIF_TEXT; 1302 item.iItem = 0; 1303 item.iSubItem = 1; 1304 item.pszText = NULL; 1305 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); 1306 expect(1, r); 1307 1308 item.mask = LVIF_TEXT; 1309 item.iItem = 0; 1310 item.iSubItem = 1; 1311 item.pszText = buffA; 1312 buffA[0] = 'a'; 1313 item.cchTextMax = sizeof(buffA); 1314 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1315 expect(1, r); 1316 ok(item.pszText[0] == 0, "got %p\n", item.pszText); 1317 1318 /* 2. set new text with extra flag specified */ 1319 item.mask = LVIF_TEXT | LVIF_DI_SETITEM; 1320 item.iItem = 0; 1321 item.iSubItem = 1; 1322 item.pszText = text; 1323 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); 1324 ok(r == 1 || broken(r == 0) /* NT4 */, "ret %d\n", r); 1325 1326 if (r == 1) 1327 { 1328 item.mask = LVIF_TEXT; 1329 item.iItem = 0; 1330 item.iSubItem = 1; 1331 item.pszText = buffA; 1332 buffA[0] = 'a'; 1333 item.cchTextMax = sizeof(buffA); 1334 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1335 expect(1, r); 1336 ok(!memcmp(item.pszText, text, sizeof(text)), "got %s, expected %s\n", item.pszText, text); 1337 } 1338 1339 /* Query param from subitem: returns main item param */ 1340 memset (&item, 0xcc, sizeof (item)); 1341 item.mask = LVIF_PARAM; 1342 item.iItem = 0; 1343 item.iSubItem = 1; 1344 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1345 expect(1, r); 1346 ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest); 1347 1348 /* Set up param on first subitem: no effect */ 1349 memset (&item, 0xcc, sizeof (item)); 1350 item.mask = LVIF_PARAM; 1351 item.iItem = 0; 1352 item.iSubItem = 1; 1353 item.lParam = lparamTest+1; 1354 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); 1355 expect(0, r); 1356 1357 /* Query param from subitem again: should still return main item param */ 1358 memset (&item, 0xcc, sizeof (item)); 1359 item.mask = LVIF_PARAM; 1360 item.iItem = 0; 1361 item.iSubItem = 1; 1362 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1363 expect(1, r); 1364 ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest); 1365 1366 /**** Some tests of state highlighting ****/ 1367 memset (&item, 0xcc, sizeof (item)); 1368 item.mask = LVIF_STATE; 1369 item.iItem = 0; 1370 item.iSubItem = 0; 1371 item.state = LVIS_SELECTED; 1372 item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED; 1373 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); 1374 expect(1, r); 1375 item.iSubItem = 1; 1376 item.state = LVIS_DROPHILITED; 1377 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item); 1378 expect(1, r); 1379 1380 memset (&item, 0xcc, sizeof (item)); 1381 item.mask = LVIF_STATE; 1382 item.iItem = 0; 1383 item.iSubItem = 0; 1384 item.stateMask = -1; 1385 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1386 expect(1, r); 1387 ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED); 1388 item.iSubItem = 1; 1389 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1390 expect(1, r); 1391 todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED); 1392 1393 /* some notnull but meaningless masks */ 1394 memset (&item, 0, sizeof(item)); 1395 item.mask = LVIF_NORECOMPUTE; 1396 item.iItem = 0; 1397 item.iSubItem = 0; 1398 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1399 expect(1, r); 1400 memset (&item, 0, sizeof(item)); 1401 item.mask = LVIF_DI_SETITEM; 1402 item.iItem = 0; 1403 item.iSubItem = 0; 1404 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 1405 expect(1, r); 1406 1407 /* set text to callback value already having it */ 1408 r = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0); 1409 expect(TRUE, r); 1410 memset (&item, 0, sizeof (item)); 1411 item.mask = LVIF_TEXT; 1412 item.pszText = LPSTR_TEXTCALLBACKA; 1413 item.iItem = 0; 1414 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 1415 expect(0, r); 1416 memset (&item, 0, sizeof (item)); 1417 1418 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1419 1420 item.pszText = LPSTR_TEXTCALLBACKA; 1421 r = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0 , (LPARAM) &item); 1422 expect(TRUE, r); 1423 1424 ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq, 1425 "check callback text comparison rule", FALSE); 1426 1427 DestroyWindow(hwnd); 1428 } 1429 1430 static void test_columns(void) 1431 { 1432 HWND hwnd, header; 1433 LVCOLUMNA column; 1434 LVITEMA item; 1435 INT order[2]; 1436 CHAR buff[5]; 1437 DWORD rc; 1438 1439 hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_LIST, 1440 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); 1441 ok(hwnd != NULL, "failed to create listview window\n"); 1442 1443 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 1444 ok(header == NULL, "got %p\n", header); 1445 1446 rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order); 1447 ok(rc == 0, "got %d\n", rc); 1448 1449 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 1450 ok(header == NULL, "got %p\n", header); 1451 1452 DestroyWindow(hwnd); 1453 1454 hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT, 1455 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); 1456 ok(hwnd != NULL, "failed to create listview window\n"); 1457 1458 rc = SendMessageA(hwnd, LVM_DELETECOLUMN, -1, 0); 1459 ok(!rc, "got %d\n", rc); 1460 1461 rc = SendMessageA(hwnd, LVM_DELETECOLUMN, 0, 0); 1462 ok(!rc, "got %d\n", rc); 1463 1464 /* Add a column with no mask */ 1465 memset(&column, 0xcc, sizeof(column)); 1466 column.mask = 0; 1467 rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&column); 1468 ok(rc == 0, "Inserting column with no mask failed with %d\n", rc); 1469 1470 /* Check its width */ 1471 rc = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); 1472 ok(rc == 10, "Inserting column with no mask failed to set width to 10 with %d\n", rc); 1473 1474 DestroyWindow(hwnd); 1475 1476 /* LVM_GETCOLUMNORDERARRAY */ 1477 hwnd = create_listview_control(LVS_REPORT); 1478 subclass_header(hwnd); 1479 1480 memset(&column, 0, sizeof(column)); 1481 column.mask = LVCF_WIDTH; 1482 column.cx = 100; 1483 rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&column); 1484 expect(0, rc); 1485 1486 column.cx = 200; 1487 rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&column); 1488 expect(1, rc); 1489 1490 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1491 1492 rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order); 1493 expect(1, rc); 1494 ok(order[0] == 0, "Expected order 0, got %d\n", order[0]); 1495 ok(order[1] == 1, "Expected order 1, got %d\n", order[1]); 1496 1497 rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 0, 0); 1498 expect(0, rc); 1499 1500 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE); 1501 1502 /* LVM_SETCOLUMNORDERARRAY */ 1503 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1504 1505 order[0] = 0; 1506 order[1] = 1; 1507 rc = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order); 1508 expect(1, rc); 1509 1510 rc = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 0, 0); 1511 expect(0, rc); 1512 1513 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_setorderarray_seq, "set order array", FALSE); 1514 1515 /* after column added subitem is considered as present */ 1516 insert_item(hwnd, 0); 1517 1518 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1519 1520 item.pszText = buff; 1521 item.cchTextMax = sizeof(buff); 1522 item.iItem = 0; 1523 item.iSubItem = 1; 1524 item.mask = LVIF_TEXT; 1525 memset(&g_itema, 0, sizeof(g_itema)); 1526 rc = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 1527 expect(1, rc); 1528 ok(g_itema.iSubItem == 1, "got %d\n", g_itema.iSubItem); 1529 1530 ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq, 1531 "get subitem text after column added", FALSE); 1532 1533 DestroyWindow(hwnd); 1534 } 1535 1536 /* test setting imagelist between WM_NCCREATE and WM_CREATE */ 1537 static WNDPROC listviewWndProc; 1538 static HIMAGELIST test_create_imagelist; 1539 1540 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 1541 { 1542 LRESULT ret; 1543 1544 if (uMsg == WM_CREATE) 1545 { 1546 CREATESTRUCTA *lpcs = (CREATESTRUCTA*)lParam; 1547 lpcs->style |= LVS_REPORT; 1548 } 1549 ret = CallWindowProcA(listviewWndProc, hwnd, uMsg, wParam, lParam); 1550 if (uMsg == WM_CREATE) SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist); 1551 return ret; 1552 } 1553 1554 /* Header creation is delayed in classic implementation. */ 1555 #define TEST_NO_HEADER(a) test_header_presence_(a, FALSE, __LINE__) 1556 #define TEST_HEADER_EXPECTED(a) test_header_presence_(a, TRUE, __LINE__) 1557 #define TEST_NO_HEADER2(a, b) test_header_presence_(a, b, __LINE__) 1558 static void test_header_presence_(HWND hwnd, BOOL present, int line) 1559 { 1560 HWND header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 1561 1562 if (present) 1563 { 1564 ok_(__FILE__, line)(IsWindow(header), "Header should have been created.\n"); 1565 if (header) /* FIXME: remove when todo's are fixed */ 1566 ok_(__FILE__, line)(header == GetDlgItem(hwnd, 0), "Dialog item expected.\n"); 1567 } 1568 else 1569 { 1570 ok_(__FILE__, line)(!IsWindow(header), "Header shouldn't be created.\n"); 1571 ok_(__FILE__, line)(NULL == GetDlgItem(hwnd, 0), "NULL dialog item expected.\n"); 1572 } 1573 } 1574 1575 static void test_create(BOOL is_version_6) 1576 { 1577 static const WCHAR testtextW[] = {'t','e','s','t',' ','t','e','x','t',0}; 1578 char buff[16]; 1579 HWND hList; 1580 HWND hHeader; 1581 LONG_PTR ret; 1582 LONG r; 1583 LVCOLUMNA col; 1584 RECT rect; 1585 WNDCLASSEXA cls; 1586 DWORD style; 1587 ATOM class; 1588 1589 if (is_win_xp() && is_version_6) 1590 { 1591 win_skip("Skipping some tests on XP.\n"); 1592 return; 1593 } 1594 1595 cls.cbSize = sizeof(WNDCLASSEXA); 1596 r = GetClassInfoExA(GetModuleHandleA(NULL), WC_LISTVIEWA, &cls); 1597 ok(r, "Failed to get class info.\n"); 1598 listviewWndProc = cls.lpfnWndProc; 1599 cls.lpfnWndProc = create_test_wndproc; 1600 cls.lpszClassName = "MyListView32"; 1601 class = RegisterClassExA(&cls); 1602 ok(class, "Failed to register class.\n"); 1603 1604 test_create_imagelist = pImageList_Create(16, 16, 0, 5, 10); 1605 hList = CreateWindowA("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); 1606 ok((HIMAGELIST)SendMessageA(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n"); 1607 hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0); 1608 ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n"); 1609 ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n"); 1610 DestroyWindow(hList); 1611 1612 /* header isn't created on LVS_ICON and LVS_LIST styles */ 1613 hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); 1614 TEST_NO_HEADER(hList); 1615 1616 /* insert column */ 1617 memset(&col, 0, sizeof(LVCOLUMNA)); 1618 col.mask = LVCF_WIDTH; 1619 col.cx = 100; 1620 r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); 1621 expect(0, r); 1622 TEST_HEADER_EXPECTED(hList); 1623 hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0); 1624 style = GetWindowLongA(hHeader, GWL_STYLE); 1625 ok(!(style & HDS_HIDDEN), "Not expected HDS_HIDDEN\n"); 1626 DestroyWindow(hList); 1627 1628 hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL, 1629 GetModuleHandleA(NULL), 0); 1630 TEST_NO_HEADER(hList); 1631 /* insert column */ 1632 memset(&col, 0, sizeof(LVCOLUMNA)); 1633 col.mask = LVCF_WIDTH; 1634 col.cx = 100; 1635 r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); 1636 expect(0, r); 1637 TEST_HEADER_EXPECTED(hList); 1638 DestroyWindow(hList); 1639 1640 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */ 1641 hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, 1642 GetModuleHandleA(NULL), 0); 1643 ret = SetWindowLongPtrA(hList, GWL_STYLE, GetWindowLongPtrA(hList, GWL_STYLE) | LVS_REPORT); 1644 ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n"); 1645 TEST_HEADER_EXPECTED(hList); 1646 ret = SetWindowLongPtrA(hList, GWL_STYLE, GetWindowLongA(hList, GWL_STYLE) & ~LVS_REPORT); 1647 ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n"); 1648 TEST_HEADER_EXPECTED(hList); 1649 DestroyWindow(hList); 1650 1651 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */ 1652 hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL, 1653 GetModuleHandleA(NULL), 0); 1654 ret = SetWindowLongPtrA(hList, GWL_STYLE, 1655 (GetWindowLongPtrA(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT); 1656 ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n"); 1657 TEST_HEADER_EXPECTED(hList); 1658 ret = SetWindowLongPtrA(hList, GWL_STYLE, (GetWindowLongPtrA(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST); 1659 ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n"); 1660 TEST_HEADER_EXPECTED(hList); 1661 DestroyWindow(hList); 1662 1663 /* LVS_REPORT without WS_VISIBLE */ 1664 hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, 1665 GetModuleHandleA(NULL), 0); 1666 hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0); 1667 todo_wine_if(is_version_6) 1668 TEST_NO_HEADER2(hList, is_version_6); 1669 1670 /* insert column */ 1671 memset(&col, 0, sizeof(LVCOLUMNA)); 1672 col.mask = LVCF_WIDTH; 1673 col.cx = 100; 1674 r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); 1675 expect(0, r); 1676 TEST_HEADER_EXPECTED(hList); 1677 DestroyWindow(hList); 1678 1679 /* LVS_REPORT without WS_VISIBLE, try to show it */ 1680 hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, 1681 GetModuleHandleA(NULL), 0); 1682 todo_wine_if(is_version_6) 1683 TEST_NO_HEADER2(hList, is_version_6); 1684 1685 ShowWindow(hList, SW_SHOW); 1686 TEST_HEADER_EXPECTED(hList); 1687 DestroyWindow(hList); 1688 1689 /* LVS_REPORT with LVS_NOCOLUMNHEADER */ 1690 hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE, 1691 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0); 1692 TEST_HEADER_EXPECTED(hList); 1693 hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0); 1694 /* HDS_DRAGDROP set by default */ 1695 ok(GetWindowLongPtrA(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n"); 1696 DestroyWindow(hList); 1697 1698 /* setting LVS_EX_HEADERDRAGDROP creates header */ 1699 hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, 1700 GetModuleHandleA(NULL), 0); 1701 todo_wine_if(is_version_6) 1702 TEST_NO_HEADER2(hList, is_version_6); 1703 1704 SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP); 1705 TEST_HEADER_EXPECTED(hList); 1706 DestroyWindow(hList); 1707 1708 /* setting LVS_EX_GRIDLINES creates header */ 1709 hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, 1710 GetModuleHandleA(NULL), 0); 1711 todo_wine_if(is_version_6) 1712 TEST_NO_HEADER2(hList, is_version_6); 1713 1714 SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES); 1715 TEST_HEADER_EXPECTED(hList); 1716 DestroyWindow(hList); 1717 1718 /* setting LVS_EX_FULLROWSELECT creates header */ 1719 hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, 1720 GetModuleHandleA(NULL), 0); 1721 todo_wine_if(is_version_6) 1722 TEST_NO_HEADER2(hList, is_version_6); 1723 SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); 1724 TEST_HEADER_EXPECTED(hList); 1725 DestroyWindow(hList); 1726 1727 /* not report style accepts LVS_EX_HEADERDRAGDROP too */ 1728 hList = create_listview_control(LVS_ICON); 1729 SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP); 1730 r = SendMessageA(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); 1731 ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n"); 1732 DestroyWindow(hList); 1733 1734 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */ 1735 hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL, 1736 GetModuleHandleA(NULL), 0); 1737 todo_wine_if(is_version_6) 1738 TEST_NO_HEADER2(hList, is_version_6); 1739 1740 SetRect(&rect, LVIR_BOUNDS, 1, -10, -10); 1741 r = SendMessageA(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); 1742 ok(r == 1, "Unexpected ret value %d.\n", r); 1743 /* right value contains garbage, probably because header columns are not set up */ 1744 ok(rect.bottom >= 0, "Unexpected rectangle.\n"); 1745 1746 todo_wine_if(is_version_6) 1747 TEST_NO_HEADER2(hList, is_version_6); 1748 DestroyWindow(hList); 1749 1750 /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */ 1751 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1752 hList = create_listview_control(LVS_OWNERDRAWFIXED | LVS_REPORT); 1753 ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq, 1754 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE); 1755 DestroyWindow(hList); 1756 1757 /* Test that window text is preserved. */ 1758 hList = CreateWindowExA(0, WC_LISTVIEWA, "test text", WS_CHILD | WS_BORDER | WS_VISIBLE, 1759 0, 0, 100, 100, hwndparent, NULL, GetModuleHandleA(NULL), NULL); 1760 ok(hList != NULL, "Failed to create ListView window.\n"); 1761 *buff = 0; 1762 GetWindowTextA(hList, buff, sizeof(buff)); 1763 ok(!strcmp(buff, "test text"), "Unexpected window text %s.\n", buff); 1764 DestroyWindow(hList); 1765 1766 hList = CreateWindowExW(0, WC_LISTVIEWW, testtextW, WS_CHILD | WS_BORDER | WS_VISIBLE, 1767 0, 0, 100, 100, hwndparent, NULL, GetModuleHandleA(NULL), NULL); 1768 ok(hList != NULL, "Failed to create ListView window.\n"); 1769 *buff = 0; 1770 GetWindowTextA(hList, buff, sizeof(buff)); 1771 ok(!strcmp(buff, "test text"), "Unexpected window text %s.\n", buff); 1772 DestroyWindow(hList); 1773 1774 r = UnregisterClassA("MyListView32", NULL); 1775 ok(r, "Failed to unregister test class.\n"); 1776 } 1777 1778 static void test_redraw(void) 1779 { 1780 HWND hwnd; 1781 HDC hdc; 1782 BOOL res; 1783 DWORD r; 1784 1785 hwnd = create_listview_control(LVS_REPORT); 1786 subclass_header(hwnd); 1787 1788 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1789 1790 InvalidateRect(hwnd, NULL, TRUE); 1791 UpdateWindow(hwnd); 1792 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE); 1793 1794 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1795 1796 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */ 1797 /* 1. Without backbuffer */ 1798 res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE); 1799 expect(TRUE, res); 1800 1801 hdc = GetWindowDC(hwndparent); 1802 1803 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1804 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); 1805 ok(r == 1, "Expected not zero result\n"); 1806 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq, 1807 "forward WM_ERASEBKGND on CLR_NONE", FALSE); 1808 1809 res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_DEFAULT); 1810 expect(TRUE, res); 1811 1812 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1813 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); 1814 expect(1, r); 1815 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq, 1816 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE); 1817 1818 /* 2. With backbuffer */ 1819 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER, 1820 LVS_EX_DOUBLEBUFFER); 1821 res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE); 1822 expect(TRUE, res); 1823 1824 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1825 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); 1826 expect(1, r); 1827 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq, 1828 "forward WM_ERASEBKGND on CLR_NONE", FALSE); 1829 1830 res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_DEFAULT); 1831 expect(TRUE, res); 1832 1833 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1834 r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); 1835 todo_wine expect(1, r); 1836 ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq, 1837 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE); 1838 1839 ReleaseDC(hwndparent, hdc); 1840 1841 DestroyWindow(hwnd); 1842 } 1843 1844 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 1845 { 1846 COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee); 1847 1848 if(message == WM_NOTIFY) { 1849 NMHDR *nmhdr = (NMHDR*)lParam; 1850 if(nmhdr->code == NM_CUSTOMDRAW) { 1851 NMLVCUSTOMDRAW *nmlvcd = (NMLVCUSTOMDRAW*)nmhdr; 1852 struct message msg; 1853 1854 msg.message = message; 1855 msg.flags = sent|wparam|lparam|custdraw; 1856 msg.wParam = wParam; 1857 msg.lParam = lParam; 1858 msg.id = nmhdr->code; 1859 msg.stage = nmlvcd->nmcd.dwDrawStage; 1860 add_message(sequences, PARENT_CD_SEQ_INDEX, &msg); 1861 1862 switch(nmlvcd->nmcd.dwDrawStage) { 1863 case CDDS_PREPAINT: 1864 SetBkColor(nmlvcd->nmcd.hdc, c0ffee); 1865 return CDRF_NOTIFYITEMDRAW|CDRF_NOTIFYPOSTPAINT; 1866 case CDDS_ITEMPREPAINT: 1867 nmlvcd->clrTextBk = CLR_DEFAULT; 1868 nmlvcd->clrText = RGB(0, 255, 0); 1869 return CDRF_NOTIFYSUBITEMDRAW|CDRF_NOTIFYPOSTPAINT; 1870 case CDDS_ITEMPREPAINT | CDDS_SUBITEM: 1871 clr = GetBkColor(nmlvcd->nmcd.hdc); 1872 ok(nmlvcd->clrTextBk == CLR_DEFAULT, "got 0x%x\n", nmlvcd->clrTextBk); 1873 ok(nmlvcd->clrText == RGB(0, 255, 0), "got 0x%x\n", nmlvcd->clrText); 1874 if (!(GetWindowLongW(nmhdr->hwndFrom, GWL_STYLE) & LVS_SHOWSELALWAYS)) 1875 { 1876 todo_wine_if(nmlvcd->iSubItem) 1877 ok(clr == c0ffee, "clr=%.8x\n", clr); 1878 } 1879 return CDRF_NOTIFYPOSTPAINT; 1880 case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM: 1881 clr = GetBkColor(nmlvcd->nmcd.hdc); 1882 if (!(GetWindowLongW(nmhdr->hwndFrom, GWL_STYLE) & LVS_SHOWSELALWAYS)) 1883 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr); 1884 ok(nmlvcd->clrTextBk == CLR_DEFAULT, "got 0x%x\n", nmlvcd->clrTextBk); 1885 ok(nmlvcd->clrText == RGB(0, 255, 0), "got 0x%x\n", nmlvcd->clrText); 1886 return CDRF_DODEFAULT; 1887 } 1888 return CDRF_DODEFAULT; 1889 } 1890 } 1891 1892 return DefWindowProcA(hwnd, message, wParam, lParam); 1893 } 1894 1895 static void test_customdraw(void) 1896 { 1897 HWND hwnd; 1898 WNDPROC oldwndproc; 1899 LVITEMA item; 1900 1901 hwnd = create_listview_control(LVS_REPORT); 1902 1903 insert_column(hwnd, 0); 1904 insert_column(hwnd, 1); 1905 insert_item(hwnd, 0); 1906 1907 oldwndproc = (WNDPROC)SetWindowLongPtrA(hwndparent, GWLP_WNDPROC, 1908 (LONG_PTR)cd_wndproc); 1909 1910 InvalidateRect(hwnd, NULL, TRUE); 1911 UpdateWindow(hwnd); 1912 1913 /* message tests */ 1914 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1915 InvalidateRect(hwnd, NULL, TRUE); 1916 UpdateWindow(hwnd); 1917 ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, LVS_REPORT", FALSE); 1918 1919 /* check colors when item is selected */ 1920 SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | LVS_SHOWSELALWAYS); 1921 item.mask = LVIF_STATE; 1922 item.stateMask = LVIS_SELECTED; 1923 item.state = LVIS_SELECTED; 1924 SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 1925 1926 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1927 InvalidateRect(hwnd, NULL, TRUE); 1928 UpdateWindow(hwnd); 1929 ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, LVS_REPORT, selection", FALSE); 1930 1931 DestroyWindow(hwnd); 1932 1933 hwnd = create_listview_control(LVS_LIST); 1934 1935 insert_column(hwnd, 0); 1936 insert_column(hwnd, 1); 1937 insert_item(hwnd, 0); 1938 1939 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1940 InvalidateRect(hwnd, NULL, TRUE); 1941 UpdateWindow(hwnd); 1942 ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_list_cd_seq, "parent customdraw, LVS_LIST", FALSE); 1943 1944 SetWindowLongPtrA(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc); 1945 DestroyWindow(hwnd); 1946 } 1947 1948 static void test_icon_spacing(void) 1949 { 1950 /* LVM_SETICONSPACING */ 1951 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */ 1952 1953 HWND hwnd; 1954 WORD w, h; 1955 INT r; 1956 1957 hwnd = create_listview_control(LVS_ICON); 1958 ok(hwnd != NULL, "failed to create a listview window\n"); 1959 1960 r = SendMessageA(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, NF_REQUERY); 1961 expect(NFR_ANSI, r); 1962 1963 /* reset the icon spacing to defaults */ 1964 SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1)); 1965 1966 /* now we can request what the defaults are */ 1967 r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1)); 1968 w = LOWORD(r); 1969 h = HIWORD(r); 1970 1971 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1972 1973 r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30)); 1974 ok(r == MAKELONG(w, h) || 1975 broken(r == MAKELONG(w, w)), /* win98 */ 1976 "Expected %d, got %d\n", MAKELONG(w, h), r); 1977 1978 r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35)); 1979 expect(MAKELONG(20,30), r); 1980 1981 r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1)); 1982 expect(MAKELONG(25,35), r); 1983 1984 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE); 1985 1986 flush_sequences(sequences, NUM_MSG_SEQUENCES); 1987 DestroyWindow(hwnd); 1988 } 1989 1990 static void test_color(void) 1991 { 1992 RECT rect; 1993 HWND hwnd; 1994 DWORD r; 1995 int i; 1996 1997 COLORREF color; 1998 COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)}; 1999 2000 hwnd = create_listview_control(LVS_REPORT); 2001 ok(hwnd != NULL, "failed to create a listview window\n"); 2002 2003 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2004 2005 for (i = 0; i < 4; i++) 2006 { 2007 color = colors[i]; 2008 2009 r = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, color); 2010 expect(TRUE, r); 2011 r = SendMessageA(hwnd, LVM_GETBKCOLOR, 0, 0); 2012 expect(color, r); 2013 2014 r = SendMessageA(hwnd, LVM_SETTEXTCOLOR, 0, color); 2015 expect (TRUE, r); 2016 r = SendMessageA(hwnd, LVM_GETTEXTCOLOR, 0, 0); 2017 expect(color, r); 2018 2019 r = SendMessageA(hwnd, LVM_SETTEXTBKCOLOR, 0, color); 2020 expect(TRUE, r); 2021 r = SendMessageA(hwnd, LVM_GETTEXTBKCOLOR, 0, 0); 2022 expect(color, r); 2023 } 2024 2025 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE); 2026 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2027 2028 /* invalidation test done separately to avoid a message chain mess */ 2029 r = ValidateRect(hwnd, NULL); 2030 expect(TRUE, r); 2031 r = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, colors[0]); 2032 expect(TRUE, r); 2033 2034 rect.right = rect.bottom = 1; 2035 r = GetUpdateRect(hwnd, &rect, TRUE); 2036 todo_wine expect(FALSE, r); 2037 ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n"); 2038 2039 r = ValidateRect(hwnd, NULL); 2040 expect(TRUE, r); 2041 r = SendMessageA(hwnd, LVM_SETTEXTCOLOR, 0, colors[0]); 2042 expect(TRUE, r); 2043 2044 rect.right = rect.bottom = 1; 2045 r = GetUpdateRect(hwnd, &rect, TRUE); 2046 todo_wine expect(FALSE, r); 2047 ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n"); 2048 2049 r = ValidateRect(hwnd, NULL); 2050 expect(TRUE, r); 2051 r = SendMessageA(hwnd, LVM_SETTEXTBKCOLOR, 0, colors[0]); 2052 expect(TRUE, r); 2053 2054 rect.right = rect.bottom = 1; 2055 r = GetUpdateRect(hwnd, &rect, TRUE); 2056 todo_wine expect(FALSE, r); 2057 ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n"); 2058 2059 DestroyWindow(hwnd); 2060 } 2061 2062 static void test_item_count(void) 2063 { 2064 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */ 2065 2066 HWND hwnd; 2067 DWORD r; 2068 HDC hdc; 2069 HFONT hOldFont; 2070 TEXTMETRICA tm; 2071 RECT rect; 2072 INT height; 2073 2074 LVITEMA item0; 2075 LVITEMA item1; 2076 LVITEMA item2; 2077 static CHAR item0text[] = "item0"; 2078 static CHAR item1text[] = "item1"; 2079 static CHAR item2text[] = "item2"; 2080 2081 hwnd = create_listview_control(LVS_REPORT); 2082 ok(hwnd != NULL, "failed to create a listview window\n"); 2083 2084 /* resize in dpiaware manner to fit all 3 items added */ 2085 hdc = GetDC(0); 2086 hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT)); 2087 GetTextMetricsA(hdc, &tm); 2088 /* 2 extra pixels for bounds and header border */ 2089 height = tm.tmHeight + 2; 2090 SelectObject(hdc, hOldFont); 2091 ReleaseDC(0, hdc); 2092 2093 GetWindowRect(hwnd, &rect); 2094 /* 3 items + 1 header + 1 to be sure */ 2095 MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE); 2096 2097 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2098 2099 r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 2100 expect(0, r); 2101 2102 /* [item0] */ 2103 item0.mask = LVIF_TEXT; 2104 item0.iItem = 0; 2105 item0.iSubItem = 0; 2106 item0.pszText = item0text; 2107 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item0); 2108 expect(0, r); 2109 2110 /* [item0, item1] */ 2111 item1.mask = LVIF_TEXT; 2112 item1.iItem = 1; 2113 item1.iSubItem = 0; 2114 item1.pszText = item1text; 2115 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1); 2116 expect(1, r); 2117 2118 /* [item0, item1, item2] */ 2119 item2.mask = LVIF_TEXT; 2120 item2.iItem = 2; 2121 item2.iSubItem = 0; 2122 item2.pszText = item2text; 2123 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item2); 2124 expect(2, r); 2125 2126 r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 2127 expect(3, r); 2128 2129 /* [item0, item1] */ 2130 r = SendMessageA(hwnd, LVM_DELETEITEM, 2, 0); 2131 expect(TRUE, r); 2132 2133 r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 2134 expect(2, r); 2135 2136 /* [] */ 2137 r = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0); 2138 expect(TRUE, r); 2139 2140 r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 2141 expect(0, r); 2142 2143 /* [item0] */ 2144 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1); 2145 expect(0, r); 2146 2147 /* [item0, item1] */ 2148 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1); 2149 expect(1, r); 2150 2151 r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 2152 expect(2, r); 2153 2154 /* [item0, item1, item2] */ 2155 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item2); 2156 expect(2, r); 2157 2158 r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 2159 expect(3, r); 2160 2161 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE); 2162 2163 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2164 DestroyWindow(hwnd); 2165 } 2166 2167 static void test_item_position(void) 2168 { 2169 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */ 2170 2171 HWND hwnd; 2172 DWORD r; 2173 POINT position; 2174 2175 LVITEMA item0; 2176 LVITEMA item1; 2177 LVITEMA item2; 2178 static CHAR item0text[] = "item0"; 2179 static CHAR item1text[] = "item1"; 2180 static CHAR item2text[] = "item2"; 2181 2182 hwnd = create_listview_control(LVS_ICON); 2183 ok(hwnd != NULL, "failed to create a listview window\n"); 2184 2185 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2186 2187 /* [item0] */ 2188 item0.mask = LVIF_TEXT; 2189 item0.iItem = 0; 2190 item0.iSubItem = 0; 2191 item0.pszText = item0text; 2192 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item0); 2193 expect(0, r); 2194 2195 /* [item0, item1] */ 2196 item1.mask = LVIF_TEXT; 2197 item1.iItem = 1; 2198 item1.iSubItem = 0; 2199 item1.pszText = item1text; 2200 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1); 2201 expect(1, r); 2202 2203 /* [item0, item1, item2] */ 2204 item2.mask = LVIF_TEXT; 2205 item2.iItem = 2; 2206 item2.iSubItem = 0; 2207 item2.pszText = item2text; 2208 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item2); 2209 expect(2, r); 2210 2211 r = SendMessageA(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5)); 2212 expect(TRUE, r); 2213 r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position); 2214 expect(TRUE, r); 2215 expect2(10, 5, position.x, position.y); 2216 2217 r = SendMessageA(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0)); 2218 expect(TRUE, r); 2219 r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position); 2220 expect(TRUE, r); 2221 expect2(0, 0, position.x, position.y); 2222 2223 r = SendMessageA(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20)); 2224 expect(TRUE, r); 2225 r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position); 2226 expect(TRUE, r); 2227 expect2(20, 20, position.x, position.y); 2228 2229 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE); 2230 2231 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2232 DestroyWindow(hwnd); 2233 } 2234 2235 static void test_getorigin(void) 2236 { 2237 /* LVM_GETORIGIN */ 2238 2239 HWND hwnd; 2240 DWORD r; 2241 POINT position; 2242 2243 position.x = position.y = 0; 2244 2245 hwnd = create_listview_control(LVS_ICON); 2246 ok(hwnd != NULL, "failed to create a listview window\n"); 2247 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2248 2249 r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position); 2250 expect(TRUE, r); 2251 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2252 DestroyWindow(hwnd); 2253 2254 hwnd = create_listview_control(LVS_SMALLICON); 2255 ok(hwnd != NULL, "failed to create a listview window\n"); 2256 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2257 2258 r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position); 2259 expect(TRUE, r); 2260 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2261 DestroyWindow(hwnd); 2262 2263 hwnd = create_listview_control(LVS_LIST); 2264 ok(hwnd != NULL, "failed to create a listview window\n"); 2265 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2266 2267 r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position); 2268 expect(FALSE, r); 2269 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2270 DestroyWindow(hwnd); 2271 2272 hwnd = create_listview_control(LVS_REPORT); 2273 ok(hwnd != NULL, "failed to create a listview window\n"); 2274 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2275 2276 r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position); 2277 expect(FALSE, r); 2278 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2279 DestroyWindow(hwnd); 2280 } 2281 2282 static void test_multiselect(void) 2283 { 2284 typedef struct t_select_task 2285 { 2286 const char *descr; 2287 int initPos; 2288 int loopVK; 2289 int count; 2290 int result; 2291 } select_task; 2292 2293 HWND hwnd; 2294 INT r; 2295 int i, j; 2296 static const int items=5; 2297 DWORD item_count; 2298 BYTE kstate[256]; 2299 select_task task; 2300 LONG_PTR style; 2301 LVITEMA item; 2302 2303 static struct t_select_task task_list[] = { 2304 { "using VK_DOWN", 0, VK_DOWN, -1, -1 }, 2305 { "using VK_UP", -1, VK_UP, -1, -1 }, 2306 { "using VK_END", 0, VK_END, 1, -1 }, 2307 { "using VK_HOME", -1, VK_HOME, 1, -1 } 2308 }; 2309 2310 hwnd = create_listview_control(LVS_REPORT); 2311 2312 for (i = 0; i < items; i++) 2313 insert_item(hwnd, 0); 2314 2315 item_count = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 2316 expect(items, item_count); 2317 2318 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); 2319 ok(r == -1, "got %d\n", r); 2320 2321 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, 0); 2322 ok(r == -1, "got %d\n", r); 2323 2324 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, 0); 2325 ok(r == 0, "got %d\n", r); 2326 2327 /* out of range index */ 2328 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, items); 2329 ok(r == 0, "got %d\n", r); 2330 2331 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2332 ok(r == 0, "got %d\n", r); 2333 2334 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -2); 2335 ok(r == 0, "got %d\n", r); 2336 2337 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2338 ok(r == 0, "got %d\n", r); 2339 2340 for (i = 0; i < sizeof(task_list)/sizeof(task_list[0]); i++) { 2341 DWORD selected_count; 2342 LVITEMA item; 2343 2344 task = task_list[i]; 2345 2346 /* deselect all items */ 2347 item.state = 0; 2348 item.stateMask = LVIS_SELECTED; 2349 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2350 ok(r, "got %d\n", r); 2351 SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); 2352 2353 /* set initial position */ 2354 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos)); 2355 ok(r, "got %d\n", r); 2356 2357 item.state = LVIS_SELECTED; 2358 item.stateMask = LVIS_SELECTED; 2359 r = SendMessageA(hwnd, LVM_SETITEMSTATE, task.initPos == -1 ? item_count-1 : task.initPos, (LPARAM)&item); 2360 ok(r, "got %d\n", r); 2361 2362 selected_count = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 2363 ok(selected_count == 1, "expected 1, got %d\n", selected_count); 2364 2365 /* Set SHIFT key pressed */ 2366 GetKeyboardState(kstate); 2367 kstate[VK_SHIFT]=0x80; 2368 SetKeyboardState(kstate); 2369 2370 for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) { 2371 r = SendMessageA(hwnd, WM_KEYDOWN, task.loopVK, 0); 2372 expect(0,r); 2373 r = SendMessageA(hwnd, WM_KEYUP, task.loopVK, 0); 2374 expect(0,r); 2375 } 2376 2377 selected_count = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 2378 2379 ok((task.result == -1 ? item_count : task.result) == selected_count, 2380 "Failed multiple selection %s. There should be %d selected items (is %d)\n", 2381 task.descr, item_count, selected_count); 2382 2383 /* Set SHIFT key released */ 2384 GetKeyboardState(kstate); 2385 kstate[VK_SHIFT]=0x00; 2386 SetKeyboardState(kstate); 2387 } 2388 DestroyWindow(hwnd); 2389 2390 /* make multiple selection, then switch to LVS_SINGLESEL */ 2391 hwnd = create_listview_control(LVS_REPORT); 2392 for (i=0;i<items;i++) { 2393 insert_item(hwnd, 0); 2394 } 2395 item_count = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 2396 expect(items,item_count); 2397 2398 /* try with NULL pointer */ 2399 r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, 0); 2400 expect(FALSE, r); 2401 2402 /* select all, check notifications */ 2403 item.state = 0; 2404 item.stateMask = LVIS_SELECTED; 2405 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2406 ok(r, "got %d\n", r); 2407 2408 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2409 2410 item.stateMask = LVIS_SELECTED; 2411 item.state = LVIS_SELECTED; 2412 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2413 expect(TRUE, r); 2414 2415 ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq, 2416 "select all notification", FALSE); 2417 2418 /* select all again (all selected already) */ 2419 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2420 2421 memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing)); 2422 2423 item.stateMask = LVIS_SELECTED; 2424 item.state = LVIS_SELECTED; 2425 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2426 expect(TRUE, r); 2427 2428 ok(g_nmlistview_changing.uNewState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uNewState); 2429 ok(g_nmlistview_changing.uOldState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uOldState); 2430 ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged); 2431 2432 ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq, 2433 "select all notification 2", FALSE); 2434 2435 /* deselect all items */ 2436 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2437 2438 item.state = 0; 2439 item.stateMask = LVIS_SELECTED; 2440 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2441 ok(r, "got %d\n", r); 2442 2443 ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq, 2444 "deselect all notification", FALSE); 2445 2446 /* deselect all items again */ 2447 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2448 item.state = 0; 2449 item.stateMask = LVIS_SELECTED; 2450 SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2451 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "deselect all notification 2", FALSE); 2452 2453 /* any non-zero state value does the same */ 2454 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2455 2456 memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing)); 2457 2458 item.stateMask = LVIS_SELECTED; 2459 item.state = LVIS_CUT; 2460 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2461 expect(TRUE, r); 2462 2463 ok(g_nmlistview_changing.uNewState == 0, "got 0x%x\n", g_nmlistview_changing.uNewState); 2464 ok(g_nmlistview_changing.uOldState == 0, "got 0x%x\n", g_nmlistview_changing.uOldState); 2465 ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged); 2466 2467 ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq, 2468 "set state all notification 3", FALSE); 2469 2470 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); 2471 ok(r, "got %d\n", r); 2472 for (i = 0; i < 3; i++) { 2473 item.state = LVIS_SELECTED; 2474 item.stateMask = LVIS_SELECTED; 2475 r = SendMessageA(hwnd, LVM_SETITEMSTATE, i, (LPARAM)&item); 2476 ok(r, "got %d\n", r); 2477 } 2478 2479 r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 2480 expect(3, r); 2481 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2482 expect(-1, r); 2483 2484 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 2485 ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n"); 2486 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL); 2487 /* check that style is accepted */ 2488 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 2489 ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n"); 2490 2491 for (i=0;i<3;i++) { 2492 r = SendMessageA(hwnd, LVM_GETITEMSTATE, i, LVIS_SELECTED); 2493 ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i); 2494 } 2495 r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 2496 expect(3, r); 2497 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2498 ok(r == -1, "got %d\n", r); 2499 2500 /* select one more */ 2501 item.state = LVIS_SELECTED; 2502 item.stateMask = LVIS_SELECTED; 2503 r = SendMessageA(hwnd, LVM_SETITEMSTATE, 3, (LPARAM)&item); 2504 ok(r, "got %d\n", r); 2505 2506 for (i=0;i<3;i++) { 2507 r = SendMessageA(hwnd, LVM_GETITEMSTATE, i, LVIS_SELECTED); 2508 ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i); 2509 } 2510 2511 r = SendMessageA(hwnd, LVM_GETITEMSTATE, 3, LVIS_SELECTED); 2512 ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i); 2513 2514 r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 2515 expect(1, r); 2516 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2517 expect(-1, r); 2518 2519 /* try to select all on LVS_SINGLESEL */ 2520 memset(&item, 0, sizeof(item)); 2521 item.stateMask = LVIS_SELECTED; 2522 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2523 expect(TRUE, r); 2524 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); 2525 ok(r == -1, "got %d\n", r); 2526 2527 item.stateMask = LVIS_SELECTED; 2528 item.state = LVIS_SELECTED; 2529 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2530 expect(FALSE, r); 2531 2532 r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 2533 expect(0, r); 2534 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2535 expect(-1, r); 2536 2537 /* try to deselect all on LVS_SINGLESEL */ 2538 item.stateMask = LVIS_SELECTED; 2539 item.state = LVIS_SELECTED; 2540 r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 2541 expect(TRUE, r); 2542 2543 item.stateMask = LVIS_SELECTED; 2544 item.state = 0; 2545 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2546 expect(TRUE, r); 2547 r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 2548 expect(0, r); 2549 2550 /* 1. selection mark is update when new focused item is set */ 2551 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 2552 SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SINGLESEL); 2553 2554 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); 2555 expect(-1, r); 2556 2557 item.stateMask = LVIS_FOCUSED; 2558 item.state = LVIS_FOCUSED; 2559 r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 2560 expect(TRUE, r); 2561 2562 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2563 expect(0, r); 2564 2565 /* it's not updated if already set */ 2566 item.stateMask = LVIS_FOCUSED; 2567 item.state = LVIS_FOCUSED; 2568 r = SendMessageA(hwnd, LVM_SETITEMSTATE, 1, (LPARAM)&item); 2569 expect(TRUE, r); 2570 2571 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2572 expect(0, r); 2573 2574 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); 2575 expect(0, r); 2576 2577 item.stateMask = LVIS_FOCUSED; 2578 item.state = LVIS_FOCUSED; 2579 r = SendMessageA(hwnd, LVM_SETITEMSTATE, 1, (LPARAM)&item); 2580 expect(TRUE, r); 2581 2582 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2583 expect(-1, r); 2584 2585 /* need to reset focused item first */ 2586 item.stateMask = LVIS_FOCUSED; 2587 item.state = 0; 2588 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2589 expect(TRUE, r); 2590 2591 item.stateMask = LVIS_FOCUSED; 2592 item.state = LVIS_FOCUSED; 2593 r = SendMessageA(hwnd, LVM_SETITEMSTATE, 2, (LPARAM)&item); 2594 expect(TRUE, r); 2595 2596 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2597 expect(2, r); 2598 2599 item.stateMask = LVIS_FOCUSED; 2600 item.state = 0; 2601 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2602 expect(TRUE, r); 2603 2604 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2605 expect(2, r); 2606 2607 /* 2. same tests, with LVM_SETITEM */ 2608 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 2609 SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SINGLESEL); 2610 2611 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); 2612 expect(2, r); 2613 2614 item.stateMask = LVIS_FOCUSED; 2615 item.state = LVIS_FOCUSED; 2616 item.mask = LVIF_STATE; 2617 item.iItem = item.iSubItem = 0; 2618 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 2619 expect(TRUE, r); 2620 2621 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2622 expect(0, r); 2623 2624 /* it's not updated if already set */ 2625 item.stateMask = LVIS_FOCUSED; 2626 item.state = LVIS_FOCUSED; 2627 item.mask = LVIF_STATE; 2628 item.iItem = 1; 2629 item.iSubItem = 0; 2630 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 2631 expect(TRUE, r); 2632 2633 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2634 expect(0, r); 2635 2636 r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1); 2637 expect(0, r); 2638 2639 item.stateMask = LVIS_FOCUSED; 2640 item.state = LVIS_FOCUSED; 2641 item.mask = LVIF_STATE; 2642 item.iItem = 1; 2643 item.iSubItem = 0; 2644 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 2645 expect(TRUE, r); 2646 2647 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2648 expect(-1, r); 2649 2650 /* need to reset focused item first */ 2651 item.stateMask = LVIS_FOCUSED; 2652 item.state = 0; 2653 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2654 expect(TRUE, r); 2655 2656 item.stateMask = LVIS_FOCUSED; 2657 item.state = LVIS_FOCUSED; 2658 item.mask = LVIF_STATE; 2659 item.iItem = 2; 2660 item.iSubItem = 0; 2661 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 2662 expect(TRUE, r); 2663 2664 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2665 expect(2, r); 2666 2667 item.stateMask = LVIS_FOCUSED; 2668 item.state = 0; 2669 r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 2670 expect(TRUE, r); 2671 2672 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2673 expect(2, r); 2674 2675 DestroyWindow(hwnd); 2676 } 2677 2678 static void test_subitem_rect(void) 2679 { 2680 HWND hwnd; 2681 DWORD r; 2682 LVCOLUMNA col; 2683 RECT rect, rect2; 2684 INT arr[3]; 2685 2686 /* test LVM_GETSUBITEMRECT for header */ 2687 hwnd = create_listview_control(LVS_REPORT); 2688 ok(hwnd != NULL, "failed to create a listview window\n"); 2689 /* add some columns */ 2690 memset(&col, 0, sizeof(LVCOLUMNA)); 2691 col.mask = LVCF_WIDTH; 2692 col.cx = 100; 2693 r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); 2694 expect(0, r); 2695 col.cx = 150; 2696 r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&col); 2697 expect(1, r); 2698 col.cx = 200; 2699 r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 2, (LPARAM)&col); 2700 expect(2, r); 2701 /* item = -1 means header, subitem index is 1 based */ 2702 SetRect(&rect, LVIR_BOUNDS, 0, 0, 0); 2703 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); 2704 expect(0, r); 2705 2706 SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); 2707 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); 2708 expect(1, r); 2709 2710 expect(100, rect.left); 2711 expect(250, rect.right); 2712 expect(3, rect.top); 2713 2714 SetRect(&rect, LVIR_BOUNDS, 2, 0, 0); 2715 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); 2716 expect(1, r); 2717 2718 expect(250, rect.left); 2719 expect(450, rect.right); 2720 expect(3, rect.top); 2721 2722 /* item LVS_REPORT padding isn't applied to subitems */ 2723 insert_item(hwnd, 0); 2724 2725 SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); 2726 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); 2727 expect(1, r); 2728 expect(100, rect.left); 2729 expect(250, rect.right); 2730 2731 SetRect(&rect, LVIR_ICON, 1, 0, 0); 2732 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); 2733 expect(1, r); 2734 /* no icon attached - zero width rectangle, with no left padding */ 2735 expect(100, rect.left); 2736 expect(100, rect.right); 2737 2738 SetRect(&rect, LVIR_LABEL, 1, 0, 0); 2739 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); 2740 expect(1, r); 2741 /* same as full LVIR_BOUNDS */ 2742 expect(100, rect.left); 2743 expect(250, rect.right); 2744 2745 r = SendMessageA(hwnd, LVM_SCROLL, 10, 0); 2746 ok(r, "got %d\n", r); 2747 2748 SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); 2749 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); 2750 expect(1, r); 2751 expect(90, rect.left); 2752 expect(240, rect.right); 2753 2754 SendMessageA(hwnd, LVM_SCROLL, -10, 0); 2755 2756 /* test header interaction */ 2757 subclass_header(hwnd); 2758 flush_sequences(sequences, NUM_MSG_SEQUENCES); 2759 2760 SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); 2761 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); 2762 expect(1, r); 2763 2764 SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); 2765 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); 2766 expect(1, r); 2767 2768 SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); 2769 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -10, (LPARAM)&rect); 2770 expect(1, r); 2771 2772 SetRect(&rect, LVIR_BOUNDS, 1, 0, 0); 2773 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 20, (LPARAM)&rect); 2774 expect(1, r); 2775 2776 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getsubitemrect_seq, "LVM_GETSUBITEMRECT negative index", FALSE); 2777 2778 DestroyWindow(hwnd); 2779 2780 /* test subitem rects after re-arranging columns */ 2781 hwnd = create_listview_control(LVS_REPORT); 2782 ok(hwnd != NULL, "failed to create a listview window\n"); 2783 memset(&col, 0, sizeof(LVCOLUMNA)); 2784 col.mask = LVCF_WIDTH; 2785 2786 col.cx = 100; 2787 r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); 2788 expect(0, r); 2789 2790 col.cx = 200; 2791 r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&col); 2792 expect(1, r); 2793 2794 col.cx = 300; 2795 r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 2, (LPARAM)&col); 2796 expect(2, r); 2797 2798 insert_item(hwnd, 0); 2799 insert_item(hwnd, 1); 2800 2801 /* wrong item is refused for main item */ 2802 SetRect(&rect, LVIR_BOUNDS, 0, -1, -1); 2803 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 2, (LPARAM)&rect); 2804 expect(FALSE, r); 2805 2806 /* for subitems rectangle is calculated even if there's no item added */ 2807 SetRect(&rect, LVIR_BOUNDS, 1, -1, -1); 2808 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 1, (LPARAM)&rect); 2809 expect(TRUE, r); 2810 2811 SetRect(&rect2, LVIR_BOUNDS, 1, -1, -1); 2812 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 2, (LPARAM)&rect2); 2813 expect(TRUE, r); 2814 expect(rect.right, rect2.right); 2815 expect(rect.left, rect2.left); 2816 expect(rect.bottom, rect2.top); 2817 ok(rect2.bottom > rect2.top, "expected not zero height\n"); 2818 2819 arr[0] = 1; arr[1] = 0; arr[2] = 2; 2820 r = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 3, (LPARAM)arr); 2821 expect(TRUE, r); 2822 2823 SetRect(&rect, LVIR_BOUNDS, 0, -1, -1); 2824 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); 2825 expect(TRUE, r); 2826 expect(0, rect.left); 2827 expect(600, rect.right); 2828 2829 SetRect(&rect, LVIR_BOUNDS, 1, -1, -1); 2830 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); 2831 expect(TRUE, r); 2832 expect(0, rect.left); 2833 expect(200, rect.right); 2834 2835 SetRect(&rect2, LVIR_BOUNDS, 1, -1, -1); 2836 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 1, (LPARAM)&rect2); 2837 expect(TRUE, r); 2838 expect(0, rect2.left); 2839 expect(200, rect2.right); 2840 /* items are of the same height */ 2841 ok(rect2.top > 0, "expected positive item height\n"); 2842 expect(rect.bottom, rect2.top); 2843 expect(rect.bottom * 2 - rect.top, rect2.bottom); 2844 2845 SetRect(&rect, LVIR_BOUNDS, 2, -1, -1); 2846 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect); 2847 expect(TRUE, r); 2848 expect(300, rect.left); 2849 expect(600, rect.right); 2850 2851 DestroyWindow(hwnd); 2852 2853 /* try it for non LVS_REPORT style */ 2854 hwnd = CreateWindowA(WC_LISTVIEWA, "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL, 2855 GetModuleHandleA(NULL), 0); 2856 SetRect(&rect, LVIR_BOUNDS, 1, -10, -10); 2857 r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect); 2858 expect(0, r); 2859 /* rect is unchanged */ 2860 expect(0, rect.left); 2861 expect(-10, rect.right); 2862 expect(1, rect.top); 2863 expect(-10, rect.bottom); 2864 DestroyWindow(hwnd); 2865 } 2866 2867 /* comparison callback for test_sorting */ 2868 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam) 2869 { 2870 if (first == second) return 0; 2871 return (first > second ? 1 : -1); 2872 } 2873 2874 static void test_sorting(void) 2875 { 2876 HWND hwnd; 2877 LVITEMA item = {0}; 2878 INT r; 2879 LONG_PTR style; 2880 static CHAR names[][5] = {"A", "B", "C", "D", "0"}; 2881 CHAR buff[10]; 2882 2883 hwnd = create_listview_control(LVS_REPORT); 2884 ok(hwnd != NULL, "failed to create a listview window\n"); 2885 2886 /* insert some items */ 2887 item.mask = LVIF_PARAM | LVIF_STATE; 2888 item.state = LVIS_SELECTED; 2889 item.iItem = 0; 2890 item.iSubItem = 0; 2891 item.lParam = 3; 2892 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 2893 expect(0, r); 2894 2895 item.mask = LVIF_PARAM; 2896 item.iItem = 1; 2897 item.iSubItem = 0; 2898 item.lParam = 2; 2899 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 2900 expect(1, r); 2901 2902 item.mask = LVIF_STATE | LVIF_PARAM; 2903 item.state = LVIS_SELECTED; 2904 item.iItem = 2; 2905 item.iSubItem = 0; 2906 item.lParam = 4; 2907 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 2908 expect(2, r); 2909 2910 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2911 expect(-1, r); 2912 2913 r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 2914 expect(2, r); 2915 2916 r = SendMessageA(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare); 2917 expect(TRUE, r); 2918 2919 r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 2920 expect(2, r); 2921 r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 2922 expect(-1, r); 2923 r = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED); 2924 expect(0, r); 2925 r = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED); 2926 expect(LVIS_SELECTED, r); 2927 r = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED); 2928 expect(LVIS_SELECTED, r); 2929 2930 DestroyWindow(hwnd); 2931 2932 /* switch to LVS_SORTASCENDING when some items added */ 2933 hwnd = create_listview_control(LVS_REPORT); 2934 ok(hwnd != NULL, "failed to create a listview window\n"); 2935 2936 item.mask = LVIF_TEXT; 2937 item.iItem = 0; 2938 item.iSubItem = 0; 2939 item.pszText = names[1]; 2940 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 2941 expect(0, r); 2942 2943 item.mask = LVIF_TEXT; 2944 item.iItem = 1; 2945 item.iSubItem = 0; 2946 item.pszText = names[2]; 2947 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 2948 expect(1, r); 2949 2950 item.mask = LVIF_TEXT; 2951 item.iItem = 2; 2952 item.iSubItem = 0; 2953 item.pszText = names[0]; 2954 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 2955 expect(2, r); 2956 2957 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 2958 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING); 2959 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 2960 ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n"); 2961 2962 /* no sorting performed when switched to LVS_SORTASCENDING */ 2963 item.mask = LVIF_TEXT; 2964 item.iItem = 0; 2965 item.pszText = buff; 2966 item.cchTextMax = sizeof(buff); 2967 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 2968 expect(TRUE, r); 2969 ok(lstrcmpA(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff); 2970 2971 item.iItem = 1; 2972 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 2973 expect(TRUE, r); 2974 ok(lstrcmpA(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff); 2975 2976 item.iItem = 2; 2977 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 2978 expect(TRUE, r); 2979 ok(lstrcmpA(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff); 2980 2981 /* adding new item doesn't resort list */ 2982 item.mask = LVIF_TEXT; 2983 item.iItem = 3; 2984 item.iSubItem = 0; 2985 item.pszText = names[3]; 2986 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 2987 expect(3, r); 2988 2989 item.mask = LVIF_TEXT; 2990 item.iItem = 0; 2991 item.pszText = buff; 2992 item.cchTextMax = sizeof(buff); 2993 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 2994 expect(TRUE, r); 2995 ok(lstrcmpA(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff); 2996 2997 item.iItem = 1; 2998 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 2999 expect(TRUE, r); 3000 ok(lstrcmpA(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff); 3001 3002 item.iItem = 2; 3003 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 3004 expect(TRUE, r); 3005 ok(lstrcmpA(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff); 3006 3007 item.iItem = 3; 3008 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 3009 expect(TRUE, r); 3010 ok(lstrcmpA(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff); 3011 3012 /* corner case - item should be placed at first position */ 3013 item.mask = LVIF_TEXT; 3014 item.iItem = 4; 3015 item.iSubItem = 0; 3016 item.pszText = names[4]; 3017 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 3018 expect(0, r); 3019 3020 item.iItem = 0; 3021 item.pszText = buff; 3022 item.cchTextMax = sizeof(buff); 3023 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 3024 expect(TRUE, r); 3025 ok(lstrcmpA(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff); 3026 3027 item.iItem = 1; 3028 item.pszText = buff; 3029 item.cchTextMax = sizeof(buff); 3030 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 3031 expect(TRUE, r); 3032 ok(lstrcmpA(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff); 3033 3034 item.iItem = 2; 3035 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 3036 expect(TRUE, r); 3037 ok(lstrcmpA(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff); 3038 3039 item.iItem = 3; 3040 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 3041 expect(TRUE, r); 3042 ok(lstrcmpA(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff); 3043 3044 item.iItem = 4; 3045 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item); 3046 expect(TRUE, r); 3047 ok(lstrcmpA(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff); 3048 3049 DestroyWindow(hwnd); 3050 } 3051 3052 static void test_ownerdata(void) 3053 { 3054 static char test_str[] = "test"; 3055 3056 HWND hwnd; 3057 LONG_PTR style, ret; 3058 DWORD res; 3059 LVITEMA item; 3060 3061 /* it isn't possible to set LVS_OWNERDATA after creation */ 3062 if (g_is_below_5) 3063 { 3064 win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n"); 3065 } 3066 else 3067 { 3068 hwnd = create_listview_control(LVS_REPORT); 3069 ok(hwnd != NULL, "failed to create a listview window\n"); 3070 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3071 ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n"); 3072 3073 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3074 3075 ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA); 3076 ok(ret == style, "Expected set GWL_STYLE to succeed\n"); 3077 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, 3078 "try to switch to LVS_OWNERDATA seq", FALSE); 3079 3080 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3081 ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n"); 3082 DestroyWindow(hwnd); 3083 } 3084 3085 /* try to set LVS_OWNERDATA after creation just having it */ 3086 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3087 ok(hwnd != NULL, "failed to create a listview window\n"); 3088 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3089 ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n"); 3090 3091 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3092 3093 ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA); 3094 ok(ret == style, "Expected set GWL_STYLE to succeed\n"); 3095 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, 3096 "try to switch to LVS_OWNERDATA seq", FALSE); 3097 DestroyWindow(hwnd); 3098 3099 /* try to remove LVS_OWNERDATA after creation just having it */ 3100 if (g_is_below_5) 3101 { 3102 win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n"); 3103 } 3104 else 3105 { 3106 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3107 ok(hwnd != NULL, "failed to create a listview window\n"); 3108 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3109 ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n"); 3110 3111 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3112 3113 ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA); 3114 ok(ret == style, "Expected set GWL_STYLE to succeed\n"); 3115 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq, 3116 "try to switch to LVS_OWNERDATA seq", FALSE); 3117 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3118 ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n"); 3119 DestroyWindow(hwnd); 3120 } 3121 3122 /* try select an item */ 3123 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3124 ok(hwnd != NULL, "failed to create a listview window\n"); 3125 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); 3126 expect(1, res); 3127 res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 3128 expect(0, res); 3129 memset(&item, 0, sizeof(item)); 3130 item.stateMask = LVIS_SELECTED; 3131 item.state = LVIS_SELECTED; 3132 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 3133 expect(TRUE, res); 3134 res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 3135 expect(1, res); 3136 res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 3137 expect(1, res); 3138 DestroyWindow(hwnd); 3139 3140 /* LVM_SETITEM and LVM_SETITEMTEXT is unsupported on LVS_OWNERDATA */ 3141 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3142 ok(hwnd != NULL, "failed to create a listview window\n"); 3143 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); 3144 expect(1, res); 3145 res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 3146 expect(1, res); 3147 memset(&item, 0, sizeof(item)); 3148 item.mask = LVIF_STATE; 3149 item.iItem = 0; 3150 item.stateMask = LVIS_SELECTED; 3151 item.state = LVIS_SELECTED; 3152 res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 3153 expect(FALSE, res); 3154 memset(&item, 0, sizeof(item)); 3155 item.pszText = test_str; 3156 res = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); 3157 expect(FALSE, res); 3158 DestroyWindow(hwnd); 3159 3160 /* check notifications after focused/selected changed */ 3161 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3162 ok(hwnd != NULL, "failed to create a listview window\n"); 3163 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 20, 0); 3164 expect(1, res); 3165 3166 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3167 3168 memset(&item, 0, sizeof(item)); 3169 item.stateMask = LVIS_SELECTED; 3170 item.state = LVIS_SELECTED; 3171 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 3172 expect(TRUE, res); 3173 3174 ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_select_focus_parent_seq, 3175 "ownerdata select notification", TRUE); 3176 3177 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3178 3179 memset(&item, 0, sizeof(item)); 3180 item.stateMask = LVIS_FOCUSED; 3181 item.state = LVIS_FOCUSED; 3182 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 3183 expect(TRUE, res); 3184 3185 ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_select_focus_parent_seq, 3186 "ownerdata focus notification", TRUE); 3187 3188 /* select all, check notifications */ 3189 item.stateMask = LVIS_SELECTED; 3190 item.state = 0; 3191 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3192 expect(TRUE, res); 3193 3194 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3195 3196 item.stateMask = LVIS_SELECTED; 3197 item.state = LVIS_SELECTED; 3198 3199 memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 3200 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3201 expect(TRUE, res); 3202 ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); 3203 ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); 3204 ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState); 3205 ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); 3206 ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); 3207 ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); 3208 ok(g_nmlistview.lParam == 0, "got wrong lparam\n"); 3209 3210 ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq, 3211 "ownerdata select all notification", FALSE); 3212 3213 /* select all again, note that all items are selected already */ 3214 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3215 item.stateMask = LVIS_SELECTED; 3216 item.state = LVIS_SELECTED; 3217 3218 memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 3219 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3220 expect(TRUE, res); 3221 ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); 3222 ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); 3223 ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState); 3224 ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); 3225 ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); 3226 ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); 3227 ok(g_nmlistview.lParam == 0, "got wrong lparam\n"); 3228 3229 ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq, 3230 "ownerdata select all notification", FALSE); 3231 3232 /* deselect all */ 3233 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3234 item.stateMask = LVIS_SELECTED; 3235 item.state = 0; 3236 3237 memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 3238 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3239 expect(TRUE, res); 3240 ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); 3241 ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); 3242 ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState); 3243 ok(g_nmlistview.uOldState == LVIS_SELECTED, "got old state 0x%08x\n", g_nmlistview.uOldState); 3244 ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); 3245 ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); 3246 ok(g_nmlistview.lParam == 0, "got wrong lparam\n"); 3247 3248 ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq, 3249 "ownerdata deselect all notification", TRUE); 3250 3251 /* nothing selected, deselect all again */ 3252 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3253 item.stateMask = LVIS_SELECTED; 3254 item.state = 0; 3255 3256 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3257 expect(TRUE, res); 3258 3259 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "ownerdata deselect all notification", FALSE); 3260 3261 /* select one, then deselect all */ 3262 item.stateMask = LVIS_SELECTED; 3263 item.state = LVIS_SELECTED; 3264 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 3265 expect(TRUE, res); 3266 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3267 item.stateMask = LVIS_SELECTED; 3268 item.state = 0; 3269 3270 memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 3271 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3272 expect(TRUE, res); 3273 ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); 3274 ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); 3275 ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState); 3276 ok(g_nmlistview.uOldState == LVIS_SELECTED, "got old state 0x%08x\n", g_nmlistview.uOldState); 3277 ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); 3278 ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); 3279 ok(g_nmlistview.lParam == 0, "got wrong lparam\n"); 3280 3281 ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq, 3282 "ownerdata select all notification", TRUE); 3283 3284 /* remove focused, try to focus all */ 3285 item.stateMask = LVIS_FOCUSED; 3286 item.state = LVIS_FOCUSED; 3287 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 3288 expect(TRUE, res); 3289 item.stateMask = LVIS_FOCUSED; 3290 item.state = 0; 3291 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3292 expect(TRUE, res); 3293 item.stateMask = LVIS_FOCUSED; 3294 res = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED); 3295 expect(0, res); 3296 3297 /* setting all to focused returns failure value */ 3298 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3299 item.stateMask = LVIS_FOCUSED; 3300 item.state = LVIS_FOCUSED; 3301 3302 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3303 expect(FALSE, res); 3304 3305 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 3306 "ownerdata focus all notification", FALSE); 3307 3308 /* focus single item, remove all */ 3309 item.stateMask = LVIS_FOCUSED; 3310 item.state = LVIS_FOCUSED; 3311 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 3312 expect(TRUE, res); 3313 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3314 item.stateMask = LVIS_FOCUSED; 3315 item.state = 0; 3316 3317 memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 3318 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3319 expect(TRUE, res); 3320 ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); 3321 ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); 3322 ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState); 3323 ok(g_nmlistview.uOldState == LVIS_FOCUSED, "got old state 0x%08x\n", g_nmlistview.uOldState); 3324 ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); 3325 ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); 3326 ok(g_nmlistview.lParam == 0, "got wrong lparam\n"); 3327 3328 ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_defocus_all_parent_seq, 3329 "ownerdata remove focus all notification", TRUE); 3330 3331 /* set all cut */ 3332 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3333 item.stateMask = LVIS_CUT; 3334 item.state = LVIS_CUT; 3335 3336 memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 3337 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3338 expect(TRUE, res); 3339 ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); 3340 ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); 3341 ok(g_nmlistview.uNewState == LVIS_CUT, "got new state 0x%08x\n", g_nmlistview.uNewState); 3342 ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); 3343 ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); 3344 ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); 3345 ok(g_nmlistview.lParam == 0, "got wrong lparam\n"); 3346 3347 ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq, 3348 "ownerdata cut all notification", FALSE); 3349 3350 /* all marked cut, try again */ 3351 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3352 item.stateMask = LVIS_CUT; 3353 item.state = LVIS_CUT; 3354 3355 memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview)); 3356 res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item); 3357 expect(TRUE, res); 3358 ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem); 3359 ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem); 3360 ok(g_nmlistview.uNewState == LVIS_CUT, "got new state 0x%08x\n", g_nmlistview.uNewState); 3361 ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState); 3362 ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged); 3363 ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n"); 3364 ok(g_nmlistview.lParam == 0, "got wrong lparam\n"); 3365 3366 ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq, 3367 "ownerdata cut all notification #2", FALSE); 3368 3369 DestroyWindow(hwnd); 3370 3371 /* check notifications on LVM_GETITEM */ 3372 /* zero callback mask */ 3373 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3374 ok(hwnd != NULL, "failed to create a listview window\n"); 3375 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); 3376 expect(1, res); 3377 3378 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3379 3380 memset(&item, 0, sizeof(item)); 3381 item.stateMask = LVIS_SELECTED; 3382 item.mask = LVIF_STATE; 3383 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 3384 expect(TRUE, res); 3385 3386 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 3387 "ownerdata getitem selected state 1", FALSE); 3388 3389 /* non zero callback mask but not we asking for */ 3390 res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0); 3391 expect(TRUE, res); 3392 3393 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3394 3395 memset(&item, 0, sizeof(item)); 3396 item.stateMask = LVIS_SELECTED; 3397 item.mask = LVIF_STATE; 3398 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 3399 expect(TRUE, res); 3400 3401 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 3402 "ownerdata getitem selected state 2", FALSE); 3403 3404 /* LVIS_OVERLAYMASK callback mask, asking for index */ 3405 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3406 3407 memset(&item, 0, sizeof(item)); 3408 item.stateMask = LVIS_OVERLAYMASK; 3409 item.mask = LVIF_STATE; 3410 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 3411 expect(TRUE, res); 3412 3413 ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq, 3414 "ownerdata getitem selected state 2", FALSE); 3415 3416 DestroyWindow(hwnd); 3417 3418 /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */ 3419 hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING | LVS_REPORT); 3420 ok(hwnd != NULL, "failed to create a listview window\n"); 3421 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3422 ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n"); 3423 ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n"); 3424 SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING); 3425 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3426 ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n"); 3427 DestroyWindow(hwnd); 3428 /* apparently it's allowed to switch these style on after creation */ 3429 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3430 ok(hwnd != NULL, "failed to create a listview window\n"); 3431 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3432 ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n"); 3433 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING); 3434 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3435 ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n"); 3436 DestroyWindow(hwnd); 3437 3438 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3439 ok(hwnd != NULL, "failed to create a listview window\n"); 3440 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3441 ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n"); 3442 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTDESCENDING); 3443 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3444 ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n"); 3445 DestroyWindow(hwnd); 3446 3447 /* The focused item is updated after the invalidation */ 3448 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3449 ok(hwnd != NULL, "failed to create a listview window\n"); 3450 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 3, 0); 3451 expect(TRUE, res); 3452 3453 memset(&item, 0, sizeof(item)); 3454 item.stateMask = LVIS_FOCUSED; 3455 item.state = LVIS_FOCUSED; 3456 res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 3457 expect(TRUE, res); 3458 3459 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3460 res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 0, 0); 3461 expect(TRUE, res); 3462 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 3463 "ownerdata setitemcount", FALSE); 3464 3465 res = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 3466 expect(-1, res); 3467 DestroyWindow(hwnd); 3468 } 3469 3470 static void test_norecompute(void) 3471 { 3472 static CHAR testA[] = "test"; 3473 CHAR buff[10]; 3474 LVITEMA item; 3475 HWND hwnd; 3476 DWORD res; 3477 3478 /* self containing control */ 3479 hwnd = create_listview_control(LVS_REPORT); 3480 ok(hwnd != NULL, "failed to create a listview window\n"); 3481 memset(&item, 0, sizeof(item)); 3482 item.mask = LVIF_TEXT | LVIF_STATE; 3483 item.iItem = 0; 3484 item.stateMask = LVIS_SELECTED; 3485 item.state = LVIS_SELECTED; 3486 item.pszText = testA; 3487 res = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 3488 expect(0, res); 3489 /* retrieve with LVIF_NORECOMPUTE */ 3490 item.mask = LVIF_TEXT | LVIF_NORECOMPUTE; 3491 item.iItem = 0; 3492 item.pszText = buff; 3493 item.cchTextMax = sizeof(buff)/sizeof(CHAR); 3494 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 3495 expect(TRUE, res); 3496 ok(lstrcmpA(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff); 3497 3498 item.mask = LVIF_TEXT; 3499 item.iItem = 1; 3500 item.pszText = LPSTR_TEXTCALLBACKA; 3501 res = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 3502 expect(1, res); 3503 3504 item.mask = LVIF_TEXT | LVIF_NORECOMPUTE; 3505 item.iItem = 1; 3506 item.pszText = buff; 3507 item.cchTextMax = sizeof(buff)/sizeof(CHAR); 3508 3509 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3510 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 3511 expect(TRUE, res); 3512 ok(item.pszText == LPSTR_TEXTCALLBACKA, "Expected (%p), got (%p)\n", 3513 LPSTR_TEXTCALLBACKA, (VOID*)item.pszText); 3514 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE); 3515 3516 DestroyWindow(hwnd); 3517 3518 /* LVS_OWNERDATA */ 3519 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3520 ok(hwnd != NULL, "failed to create a listview window\n"); 3521 3522 item.mask = LVIF_STATE; 3523 item.stateMask = LVIS_SELECTED; 3524 item.state = LVIS_SELECTED; 3525 item.iItem = 0; 3526 res = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 3527 expect(0, res); 3528 3529 item.mask = LVIF_TEXT | LVIF_NORECOMPUTE; 3530 item.iItem = 0; 3531 item.pszText = buff; 3532 item.cchTextMax = sizeof(buff)/sizeof(CHAR); 3533 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3534 res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 3535 expect(TRUE, res); 3536 ok(item.pszText == LPSTR_TEXTCALLBACKA, "Expected (%p), got (%p)\n", 3537 LPSTR_TEXTCALLBACKA, (VOID*)item.pszText); 3538 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE); 3539 3540 DestroyWindow(hwnd); 3541 } 3542 3543 static void test_nosortheader(void) 3544 { 3545 HWND hwnd, header; 3546 LONG_PTR style; 3547 3548 hwnd = create_listview_control(LVS_REPORT); 3549 ok(hwnd != NULL, "failed to create a listview window\n"); 3550 3551 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 3552 ok(IsWindow(header), "header expected\n"); 3553 3554 style = GetWindowLongPtrA(header, GWL_STYLE); 3555 ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n"); 3556 3557 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3558 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER); 3559 /* HDS_BUTTONS retained */ 3560 style = GetWindowLongPtrA(header, GWL_STYLE); 3561 ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n"); 3562 3563 DestroyWindow(hwnd); 3564 3565 /* create with LVS_NOSORTHEADER */ 3566 hwnd = create_listview_control(LVS_NOSORTHEADER | LVS_REPORT); 3567 ok(hwnd != NULL, "failed to create a listview window\n"); 3568 3569 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 3570 ok(IsWindow(header), "header expected\n"); 3571 3572 style = GetWindowLongPtrA(header, GWL_STYLE); 3573 ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n"); 3574 3575 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3576 SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER); 3577 /* not changed here */ 3578 style = GetWindowLongPtrA(header, GWL_STYLE); 3579 ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n"); 3580 3581 DestroyWindow(hwnd); 3582 } 3583 3584 static void test_setredraw(void) 3585 { 3586 HWND hwnd; 3587 DWORD_PTR style; 3588 DWORD ret; 3589 HDC hdc; 3590 RECT rect; 3591 3592 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 3593 ok(hwnd != NULL, "failed to create a listview window\n"); 3594 3595 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE. 3596 ListView seems to handle it internally without DefWinProc */ 3597 3598 /* default value first */ 3599 ret = SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); 3600 expect(0, ret); 3601 /* disable */ 3602 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3603 ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n"); 3604 ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); 3605 expect(0, ret); 3606 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 3607 ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n"); 3608 ret = SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); 3609 expect(0, ret); 3610 3611 /* check update rect after redrawing */ 3612 ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); 3613 expect(0, ret); 3614 InvalidateRect(hwnd, NULL, FALSE); 3615 RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW); 3616 rect.right = rect.bottom = 1; 3617 GetUpdateRect(hwnd, &rect, FALSE); 3618 expect(0, rect.right); 3619 expect(0, rect.bottom); 3620 3621 /* WM_ERASEBKGND */ 3622 hdc = GetWindowDC(hwndparent); 3623 ret = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); 3624 expect(TRUE, ret); 3625 ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); 3626 expect(0, ret); 3627 ret = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); 3628 expect(TRUE, ret); 3629 ret = SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); 3630 expect(0, ret); 3631 ReleaseDC(hwndparent, hdc); 3632 3633 /* check notification messages to show that repainting is disabled */ 3634 ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); 3635 expect(TRUE, ret); 3636 ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); 3637 expect(0, ret); 3638 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3639 3640 InvalidateRect(hwnd, NULL, TRUE); 3641 UpdateWindow(hwnd); 3642 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 3643 "redraw after WM_SETREDRAW (FALSE)", FALSE); 3644 3645 ret = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE); 3646 expect(TRUE, ret); 3647 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3648 InvalidateRect(hwnd, NULL, TRUE); 3649 UpdateWindow(hwnd); 3650 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 3651 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE); 3652 3653 /* message isn't forwarded to header */ 3654 subclass_header(hwnd); 3655 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3656 ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); 3657 expect(0, ret); 3658 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, setredraw_seq, 3659 "WM_SETREDRAW: not forwarded to header", FALSE); 3660 3661 DestroyWindow(hwnd); 3662 } 3663 3664 static void test_hittest(void) 3665 { 3666 HWND hwnd; 3667 DWORD r; 3668 RECT bounds; 3669 LVITEMA item; 3670 static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST"; 3671 POINT pos; 3672 INT x, y, i; 3673 WORD vert; 3674 HIMAGELIST himl, himl2; 3675 HBITMAP hbmp; 3676 3677 hwnd = create_listview_control(LVS_REPORT); 3678 ok(hwnd != NULL, "failed to create a listview window\n"); 3679 3680 /* LVS_REPORT with a single subitem (2 columns) */ 3681 insert_column(hwnd, 0); 3682 insert_column(hwnd, 1); 3683 insert_item(hwnd, 0); 3684 3685 item.iSubItem = 0; 3686 /* the only purpose of that line is to be as long as a half item rect */ 3687 item.pszText = text; 3688 r = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); 3689 expect(TRUE, r); 3690 3691 r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0)); 3692 expect(TRUE, r); 3693 r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0)); 3694 expect(TRUE, r); 3695 3696 SetRect(&bounds, LVIR_BOUNDS, 0, 0, 0); 3697 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds); 3698 expect(1, r); 3699 ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n"); 3700 ok(bounds.right - bounds.left > 0, "Expected non zero item width\n"); 3701 r = SendMessageA(hwnd, LVM_GETITEMSPACING, TRUE, 0); 3702 vert = HIWORD(r); 3703 ok(bounds.bottom - bounds.top == vert, 3704 "Vertical spacing inconsistent (%d != %d)\n", bounds.bottom - bounds.top, vert); 3705 r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos); 3706 expect(TRUE, r); 3707 3708 /* LVS_EX_FULLROWSELECT not set, no icons attached */ 3709 3710 /* outside columns by x position - valid is [0, 199] */ 3711 x = -1; 3712 y = pos.y + (bounds.bottom - bounds.top) / 2; 3713 test_lvm_hittest(hwnd, x, y, -1, LVHT_TOLEFT, 0, FALSE, FALSE); 3714 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE); 3715 3716 x = pos.x + 50; /* column half width */ 3717 y = pos.y + (bounds.bottom - bounds.top) / 2; 3718 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, 0, FALSE, FALSE); 3719 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); 3720 x = pos.x + 150; /* outside column */ 3721 y = pos.y + (bounds.bottom - bounds.top) / 2; 3722 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE); 3723 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); 3724 y = (bounds.bottom - bounds.top) / 2; 3725 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE); 3726 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); 3727 /* outside possible client rectangle (to right) */ 3728 x = pos.x + 500; 3729 y = pos.y + (bounds.bottom - bounds.top) / 2; 3730 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE); 3731 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE); 3732 y = (bounds.bottom - bounds.top) / 2; 3733 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE); 3734 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE); 3735 /* subitem returned with -1 item too */ 3736 x = pos.x + 150; 3737 y = bounds.top - vert; 3738 test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE); 3739 test_lvm_subitemhittest(hwnd, x, y - vert + 1, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE); 3740 /* return values appear to underflow with negative indices */ 3741 i = -2; 3742 y = y - vert; 3743 while (i > -10) { 3744 test_lvm_subitemhittest(hwnd, x, y, i, 1, LVHT_ONITEMLABEL, TRUE, FALSE, TRUE); 3745 test_lvm_subitemhittest(hwnd, x, y - vert + 1, i, 1, LVHT_ONITEMLABEL, TRUE, FALSE, TRUE); 3746 y = y - vert; 3747 i--; 3748 } 3749 /* parent client area is 100x100 by default */ 3750 MoveWindow(hwnd, 0, 0, 300, 100, FALSE); 3751 x = pos.x + 150; /* outside column */ 3752 y = pos.y + (bounds.bottom - bounds.top) / 2; 3753 test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, FALSE); 3754 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); 3755 y = (bounds.bottom - bounds.top) / 2; 3756 test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, TRUE); 3757 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); 3758 /* the same with LVS_EX_FULLROWSELECT */ 3759 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); 3760 x = pos.x + 150; /* outside column */ 3761 y = pos.y + (bounds.bottom - bounds.top) / 2; 3762 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, LVHT_ONITEMLABEL, FALSE, FALSE); 3763 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); 3764 y = (bounds.bottom - bounds.top) / 2; 3765 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); 3766 MoveWindow(hwnd, 0, 0, 100, 100, FALSE); 3767 x = pos.x + 150; /* outside column */ 3768 y = pos.y + (bounds.bottom - bounds.top) / 2; 3769 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE); 3770 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); 3771 y = (bounds.bottom - bounds.top) / 2; 3772 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE); 3773 test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE); 3774 /* outside possible client rectangle (to right) */ 3775 x = pos.x + 500; 3776 y = pos.y + (bounds.bottom - bounds.top) / 2; 3777 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE); 3778 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE); 3779 y = (bounds.bottom - bounds.top) / 2; 3780 test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE); 3781 test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE); 3782 /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */ 3783 himl = pImageList_Create(16, 16, 0, 4, 4); 3784 ok(himl != NULL, "failed to create imagelist\n"); 3785 hbmp = CreateBitmap(16, 16, 1, 1, NULL); 3786 ok(hbmp != NULL, "failed to create bitmap\n"); 3787 r = pImageList_Add(himl, hbmp, 0); 3788 ok(r == 0, "should be zero\n"); 3789 hbmp = CreateBitmap(16, 16, 1, 1, NULL); 3790 ok(hbmp != NULL, "failed to create bitmap\n"); 3791 r = pImageList_Add(himl, hbmp, 0); 3792 ok(r == 1, "should be one\n"); 3793 3794 r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl); 3795 expect(0, r); 3796 3797 item.mask = LVIF_IMAGE; 3798 item.iImage = 0; 3799 item.iItem = 0; 3800 item.iSubItem = 0; 3801 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 3802 expect(TRUE, r); 3803 /* on state icon */ 3804 x = pos.x + 8; 3805 y = pos.y + (bounds.bottom - bounds.top) / 2; 3806 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE); 3807 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE); 3808 y = (bounds.bottom - bounds.top) / 2; 3809 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE); 3810 3811 /* state icons indices are 1 based, check with valid index */ 3812 item.mask = LVIF_STATE; 3813 item.state = INDEXTOSTATEIMAGEMASK(1); 3814 item.stateMask = LVIS_STATEIMAGEMASK; 3815 item.iItem = 0; 3816 item.iSubItem = 0; 3817 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 3818 expect(TRUE, r); 3819 /* on state icon */ 3820 x = pos.x + 8; 3821 y = pos.y + (bounds.bottom - bounds.top) / 2; 3822 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE); 3823 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE); 3824 y = (bounds.bottom - bounds.top) / 2; 3825 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE); 3826 3827 himl2 = (HIMAGELIST)SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0); 3828 ok(himl2 == himl, "should return handle\n"); 3829 3830 r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl); 3831 expect(0, r); 3832 /* on item icon */ 3833 x = pos.x + 8; 3834 y = pos.y + (bounds.bottom - bounds.top) / 2; 3835 test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, 0, FALSE, FALSE); 3836 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE); 3837 y = (bounds.bottom - bounds.top) / 2; 3838 test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE); 3839 3840 DestroyWindow(hwnd); 3841 } 3842 3843 static void test_getviewrect(void) 3844 { 3845 HWND hwnd; 3846 DWORD r; 3847 RECT rect; 3848 LVITEMA item; 3849 3850 hwnd = create_listview_control(LVS_REPORT); 3851 ok(hwnd != NULL, "failed to create a listview window\n"); 3852 3853 /* empty */ 3854 r = SendMessageA(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect); 3855 expect(TRUE, r); 3856 3857 insert_column(hwnd, 0); 3858 insert_column(hwnd, 1); 3859 3860 memset(&item, 0, sizeof(item)); 3861 item.iItem = 0; 3862 item.iSubItem = 0; 3863 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 3864 ok(!r, "got %d\n", r); 3865 3866 r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0)); 3867 expect(TRUE, r); 3868 r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0)); 3869 expect(TRUE, r); 3870 3871 SetRect(&rect, -1, -1, -1, -1); 3872 r = SendMessageA(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect); 3873 expect(TRUE, r); 3874 /* left is set to (2e31-1) - XP SP2 */ 3875 expect(0, rect.right); 3876 expect(0, rect.top); 3877 expect(0, rect.bottom); 3878 3879 /* switch to LVS_ICON */ 3880 SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & ~LVS_REPORT); 3881 3882 SetRect(&rect, -1, -1, -1, -1); 3883 r = SendMessageA(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect); 3884 expect(TRUE, r); 3885 expect(0, rect.left); 3886 expect(0, rect.top); 3887 /* precise value differs for 2k, XP and Vista */ 3888 ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom); 3889 ok(rect.right > 0, "Expected positive right value, got %d\n", rect.right); 3890 3891 DestroyWindow(hwnd); 3892 } 3893 3894 static void test_getitemposition(void) 3895 { 3896 HWND hwnd, header; 3897 DWORD r; 3898 POINT pt; 3899 RECT rect; 3900 3901 hwnd = create_listview_control(LVS_REPORT); 3902 ok(hwnd != NULL, "failed to create a listview window\n"); 3903 header = subclass_header(hwnd); 3904 3905 /* LVS_REPORT, single item, no columns added */ 3906 insert_item(hwnd, 0); 3907 3908 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3909 3910 pt.x = pt.y = -1; 3911 r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt); 3912 expect(TRUE, r); 3913 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE); 3914 3915 /* LVS_REPORT, single item, single column */ 3916 insert_column(hwnd, 0); 3917 3918 flush_sequences(sequences, NUM_MSG_SEQUENCES); 3919 3920 pt.x = pt.y = -1; 3921 r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt); 3922 expect(TRUE, r); 3923 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE); 3924 3925 SetRectEmpty(&rect); 3926 r = SendMessageA(header, HDM_GETITEMRECT, 0, (LPARAM)&rect); 3927 ok(r, "got %d\n", r); 3928 /* some padding? */ 3929 expect(2, pt.x); 3930 /* offset by header height */ 3931 expect(rect.bottom - rect.top, pt.y); 3932 3933 DestroyWindow(hwnd); 3934 } 3935 3936 static void test_columnscreation(void) 3937 { 3938 HWND hwnd, header; 3939 DWORD r; 3940 3941 hwnd = create_listview_control(LVS_REPORT); 3942 ok(hwnd != NULL, "failed to create a listview window\n"); 3943 3944 insert_item(hwnd, 0); 3945 3946 /* headers columns aren't created automatically */ 3947 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 3948 ok(IsWindow(header), "Expected header handle\n"); 3949 r = SendMessageA(header, HDM_GETITEMCOUNT, 0, 0); 3950 expect(0, r); 3951 3952 DestroyWindow(hwnd); 3953 } 3954 3955 static void test_getitemrect(void) 3956 { 3957 HWND hwnd; 3958 HIMAGELIST himl, himl_ret; 3959 HBITMAP hbm; 3960 RECT rect; 3961 DWORD r; 3962 LVITEMA item; 3963 LVCOLUMNA col; 3964 INT order[2]; 3965 POINT pt; 3966 3967 /* rectangle isn't empty for empty text items */ 3968 hwnd = create_listview_control(LVS_LIST); 3969 memset(&item, 0, sizeof(item)); 3970 item.mask = 0; 3971 item.iItem = 0; 3972 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 3973 expect(0, r); 3974 rect.left = LVIR_LABEL; 3975 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 3976 expect(TRUE, r); 3977 expect(0, rect.left); 3978 expect(0, rect.top); 3979 /* estimate it as width / height ratio */ 3980 todo_wine 3981 ok((rect.right / rect.bottom) >= 5, "got right %d, bottom %d\n", rect.right, rect.bottom); 3982 DestroyWindow(hwnd); 3983 3984 hwnd = create_listview_control(LVS_REPORT); 3985 ok(hwnd != NULL, "failed to create a listview window\n"); 3986 3987 /* empty item */ 3988 memset(&item, 0, sizeof(item)); 3989 item.iItem = 0; 3990 item.iSubItem = 0; 3991 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 3992 expect(0, r); 3993 3994 SetRect(&rect, LVIR_BOUNDS, -1, -1, -1); 3995 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 3996 expect(TRUE, r); 3997 3998 /* zero width rectangle with no padding */ 3999 expect(0, rect.left); 4000 expect(0, rect.right); 4001 4002 insert_column(hwnd, 0); 4003 insert_column(hwnd, 1); 4004 4005 col.mask = LVCF_WIDTH; 4006 col.cx = 50; 4007 r = SendMessageA(hwnd, LVM_SETCOLUMNA, 0, (LPARAM)&col); 4008 expect(TRUE, r); 4009 4010 col.mask = LVCF_WIDTH; 4011 col.cx = 100; 4012 r = SendMessageA(hwnd, LVM_SETCOLUMNA, 1, (LPARAM)&col); 4013 expect(TRUE, r); 4014 4015 SetRect(&rect, LVIR_BOUNDS, -1, -1, -1); 4016 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4017 expect(TRUE, r); 4018 4019 /* still no left padding */ 4020 expect(0, rect.left); 4021 expect(150, rect.right); 4022 4023 SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1); 4024 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4025 expect(TRUE, r); 4026 /* padding */ 4027 expect(2, rect.left); 4028 4029 SetRect(&rect, LVIR_LABEL, -1, -1, -1); 4030 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4031 expect(TRUE, r); 4032 /* padding, column width */ 4033 expect(2, rect.left); 4034 expect(50, rect.right); 4035 4036 /* no icons attached */ 4037 SetRect(&rect, LVIR_ICON, -1, -1, -1); 4038 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4039 expect(TRUE, r); 4040 /* padding */ 4041 expect(2, rect.left); 4042 expect(2, rect.right); 4043 4044 /* change order */ 4045 order[0] = 1; order[1] = 0; 4046 r = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order); 4047 expect(TRUE, r); 4048 pt.x = -1; 4049 r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt); 4050 expect(TRUE, r); 4051 /* 1 indexed column width + padding */ 4052 expect(102, pt.x); 4053 /* rect is at zero too */ 4054 SetRect(&rect, LVIR_BOUNDS, -1, -1, -1); 4055 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4056 expect(TRUE, r); 4057 expect(0, rect.left); 4058 /* just width sum */ 4059 expect(150, rect.right); 4060 4061 SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1); 4062 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4063 expect(TRUE, r); 4064 /* column width + padding */ 4065 expect(102, rect.left); 4066 4067 /* back to initial order */ 4068 order[0] = 0; order[1] = 1; 4069 r = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order); 4070 expect(TRUE, r); 4071 4072 /* state icons */ 4073 himl = pImageList_Create(16, 16, 0, 2, 2); 4074 ok(himl != NULL, "failed to create imagelist\n"); 4075 hbm = CreateBitmap(16, 16, 1, 1, NULL); 4076 ok(hbm != NULL, "failed to create bitmap\n"); 4077 r = pImageList_Add(himl, hbm, 0); 4078 expect(0, r); 4079 hbm = CreateBitmap(16, 16, 1, 1, NULL); 4080 ok(hbm != NULL, "failed to create bitmap\n"); 4081 r = pImageList_Add(himl, hbm, 0); 4082 expect(1, r); 4083 4084 r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl); 4085 expect(0, r); 4086 4087 item.mask = LVIF_STATE; 4088 item.state = INDEXTOSTATEIMAGEMASK(1); 4089 item.stateMask = LVIS_STATEIMAGEMASK; 4090 item.iItem = 0; 4091 item.iSubItem = 0; 4092 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 4093 expect(TRUE, r); 4094 4095 /* icon bounds */ 4096 SetRect(&rect, LVIR_ICON, -1, -1, -1); 4097 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4098 expect(TRUE, r); 4099 /* padding + stateicon width */ 4100 expect(18, rect.left); 4101 expect(18, rect.right); 4102 /* label bounds */ 4103 SetRect(&rect, LVIR_LABEL, -1, -1, -1); 4104 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4105 expect(TRUE, r); 4106 /* padding + stateicon width -> column width */ 4107 expect(18, rect.left); 4108 expect(50, rect.right); 4109 4110 himl_ret = (HIMAGELIST)SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0); 4111 ok(himl_ret == himl, "got %p, expected %p\n", himl_ret, himl); 4112 4113 r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl); 4114 expect(0, r); 4115 4116 item.mask = LVIF_STATE | LVIF_IMAGE; 4117 item.iImage = 1; 4118 item.state = 0; 4119 item.stateMask = ~0; 4120 item.iItem = 0; 4121 item.iSubItem = 0; 4122 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 4123 expect(TRUE, r); 4124 4125 /* icon bounds */ 4126 SetRect(&rect, LVIR_ICON, -1, -1, -1); 4127 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4128 expect(TRUE, r); 4129 /* padding, icon width */ 4130 expect(2, rect.left); 4131 expect(18, rect.right); 4132 /* label bounds */ 4133 SetRect(&rect, LVIR_LABEL, -1, -1, -1); 4134 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4135 expect(TRUE, r); 4136 /* padding + icon width -> column width */ 4137 expect(18, rect.left); 4138 expect(50, rect.right); 4139 4140 /* select bounds */ 4141 SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1); 4142 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4143 expect(TRUE, r); 4144 /* padding, column width */ 4145 expect(2, rect.left); 4146 expect(50, rect.right); 4147 4148 /* try with indentation */ 4149 item.mask = LVIF_INDENT; 4150 item.iIndent = 1; 4151 item.iItem = 0; 4152 item.iSubItem = 0; 4153 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 4154 expect(TRUE, r); 4155 4156 /* bounds */ 4157 SetRect(&rect, LVIR_BOUNDS, -1, -1, -1); 4158 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4159 expect(TRUE, r); 4160 /* padding + 1 icon width, column width */ 4161 expect(0, rect.left); 4162 expect(150, rect.right); 4163 4164 /* select bounds */ 4165 SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1); 4166 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4167 expect(TRUE, r); 4168 /* padding + 1 icon width, column width */ 4169 expect(2 + 16, rect.left); 4170 expect(50, rect.right); 4171 4172 /* label bounds */ 4173 SetRect(&rect, LVIR_LABEL, -1, -1, -1); 4174 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4175 expect(TRUE, r); 4176 /* padding + 2 icon widths, column width */ 4177 expect(2 + 16*2, rect.left); 4178 expect(50, rect.right); 4179 4180 /* icon bounds */ 4181 SetRect(&rect, LVIR_ICON, -1, -1, -1); 4182 r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect); 4183 expect(TRUE, r); 4184 /* padding + 1 icon width indentation, icon width */ 4185 expect(2 + 16, rect.left); 4186 expect(34, rect.right); 4187 4188 DestroyWindow(hwnd); 4189 } 4190 4191 static void test_editbox(void) 4192 { 4193 static CHAR testitemA[] = "testitem"; 4194 static CHAR testitem1A[] = "testitem_quitelongname"; 4195 static CHAR testitem2A[] = "testITEM_quitelongname"; 4196 static CHAR buffer[25]; 4197 HWND hwnd, hwndedit, hwndedit2, header; 4198 LVITEMA item; 4199 INT r; 4200 4201 hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT); 4202 ok(hwnd != NULL, "failed to create a listview window\n"); 4203 4204 insert_column(hwnd, 0); 4205 4206 memset(&item, 0, sizeof(item)); 4207 item.mask = LVIF_TEXT; 4208 item.pszText = testitemA; 4209 item.iItem = 0; 4210 item.iSubItem = 0; 4211 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 4212 expect(0, r); 4213 4214 /* test notifications without edit created */ 4215 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4216 r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)0xdeadbeef); 4217 expect(0, r); 4218 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 4219 "edit box WM_COMMAND (EN_SETFOCUS), no edit created", FALSE); 4220 /* same thing but with valid window */ 4221 hwndedit = CreateWindowA(WC_EDITA, "Test edit", WS_VISIBLE | WS_CHILD, 0, 0, 20, 4222 10, hwnd, (HMENU)1, (HINSTANCE)GetWindowLongPtrA(hwnd, GWLP_HINSTANCE), 0); 4223 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4224 r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)hwndedit); 4225 expect(0, r); 4226 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 4227 "edit box WM_COMMAND (EN_SETFOCUS), no edit created #2", FALSE); 4228 DestroyWindow(hwndedit); 4229 4230 /* setting focus is necessary */ 4231 SetFocus(hwnd); 4232 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4233 ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); 4234 4235 /* test children Z-order after Edit box created */ 4236 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 4237 ok(IsWindow(header), "Expected header to be created\n"); 4238 ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n"); 4239 ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT)); 4240 4241 /* modify initial string */ 4242 r = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A); 4243 expect(TRUE, r); 4244 4245 /* edit window is resized and repositioned, 4246 check again for Z-order - it should be preserved */ 4247 ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n"); 4248 ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT)); 4249 4250 /* return focus to listview */ 4251 SetFocus(hwnd); 4252 4253 memset(&item, 0, sizeof(item)); 4254 item.mask = LVIF_TEXT; 4255 item.pszText = buffer; 4256 item.cchTextMax = sizeof(buffer); 4257 item.iItem = 0; 4258 item.iSubItem = 0; 4259 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 4260 expect(TRUE, r); 4261 4262 ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n"); 4263 4264 /* send LVM_EDITLABEL on already created edit */ 4265 SetFocus(hwnd); 4266 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4267 ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); 4268 /* focus will be set to edit */ 4269 ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n"); 4270 hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4271 ok(IsWindow(hwndedit2), "Expected Edit window to be created\n"); 4272 4273 /* creating label disabled when control isn't focused */ 4274 SetFocus(0); 4275 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4276 todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n"); 4277 4278 /* check EN_KILLFOCUS handling */ 4279 memset(&item, 0, sizeof(item)); 4280 item.pszText = testitemA; 4281 item.iItem = 0; 4282 item.iSubItem = 0; 4283 r = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); 4284 expect(TRUE, r); 4285 4286 SetFocus(hwnd); 4287 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4288 ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); 4289 /* modify edit and notify control that it lost focus */ 4290 r = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A); 4291 expect(TRUE, r); 4292 g_editbox_disp_info.item.pszText = NULL; 4293 r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit); 4294 expect(0, r); 4295 ok(g_editbox_disp_info.item.pszText != NULL, "expected notification with not null text\n"); 4296 4297 memset(&item, 0, sizeof(item)); 4298 item.pszText = buffer; 4299 item.cchTextMax = sizeof(buffer); 4300 item.iItem = 0; 4301 item.iSubItem = 0; 4302 r = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item); 4303 expect(lstrlenA(item.pszText), r); 4304 ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n"); 4305 ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n"); 4306 4307 /* change item name to differ in casing only */ 4308 SetFocus(hwnd); 4309 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4310 ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); 4311 /* modify edit and notify control that it lost focus */ 4312 r = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem2A); 4313 expect(TRUE, r); 4314 g_editbox_disp_info.item.pszText = NULL; 4315 r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit); 4316 expect(0, r); 4317 ok(g_editbox_disp_info.item.pszText != NULL, "got %p\n", g_editbox_disp_info.item.pszText); 4318 4319 memset(&item, 0, sizeof(item)); 4320 item.pszText = buffer; 4321 item.cchTextMax = sizeof(buffer); 4322 item.iItem = 0; 4323 item.iSubItem = 0; 4324 r = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item); 4325 expect(lstrlenA(item.pszText), r); 4326 ok(strcmp(buffer, testitem2A) == 0, "got %s, expected %s\n", buffer, testitem2A); 4327 ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n"); 4328 4329 /* end edit without saving */ 4330 SetFocus(hwnd); 4331 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4332 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4333 r = SendMessageA(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0); 4334 expect(0, r); 4335 ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange, 4336 "edit box - end edit, no change, escape", TRUE); 4337 /* end edit with saving */ 4338 SetFocus(hwnd); 4339 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4340 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4341 r = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0); 4342 expect(0, r); 4343 ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange, 4344 "edit box - end edit, no change, return", TRUE); 4345 4346 memset(&item, 0, sizeof(item)); 4347 item.pszText = buffer; 4348 item.cchTextMax = sizeof(buffer); 4349 item.iItem = 0; 4350 item.iSubItem = 0; 4351 r = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item); 4352 expect(lstrlenA(item.pszText), r); 4353 ok(strcmp(buffer, testitem2A) == 0, "Expected item text to change\n"); 4354 4355 /* LVM_EDITLABEL with -1 destroys current edit */ 4356 hwndedit = (HWND)SendMessageA(hwnd, LVM_GETEDITCONTROL, 0, 0); 4357 ok(hwndedit == NULL, "Expected Edit window not to be created\n"); 4358 /* no edit present */ 4359 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, -1, 0); 4360 ok(hwndedit == NULL, "Expected Edit window not to be created\n"); 4361 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4362 ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); 4363 /* edit present */ 4364 ok(GetFocus() == hwndedit, "Expected Edit to be focused\n"); 4365 hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, -1, 0); 4366 ok(hwndedit2 == NULL, "Expected Edit window not to be created\n"); 4367 ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n"); 4368 ok(GetFocus() == hwnd, "Expected List to be focused\n"); 4369 /* check another negative value */ 4370 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4371 ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); 4372 ok(GetFocus() == hwndedit, "Expected Edit to be focused\n"); 4373 hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, -2, 0); 4374 ok(hwndedit2 == NULL, "Expected Edit window not to be created\n"); 4375 ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n"); 4376 ok(GetFocus() == hwnd, "Expected List to be focused\n"); 4377 /* and value greater than max item index */ 4378 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4379 ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); 4380 ok(GetFocus() == hwndedit, "Expected Edit to be focused\n"); 4381 r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0); 4382 hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, r, 0); 4383 ok(hwndedit2 == NULL, "Expected Edit window not to be created\n"); 4384 ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n"); 4385 ok(GetFocus() == hwnd, "Expected List to be focused\n"); 4386 4387 /* messaging tests */ 4388 SetFocus(hwnd); 4389 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4390 blockEdit = FALSE; 4391 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4392 ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); 4393 /* testing only sizing messages */ 4394 ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos, 4395 "edit box create - sizing", FALSE); 4396 4397 /* WM_COMMAND with EN_KILLFOCUS isn't forwarded to parent */ 4398 SetFocus(hwnd); 4399 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4400 ok(IsWindow(hwndedit), "Expected Edit window to be created\n"); 4401 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4402 r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit); 4403 expect(0, r); 4404 ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange, 4405 "edit box WM_COMMAND (EN_KILLFOCUS)", TRUE); 4406 4407 DestroyWindow(hwnd); 4408 } 4409 4410 static void test_notifyformat(void) 4411 { 4412 HWND hwnd, header; 4413 DWORD r; 4414 4415 hwnd = create_listview_control(LVS_REPORT); 4416 ok(hwnd != NULL, "failed to create a listview window\n"); 4417 4418 /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT, 4419 CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */ 4420 r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4421 expect(0, r); 4422 SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY); 4423 /* set */ 4424 r = SendMessageA(hwnd, LVM_SETUNICODEFORMAT, 1, 0); 4425 expect(0, r); 4426 r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4427 ok(r == 1, "Unexpected return value %d.\n", r); 4428 r = SendMessageA(hwnd, LVM_SETUNICODEFORMAT, 0, 0); 4429 expect(1, r); 4430 r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4431 expect(0, r); 4432 4433 DestroyWindow(hwnd); 4434 4435 /* test failure in parent WM_NOTIFYFORMAT */ 4436 notifyFormat = 0; 4437 hwnd = create_listview_control(LVS_REPORT); 4438 ok(hwnd != NULL, "failed to create a listview window\n"); 4439 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 4440 ok(IsWindow(header), "expected header to be created\n"); 4441 r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4442 expect(0, r); 4443 r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); 4444 ok( r == 1, "Expected 1, got %d\n", r ); 4445 r = SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY); 4446 ok(r != 0, "Expected valid format\n"); 4447 4448 notifyFormat = NFR_UNICODE; 4449 r = SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY); 4450 expect(NFR_UNICODE, r); 4451 r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4452 expect(1, r); 4453 r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); 4454 ok( r == 1, "Expected 1, got %d\n", r ); 4455 4456 notifyFormat = NFR_ANSI; 4457 r = SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY); 4458 expect(NFR_ANSI, r); 4459 r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4460 expect(0, r); 4461 r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); 4462 ok( r == 1, "Expected 1, got %d\n", r ); 4463 4464 DestroyWindow(hwnd); 4465 4466 hwndparentW = create_parent_window(TRUE); 4467 ok(IsWindow(hwndparentW), "Unicode parent creation failed\n"); 4468 if (!IsWindow(hwndparentW)) return; 4469 4470 notifyFormat = -1; 4471 hwnd = create_listview_controlW(LVS_REPORT, hwndparentW); 4472 ok(hwnd != NULL, "failed to create a listview window\n"); 4473 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 4474 ok(IsWindow(header), "expected header to be created\n"); 4475 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4476 expect(1, r); 4477 r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); 4478 expect(1, r); 4479 DestroyWindow(hwnd); 4480 /* receiving error code defaulting to ansi */ 4481 notifyFormat = 0; 4482 hwnd = create_listview_controlW(LVS_REPORT, hwndparentW); 4483 ok(hwnd != NULL, "failed to create a listview window\n"); 4484 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 4485 ok(IsWindow(header), "expected header to be created\n"); 4486 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4487 expect(0, r); 4488 r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); 4489 expect(1, r); 4490 DestroyWindow(hwnd); 4491 /* receiving ansi code from unicode window, use it */ 4492 notifyFormat = NFR_ANSI; 4493 hwnd = create_listview_controlW(LVS_REPORT, hwndparentW); 4494 ok(hwnd != NULL, "failed to create a listview window\n"); 4495 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 4496 ok(IsWindow(header), "expected header to be created\n"); 4497 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4498 expect(0, r); 4499 r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); 4500 expect(1, r); 4501 DestroyWindow(hwnd); 4502 /* unicode listview with ansi parent window */ 4503 notifyFormat = -1; 4504 hwnd = create_listview_controlW(LVS_REPORT, hwndparent); 4505 ok(hwnd != NULL, "failed to create a listview window\n"); 4506 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 4507 ok(IsWindow(header), "expected header to be created\n"); 4508 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4509 expect(0, r); 4510 r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); 4511 expect(1, r); 4512 DestroyWindow(hwnd); 4513 /* unicode listview with ansi parent window, return error code */ 4514 notifyFormat = 0; 4515 hwnd = create_listview_controlW(LVS_REPORT, hwndparent); 4516 ok(hwnd != NULL, "failed to create a listview window\n"); 4517 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 4518 ok(IsWindow(header), "expected header to be created\n"); 4519 r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0); 4520 expect(0, r); 4521 r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0); 4522 expect(1, r); 4523 DestroyWindow(hwnd); 4524 4525 DestroyWindow(hwndparentW); 4526 } 4527 4528 static void test_indentation(void) 4529 { 4530 HWND hwnd; 4531 LVITEMA item; 4532 DWORD r; 4533 4534 hwnd = create_listview_control(LVS_REPORT); 4535 ok(hwnd != NULL, "failed to create a listview window\n"); 4536 4537 memset(&item, 0, sizeof(item)); 4538 item.mask = LVIF_INDENT; 4539 item.iItem = 0; 4540 item.iIndent = I_INDENTCALLBACK; 4541 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 4542 expect(0, r); 4543 4544 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4545 4546 item.iItem = 0; 4547 item.mask = LVIF_INDENT; 4548 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 4549 expect(TRUE, r); 4550 4551 ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq, 4552 "get indent dispinfo", FALSE); 4553 4554 DestroyWindow(hwnd); 4555 } 4556 4557 static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param) 4558 { 4559 return 0; 4560 } 4561 4562 static BOOL is_below_comctl_5(void) 4563 { 4564 HWND hwnd; 4565 BOOL ret; 4566 4567 hwnd = create_listview_control(LVS_REPORT); 4568 ok(hwnd != NULL, "failed to create a listview window\n"); 4569 insert_item(hwnd, 0); 4570 4571 ret = SendMessageA(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx); 4572 4573 DestroyWindow(hwnd); 4574 4575 return !ret; 4576 } 4577 4578 static void test_get_set_view(void) 4579 { 4580 HWND hwnd; 4581 DWORD ret; 4582 DWORD_PTR style; 4583 4584 /* test style->view mapping */ 4585 hwnd = create_listview_control(LVS_REPORT); 4586 ok(hwnd != NULL, "failed to create a listview window\n"); 4587 4588 ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); 4589 expect(LV_VIEW_DETAILS, ret); 4590 4591 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 4592 /* LVS_ICON == 0 */ 4593 SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_REPORT); 4594 ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); 4595 expect(LV_VIEW_ICON, ret); 4596 4597 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 4598 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SMALLICON); 4599 ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); 4600 expect(LV_VIEW_SMALLICON, ret); 4601 4602 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 4603 SetWindowLongPtrA(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST); 4604 ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); 4605 expect(LV_VIEW_LIST, ret); 4606 4607 /* switching view doesn't touch window style */ 4608 ret = SendMessageA(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0); 4609 expect(1, ret); 4610 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 4611 ok(style & LVS_LIST, "Expected style to be preserved\n"); 4612 ret = SendMessageA(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0); 4613 expect(1, ret); 4614 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 4615 ok(style & LVS_LIST, "Expected style to be preserved\n"); 4616 ret = SendMessageA(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0); 4617 expect(1, ret); 4618 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 4619 ok(style & LVS_LIST, "Expected style to be preserved\n"); 4620 4621 /* now change window style to see if view is remapped */ 4622 style = GetWindowLongPtrA(hwnd, GWL_STYLE); 4623 SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SHOWSELALWAYS); 4624 ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0); 4625 expect(LV_VIEW_SMALLICON, ret); 4626 4627 DestroyWindow(hwnd); 4628 } 4629 4630 static void test_canceleditlabel(void) 4631 { 4632 HWND hwnd, hwndedit; 4633 DWORD ret; 4634 CHAR buff[10]; 4635 LVITEMA itema; 4636 static CHAR test[] = "test"; 4637 static const CHAR test1[] = "test1"; 4638 4639 hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT); 4640 ok(hwnd != NULL, "failed to create a listview window\n"); 4641 4642 insert_item(hwnd, 0); 4643 4644 /* try without edit created */ 4645 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4646 ret = SendMessageA(hwnd, LVM_CANCELEDITLABEL, 0, 0); 4647 expect(TRUE, ret); 4648 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 4649 "cancel edit label without edit", FALSE); 4650 4651 /* cancel without data change */ 4652 SetFocus(hwnd); 4653 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4654 ok(IsWindow(hwndedit), "Expected edit control to be created\n"); 4655 ret = SendMessageA(hwnd, LVM_CANCELEDITLABEL, 0, 0); 4656 expect(TRUE, ret); 4657 ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n"); 4658 4659 /* cancel after data change */ 4660 memset(&itema, 0, sizeof(itema)); 4661 itema.pszText = test; 4662 ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&itema); 4663 expect(TRUE, ret); 4664 SetFocus(hwnd); 4665 hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0); 4666 ok(IsWindow(hwndedit), "Expected edit control to be created\n"); 4667 ret = SetWindowTextA(hwndedit, test1); 4668 expect(1, ret); 4669 ret = SendMessageA(hwnd, LVM_CANCELEDITLABEL, 0, 0); 4670 expect(TRUE, ret); 4671 ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n"); 4672 memset(&itema, 0, sizeof(itema)); 4673 itema.pszText = buff; 4674 itema.cchTextMax = sizeof(buff)/sizeof(CHAR); 4675 ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&itema); 4676 expect(5, ret); 4677 ok(strcmp(buff, test1) == 0, "Expected label text not to change\n"); 4678 4679 DestroyWindow(hwnd); 4680 } 4681 4682 static void test_mapidindex(void) 4683 { 4684 HWND hwnd; 4685 INT ret; 4686 4687 /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */ 4688 hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT); 4689 ok(hwnd != NULL, "failed to create a listview window\n"); 4690 insert_item(hwnd, 0); 4691 ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0); 4692 expect(-1, ret); 4693 DestroyWindow(hwnd); 4694 4695 hwnd = create_listview_control(LVS_REPORT); 4696 ok(hwnd != NULL, "failed to create a listview window\n"); 4697 4698 /* LVM_MAPINDEXTOID with invalid index */ 4699 ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0); 4700 expect(-1, ret); 4701 4702 insert_item(hwnd, 0); 4703 insert_item(hwnd, 1); 4704 4705 ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, -1, 0); 4706 expect(-1, ret); 4707 ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 2, 0); 4708 expect(-1, ret); 4709 4710 ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0); 4711 expect(0, ret); 4712 ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 1, 0); 4713 expect(1, ret); 4714 /* remove 0 indexed item, id retained */ 4715 SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); 4716 ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0); 4717 expect(1, ret); 4718 /* new id starts from previous value */ 4719 insert_item(hwnd, 1); 4720 ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 1, 0); 4721 expect(2, ret); 4722 4723 /* get index by id */ 4724 ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, -1, 0); 4725 expect(-1, ret); 4726 ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, 0, 0); 4727 expect(-1, ret); 4728 ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, 1, 0); 4729 expect(0, ret); 4730 ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, 2, 0); 4731 expect(1, ret); 4732 4733 DestroyWindow(hwnd); 4734 } 4735 4736 static void test_getitemspacing(void) 4737 { 4738 HWND hwnd; 4739 DWORD ret; 4740 INT cx, cy; 4741 HIMAGELIST himl40, himl80; 4742 4743 cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON); 4744 cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON); 4745 4746 /* LVS_ICON */ 4747 hwnd = create_listview_control(LVS_ICON); 4748 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4749 expect(cx, LOWORD(ret)); 4750 expect(cy, HIWORD(ret)); 4751 4752 /* now try with icons */ 4753 himl40 = pImageList_Create(40, 40, 0, 4, 4); 4754 ok(himl40 != NULL, "failed to create imagelist\n"); 4755 himl80 = pImageList_Create(80, 80, 0, 4, 4); 4756 ok(himl80 != NULL, "failed to create imagelist\n"); 4757 ret = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40); 4758 expect(0, ret); 4759 4760 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4761 /* spacing + icon size returned */ 4762 expect(cx + 40, LOWORD(ret)); 4763 expect(cy + 40, HIWORD(ret)); 4764 /* try changing icon size */ 4765 SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl80); 4766 4767 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4768 /* spacing + icon size returned */ 4769 expect(cx + 80, LOWORD(ret)); 4770 expect(cy + 80, HIWORD(ret)); 4771 4772 /* set own icon spacing */ 4773 ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(100, 100)); 4774 expect(cx + 80, LOWORD(ret)); 4775 expect(cy + 80, HIWORD(ret)); 4776 4777 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4778 /* set size returned */ 4779 expect(100, LOWORD(ret)); 4780 expect(100, HIWORD(ret)); 4781 4782 /* now change image list - icon spacing should be unaffected */ 4783 SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40); 4784 4785 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4786 /* set size returned */ 4787 expect(100, LOWORD(ret)); 4788 expect(100, HIWORD(ret)); 4789 4790 /* spacing = 0 - keep previous value */ 4791 ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(0, -1)); 4792 expect(100, LOWORD(ret)); 4793 expect(100, HIWORD(ret)); 4794 4795 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4796 expect(100, LOWORD(ret)); 4797 4798 expect(0xFFFF, HIWORD(ret)); 4799 4800 if (sizeof(void*) == 8) 4801 { 4802 /* NOTE: -1 is not treated the same as (DWORD)-1 by 64bit listview */ 4803 ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, (DWORD)-1); 4804 expect(100, LOWORD(ret)); 4805 expect(0xFFFF, HIWORD(ret)); 4806 4807 ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, -1); 4808 expect(0xFFFF, LOWORD(ret)); 4809 expect(0xFFFF, HIWORD(ret)); 4810 } 4811 else 4812 { 4813 ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, -1); 4814 expect(100, LOWORD(ret)); 4815 expect(0xFFFF, HIWORD(ret)); 4816 } 4817 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4818 /* spacing + icon size returned */ 4819 expect(cx + 40, LOWORD(ret)); 4820 expect(cy + 40, HIWORD(ret)); 4821 4822 SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, 0); 4823 pImageList_Destroy(himl80); 4824 DestroyWindow(hwnd); 4825 /* LVS_SMALLICON */ 4826 hwnd = create_listview_control(LVS_SMALLICON); 4827 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4828 expect(cx, LOWORD(ret)); 4829 expect(cy, HIWORD(ret)); 4830 4831 /* spacing does not depend on selected view type */ 4832 ret = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40); 4833 expect(0, ret); 4834 4835 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4836 /* spacing + icon size returned */ 4837 expect(cx + 40, LOWORD(ret)); 4838 expect(cy + 40, HIWORD(ret)); 4839 4840 SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, 0); 4841 pImageList_Destroy(himl40); 4842 DestroyWindow(hwnd); 4843 /* LVS_REPORT */ 4844 hwnd = create_listview_control(LVS_REPORT); 4845 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4846 expect(cx, LOWORD(ret)); 4847 expect(cy, HIWORD(ret)); 4848 4849 DestroyWindow(hwnd); 4850 /* LVS_LIST */ 4851 hwnd = create_listview_control(LVS_LIST); 4852 ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0); 4853 expect(cx, LOWORD(ret)); 4854 expect(cy, HIWORD(ret)); 4855 4856 DestroyWindow(hwnd); 4857 } 4858 4859 static INT get_current_font_height(HWND listview) 4860 { 4861 TEXTMETRICA tm; 4862 HFONT hfont; 4863 HWND hwnd; 4864 HDC hdc; 4865 4866 hwnd = (HWND)SendMessageA(listview, LVM_GETHEADER, 0, 0); 4867 if (!hwnd) 4868 hwnd = listview; 4869 4870 hfont = (HFONT)SendMessageA(hwnd, WM_GETFONT, 0, 0); 4871 if (!hfont) { 4872 hdc = GetDC(hwnd); 4873 GetTextMetricsA(hdc, &tm); 4874 ReleaseDC(hwnd, hdc); 4875 } 4876 else { 4877 HFONT oldfont; 4878 4879 hdc = GetDC(0); 4880 oldfont = SelectObject(hdc, hfont); 4881 GetTextMetricsA(hdc, &tm); 4882 SelectObject(hdc, oldfont); 4883 ReleaseDC(0, hdc); 4884 } 4885 4886 return tm.tmHeight; 4887 } 4888 4889 static void test_getcolumnwidth(void) 4890 { 4891 HWND hwnd; 4892 INT ret; 4893 DWORD_PTR style; 4894 LVCOLUMNA col; 4895 LVITEMA itema; 4896 INT height; 4897 4898 /* default column width */ 4899 hwnd = create_listview_control(LVS_ICON); 4900 ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); 4901 expect(0, ret); 4902 style = GetWindowLongA(hwnd, GWL_STYLE); 4903 SetWindowLongA(hwnd, GWL_STYLE, style | LVS_LIST); 4904 ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); 4905 todo_wine expect(8, ret); 4906 style = GetWindowLongA(hwnd, GWL_STYLE) & ~LVS_LIST; 4907 SetWindowLongA(hwnd, GWL_STYLE, style | LVS_REPORT); 4908 col.mask = 0; 4909 ret = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); 4910 expect(0, ret); 4911 ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); 4912 expect(10, ret); 4913 DestroyWindow(hwnd); 4914 4915 /* default column width with item added */ 4916 hwnd = create_listview_control(LVS_LIST); 4917 memset(&itema, 0, sizeof(itema)); 4918 ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema); 4919 ok(!ret, "got %d\n", ret); 4920 ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); 4921 height = get_current_font_height(hwnd); 4922 ok((ret / height) >= 6, "got width %d, height %d\n", ret, height); 4923 DestroyWindow(hwnd); 4924 } 4925 4926 static void test_scrollnotify(void) 4927 { 4928 HWND hwnd; 4929 DWORD ret; 4930 4931 hwnd = create_listview_control(LVS_REPORT); 4932 4933 insert_column(hwnd, 0); 4934 insert_column(hwnd, 1); 4935 insert_item(hwnd, 0); 4936 4937 /* make it scrollable - resize */ 4938 ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0)); 4939 expect(TRUE, ret); 4940 ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0)); 4941 expect(TRUE, ret); 4942 4943 /* try with dummy call */ 4944 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4945 ret = SendMessageA(hwnd, LVM_SCROLL, 0, 0); 4946 expect(TRUE, ret); 4947 ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq, 4948 "scroll notify 1", TRUE); 4949 4950 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4951 ret = SendMessageA(hwnd, LVM_SCROLL, 1, 0); 4952 expect(TRUE, ret); 4953 ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq, 4954 "scroll notify 2", TRUE); 4955 4956 flush_sequences(sequences, NUM_MSG_SEQUENCES); 4957 ret = SendMessageA(hwnd, LVM_SCROLL, 1, 1); 4958 expect(TRUE, ret); 4959 ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq, 4960 "scroll notify 3", TRUE); 4961 4962 DestroyWindow(hwnd); 4963 } 4964 4965 static void test_LVS_EX_TRANSPARENTBKGND(void) 4966 { 4967 HWND hwnd; 4968 DWORD ret; 4969 HDC hdc; 4970 4971 hwnd = create_listview_control(LVS_REPORT); 4972 4973 ret = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0)); 4974 expect(TRUE, ret); 4975 4976 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND, 4977 LVS_EX_TRANSPARENTBKGND); 4978 4979 ret = SendMessageA(hwnd, LVM_GETBKCOLOR, 0, 0); 4980 if (ret != CLR_NONE) 4981 { 4982 win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n"); 4983 DestroyWindow(hwnd); 4984 return; 4985 } 4986 4987 /* try to set some back color and check this style bit */ 4988 ret = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0)); 4989 expect(TRUE, ret); 4990 ret = SendMessageA(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); 4991 ok(!(ret & LVS_EX_TRANSPARENTBKGND), "Expected LVS_EX_TRANSPARENTBKGND to unset\n"); 4992 4993 /* now test what this style actually does */ 4994 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND, 4995 LVS_EX_TRANSPARENTBKGND); 4996 4997 hdc = GetWindowDC(hwndparent); 4998 4999 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5000 SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0); 5001 ok_sequence(sequences, PARENT_SEQ_INDEX, lvs_ex_transparentbkgnd_seq, 5002 "LVS_EX_TRANSPARENTBKGND parent", FALSE); 5003 5004 ReleaseDC(hwndparent, hdc); 5005 5006 DestroyWindow(hwnd); 5007 } 5008 5009 static void test_approximate_viewrect(void) 5010 { 5011 static CHAR test[] = "abracadabra, a very long item label"; 5012 DWORD item_width, item_height, header_height; 5013 static CHAR column_header[] = "Header"; 5014 unsigned const column_width = 100; 5015 DWORD ret, item_count; 5016 HIMAGELIST himl; 5017 LVITEMA itema; 5018 LVCOLUMNA col; 5019 HBITMAP hbmp; 5020 HWND hwnd; 5021 5022 /* LVS_ICON */ 5023 hwnd = create_listview_control(LVS_ICON); 5024 himl = pImageList_Create(40, 40, 0, 4, 4); 5025 ok(himl != NULL, "failed to create imagelist\n"); 5026 hbmp = CreateBitmap(40, 40, 1, 1, NULL); 5027 ok(hbmp != NULL, "failed to create bitmap\n"); 5028 ret = pImageList_Add(himl, hbmp, 0); 5029 expect(0, ret); 5030 ret = SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl); 5031 expect(0, ret); 5032 5033 itema.mask = LVIF_IMAGE; 5034 itema.iImage = 0; 5035 itema.iItem = 0; 5036 itema.iSubItem = 0; 5037 ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema); 5038 expect(0, ret); 5039 5040 ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(75, 75)); 5041 ok(ret != 0, "Unexpected return value %#x.\n", ret); 5042 5043 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100)); 5044 expect(MAKELONG(77,827), ret); 5045 5046 ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(50, 50)); 5047 ok(ret != 0, "got 0\n"); 5048 5049 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100)); 5050 expect(MAKELONG(102,302), ret); 5051 5052 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100)); 5053 expect(MAKELONG(52,52), ret); 5054 5055 itema.pszText = test; 5056 ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&itema); 5057 expect(TRUE, ret); 5058 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100)); 5059 expect(MAKELONG(52,52), ret); 5060 5061 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, MAKELPARAM(100,100)); 5062 expect(MAKELONG(52,2), ret); 5063 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, MAKELPARAM(100,100)); 5064 expect(MAKELONG(52,52), ret); 5065 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, MAKELPARAM(100,100)); 5066 expect(MAKELONG(102,52), ret); 5067 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 3, MAKELPARAM(100,100)); 5068 expect(MAKELONG(102,102), ret); 5069 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 4, MAKELPARAM(100,100)); 5070 expect(MAKELONG(102,102), ret); 5071 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 5, MAKELPARAM(100,100)); 5072 expect(MAKELONG(102,152), ret); 5073 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 6, MAKELPARAM(100,100)); 5074 expect(MAKELONG(102,152), ret); 5075 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 7, MAKELPARAM(160,100)); 5076 expect(MAKELONG(152,152), ret); 5077 5078 DestroyWindow(hwnd); 5079 5080 /* LVS_REPORT */ 5081 hwnd = create_listview_control(LVS_REPORT); 5082 5083 /* Empty control without columns */ 5084 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, MAKELPARAM(100, 100)); 5085 todo_wine 5086 ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); 5087 ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret)); 5088 5089 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, 0); 5090 ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); 5091 todo_wine 5092 ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret)); 5093 5094 header_height = HIWORD(ret); 5095 5096 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, 0); 5097 ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); 5098 todo_wine 5099 ok(HIWORD(ret) > header_height, "Unexpected height %d.\n", HIWORD(ret)); 5100 5101 item_height = HIWORD(ret) - header_height; 5102 5103 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, 0); 5104 ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); 5105 ok(HIWORD(ret) == (header_height - 2 * item_height), "Unexpected height %d.\n", HIWORD(ret)) ; 5106 5107 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, 0); 5108 ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); 5109 ok(HIWORD(ret) == header_height, "Unexpected height.\n"); 5110 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, 0); 5111 ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret)); 5112 ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret)); 5113 5114 /* Insert column */ 5115 col.mask = LVCF_TEXT | LVCF_WIDTH; 5116 col.pszText = column_header; 5117 col.cx = column_width; 5118 ret = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); 5119 ok(ret == 0, "Unexpected return value %d.\n", ret); 5120 5121 /* Empty control with column */ 5122 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, 0); 5123 todo_wine { 5124 ok(LOWORD(ret) >= column_width, "Unexpected width %d.\n", LOWORD(ret)); 5125 ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret)); 5126 } 5127 header_height = HIWORD(ret); 5128 item_width = LOWORD(ret); 5129 5130 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, 0); 5131 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5132 todo_wine 5133 ok(HIWORD(ret) > header_height, "Unexpected height %d.\n", HIWORD(ret)); 5134 5135 item_height = HIWORD(ret) - header_height; 5136 5137 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, 0); 5138 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5139 ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret)); 5140 5141 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, 0); 5142 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5143 ok(HIWORD(ret) == header_height, "Unexpected height %d.\n", HIWORD(ret)); 5144 5145 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, 0); 5146 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5147 ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret)); 5148 5149 for (item_count = 1; item_count <= 2; ++item_count) 5150 { 5151 itema.mask = LVIF_TEXT; 5152 itema.iItem = 0; 5153 itema.iSubItem = 0; 5154 itema.pszText = test; 5155 ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema); 5156 ok(ret == 0, "Unexpected return value %d.\n", ret); 5157 5158 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, 0); 5159 ok(LOWORD(ret) >= column_width, "Unexpected width %d.\n", LOWORD(ret)); 5160 todo_wine 5161 ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret)); 5162 5163 header_height = HIWORD(ret); 5164 item_width = LOWORD(ret); 5165 5166 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, 0); 5167 ok(LOWORD(ret) == item_width, "Unexpected width %d, item %d\n", LOWORD(ret), item_count - 1); 5168 ok(HIWORD(ret) > header_height, "Unexpected height %d. item %d.\n", HIWORD(ret), item_count - 1); 5169 5170 item_height = HIWORD(ret) - header_height; 5171 5172 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, 0); 5173 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5174 todo_wine 5175 ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret)); 5176 5177 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, 0); 5178 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5179 ok(HIWORD(ret) == header_height + item_count * item_height, "Unexpected height %d.\n", HIWORD(ret)); 5180 5181 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, 0); 5182 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5183 ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret)); 5184 5185 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, MAKELONG(item_width * 2, header_height + 3 * item_height)); 5186 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5187 ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret)); 5188 5189 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, MAKELONG(item_width * 2, 0)); 5190 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5191 todo_wine 5192 ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret)); 5193 5194 ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, MAKELONG(-1, -1)); 5195 ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret)); 5196 todo_wine 5197 ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret)); 5198 } 5199 5200 DestroyWindow(hwnd); 5201 5202 } 5203 5204 static void test_finditem(void) 5205 { 5206 LVFINDINFOA fi; 5207 static char f[5]; 5208 HWND hwnd; 5209 INT r; 5210 5211 hwnd = create_listview_control(LVS_REPORT); 5212 insert_item(hwnd, 0); 5213 5214 memset(&fi, 0, sizeof(fi)); 5215 5216 /* full string search, inserted text was "foo" */ 5217 strcpy(f, "foo"); 5218 fi.flags = LVFI_STRING; 5219 fi.psz = f; 5220 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5221 expect(0, r); 5222 5223 fi.flags = LVFI_STRING | LVFI_PARTIAL; 5224 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5225 expect(0, r); 5226 5227 fi.flags = LVFI_PARTIAL; 5228 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5229 expect(0, r); 5230 5231 /* partial string search, inserted text was "foo" */ 5232 strcpy(f, "fo"); 5233 fi.flags = LVFI_STRING | LVFI_PARTIAL; 5234 fi.psz = f; 5235 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5236 expect(0, r); 5237 5238 fi.flags = LVFI_STRING; 5239 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5240 expect(-1, r); 5241 5242 fi.flags = LVFI_PARTIAL; 5243 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5244 expect(0, r); 5245 5246 /* partial string search, part after start char */ 5247 strcpy(f, "oo"); 5248 fi.flags = LVFI_STRING | LVFI_PARTIAL; 5249 fi.psz = f; 5250 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5251 expect(-1, r); 5252 5253 /* try with LVFI_SUBSTRING */ 5254 strcpy(f, "fo"); 5255 fi.flags = LVFI_SUBSTRING; 5256 fi.psz = f; 5257 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5258 expect(0, r); 5259 strcpy(f, "f"); 5260 fi.flags = LVFI_SUBSTRING; 5261 fi.psz = f; 5262 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5263 expect(0, r); 5264 strcpy(f, "o"); 5265 fi.flags = LVFI_SUBSTRING; 5266 fi.psz = f; 5267 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5268 expect(-1, r); 5269 5270 strcpy(f, "o"); 5271 fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL; 5272 fi.psz = f; 5273 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5274 expect(-1, r); 5275 5276 strcpy(f, "f"); 5277 fi.flags = LVFI_SUBSTRING | LVFI_STRING; 5278 fi.psz = f; 5279 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5280 expect(0, r); 5281 5282 fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL; 5283 r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi); 5284 expect(0, r); 5285 5286 DestroyWindow(hwnd); 5287 } 5288 5289 static void test_LVS_EX_HEADERINALLVIEWS(void) 5290 { 5291 HWND hwnd, header; 5292 DWORD style; 5293 5294 hwnd = create_listview_control(LVS_ICON); 5295 5296 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 5297 LVS_EX_HEADERINALLVIEWS); 5298 5299 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 5300 if (!IsWindow(header)) 5301 { 5302 win_skip("LVS_EX_HEADERINALLVIEWS unsupported\n"); 5303 DestroyWindow(hwnd); 5304 return; 5305 } 5306 5307 /* LVS_NOCOLUMNHEADER works as before */ 5308 style = GetWindowLongA(hwnd, GWL_STYLE); 5309 SetWindowLongW(hwnd, GWL_STYLE, style | LVS_NOCOLUMNHEADER); 5310 style = GetWindowLongA(header, GWL_STYLE); 5311 ok(style & HDS_HIDDEN, "Expected HDS_HIDDEN\n"); 5312 style = GetWindowLongA(hwnd, GWL_STYLE); 5313 SetWindowLongW(hwnd, GWL_STYLE, style & ~LVS_NOCOLUMNHEADER); 5314 style = GetWindowLongA(header, GWL_STYLE); 5315 ok(!(style & HDS_HIDDEN), "Expected HDS_HIDDEN to be unset\n"); 5316 5317 /* try to remove style */ 5318 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 0); 5319 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 5320 ok(IsWindow(header), "Expected header to be created\n"); 5321 style = GetWindowLongA(header, GWL_STYLE); 5322 ok(!(style & HDS_HIDDEN), "HDS_HIDDEN not expected\n"); 5323 5324 DestroyWindow(hwnd); 5325 5326 /* check other styles */ 5327 hwnd = create_listview_control(LVS_LIST); 5328 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 5329 LVS_EX_HEADERINALLVIEWS); 5330 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 5331 ok(IsWindow(header), "Expected header to be created\n"); 5332 DestroyWindow(hwnd); 5333 5334 hwnd = create_listview_control(LVS_SMALLICON); 5335 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 5336 LVS_EX_HEADERINALLVIEWS); 5337 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 5338 ok(IsWindow(header), "Expected header to be created\n"); 5339 DestroyWindow(hwnd); 5340 5341 hwnd = create_listview_control(LVS_REPORT); 5342 SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 5343 LVS_EX_HEADERINALLVIEWS); 5344 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 5345 ok(IsWindow(header), "Expected header to be created\n"); 5346 DestroyWindow(hwnd); 5347 } 5348 5349 static void test_hover(void) 5350 { 5351 HWND hwnd, fg; 5352 DWORD r; 5353 5354 hwnd = create_listview_control(LVS_ICON); 5355 SetForegroundWindow(hwndparent); 5356 fg = GetForegroundWindow(); 5357 if (fg != hwndparent) 5358 { 5359 skip("Window is not in the foreground. Skipping hover tests.\n"); 5360 DestroyWindow(hwnd); 5361 return; 5362 } 5363 5364 /* test WM_MOUSEHOVER forwarding */ 5365 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5366 r = SendMessageA(hwnd, WM_MOUSEHOVER, 0, 0); 5367 expect(0, r); 5368 ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER allow test", TRUE); 5369 g_block_hover = TRUE; 5370 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5371 r = SendMessageA(hwnd, WM_MOUSEHOVER, 0, 0); 5372 expect(0, r); 5373 ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER block test", TRUE); 5374 g_block_hover = FALSE; 5375 5376 r = SendMessageA(hwnd, LVM_SETHOVERTIME, 0, 500); 5377 expect(HOVER_DEFAULT, r); 5378 r = SendMessageA(hwnd, LVM_GETHOVERTIME, 0, 0); 5379 expect(500, r); 5380 5381 DestroyWindow(hwnd); 5382 } 5383 5384 static void test_destroynotify(void) 5385 { 5386 HWND hwnd; 5387 BOOL ret; 5388 5389 hwnd = create_listview_control(LVS_REPORT); 5390 ok(hwnd != NULL, "failed to create listview window\n"); 5391 5392 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5393 DestroyWindow(hwnd); 5394 ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_destroy, "check destroy order", FALSE); 5395 5396 /* same for ownerdata list */ 5397 hwnd = create_listview_control(LVS_REPORT|LVS_OWNERDATA); 5398 ok(hwnd != NULL, "failed to create listview window\n"); 5399 5400 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5401 DestroyWindow(hwnd); 5402 ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_ownerdata_destroy, "check destroy order, ownerdata", FALSE); 5403 5404 hwnd = create_listview_control(LVS_REPORT|LVS_OWNERDATA); 5405 ok(hwnd != NULL, "failed to create listview window\n"); 5406 5407 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5408 ret = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0); 5409 ok(ret == TRUE, "got %d\n", ret); 5410 ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_ownerdata_deleteall, "deleteall ownerdata", FALSE); 5411 DestroyWindow(hwnd); 5412 } 5413 5414 static void test_header_notification(void) 5415 { 5416 static char textA[] = "newtext"; 5417 HWND list, header; 5418 HDITEMA item; 5419 NMHEADERA nmh; 5420 LVCOLUMNA col; 5421 DWORD ret; 5422 BOOL r; 5423 5424 list = create_listview_control(LVS_REPORT); 5425 ok(list != NULL, "failed to create listview window\n"); 5426 5427 memset(&col, 0, sizeof(col)); 5428 col.mask = LVCF_WIDTH; 5429 col.cx = 100; 5430 ret = SendMessageA(list, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); 5431 expect(0, ret); 5432 5433 /* check list parent notification after header item changed, 5434 this test should be placed before header subclassing to avoid 5435 Listview -> Header messages to be logged */ 5436 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5437 5438 col.mask = LVCF_TEXT; 5439 col.pszText = textA; 5440 r = SendMessageA(list, LVM_SETCOLUMNA, 0, (LPARAM)&col); 5441 expect(TRUE, r); 5442 5443 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_header_changed_seq, 5444 "header notify, listview", FALSE); 5445 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 5446 "header notify, parent", FALSE); 5447 5448 header = subclass_header(list); 5449 5450 ret = SendMessageA(header, HDM_GETITEMCOUNT, 0, 0); 5451 expect(1, ret); 5452 5453 memset(&item, 0, sizeof(item)); 5454 item.mask = HDI_WIDTH; 5455 ret = SendMessageA(header, HDM_GETITEMA, 0, (LPARAM)&item); 5456 expect(1, ret); 5457 expect(100, item.cxy); 5458 5459 nmh.hdr.hwndFrom = header; 5460 nmh.hdr.idFrom = GetWindowLongPtrA(header, GWLP_ID); 5461 nmh.hdr.code = HDN_ITEMCHANGEDA; 5462 nmh.iItem = 0; 5463 nmh.iButton = 0; 5464 item.mask = HDI_WIDTH; 5465 item.cxy = 50; 5466 nmh.pitem = &item; 5467 ret = SendMessageA(list, WM_NOTIFY, 0, (LPARAM)&nmh); 5468 expect(0, ret); 5469 5470 DestroyWindow(list); 5471 } 5472 5473 static void test_header_notification2(void) 5474 { 5475 static char textA[] = "newtext"; 5476 HWND list, header; 5477 HDITEMW itemW; 5478 NMHEADERW nmhdr; 5479 LVCOLUMNA col; 5480 DWORD ret; 5481 WCHAR buffer[100]; 5482 struct message parent_header_notify_seq[] = { 5483 { WM_NOTIFY, sent|id, 0, 0, 0 }, 5484 { 0 } 5485 }; 5486 5487 list = create_listview_control(LVS_REPORT); 5488 ok(list != NULL, "failed to create listview window\n"); 5489 5490 memset(&col, 0, sizeof(col)); 5491 col.mask = LVCF_WIDTH | LVCF_TEXT; 5492 col.cx = 100; 5493 col.pszText = textA; 5494 ret = SendMessageA(list, LVM_INSERTCOLUMNA, 0, (LPARAM)&col); 5495 expect(0, ret); 5496 5497 header = (HWND)SendMessageA(list, LVM_GETHEADER, 0, 0); 5498 ok(header != 0, "No header\n"); 5499 memset(&itemW, 0, sizeof(itemW)); 5500 itemW.mask = HDI_WIDTH | HDI_ORDER | HDI_TEXT; 5501 itemW.pszText = buffer; 5502 itemW.cchTextMax = sizeof(buffer); 5503 ret = SendMessageW(header, HDM_GETITEMW, 0, (LPARAM)&itemW); 5504 expect(1, ret); 5505 5506 nmhdr.hdr.hwndFrom = header; 5507 nmhdr.hdr.idFrom = GetWindowLongPtrW(header, GWLP_ID); 5508 nmhdr.iItem = 0; 5509 nmhdr.iButton = 0; 5510 nmhdr.pitem = &itemW; 5511 5512 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5513 nmhdr.hdr.code = HDN_ITEMCHANGINGW; 5514 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5515 ok(ret == 0, "got %d\n", ret); 5516 parent_header_notify_seq[0].id = HDN_ITEMCHANGINGA; 5517 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, 5518 "header notify, parent", TRUE); 5519 todo_wine 5520 ok(nmhdr.hdr.code == HDN_ITEMCHANGINGA, "Expected ANSI notification code\n"); 5521 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5522 nmhdr.hdr.code = HDN_ITEMCHANGEDW; 5523 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5524 ok(ret == 0, "got %d\n", ret); 5525 parent_header_notify_seq[0].id = HDN_ITEMCHANGEDA; 5526 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, 5527 "header notify, parent", TRUE); 5528 todo_wine 5529 ok(nmhdr.hdr.code == HDN_ITEMCHANGEDA, "Expected ANSI notification code\n"); 5530 /* HDN_ITEMCLICK sets focus to list, which generates messages we don't want to check */ 5531 SetFocus(list); 5532 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5533 nmhdr.hdr.code = HDN_ITEMCLICKW; 5534 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5535 ok(ret == 0, "got %d\n", ret); 5536 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_click_seq, 5537 "header notify, parent", FALSE); 5538 ok(nmhdr.hdr.code == HDN_ITEMCLICKA, "Expected ANSI notification code\n"); 5539 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5540 nmhdr.hdr.code = HDN_ITEMDBLCLICKW; 5541 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5542 ok(ret == 0, "got %d\n", ret); 5543 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 5544 "header notify, parent", FALSE); 5545 ok(nmhdr.hdr.code == HDN_ITEMDBLCLICKW, "Expected Unicode notification code\n"); 5546 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5547 nmhdr.hdr.code = HDN_DIVIDERDBLCLICKW; 5548 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5549 ok(ret == 0, "got %d\n", ret); 5550 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_divider_dclick_seq, 5551 "header notify, parent", TRUE); 5552 ok(nmhdr.hdr.code == HDN_DIVIDERDBLCLICKA, "Expected ANSI notification code\n"); 5553 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5554 nmhdr.hdr.code = HDN_BEGINTRACKW; 5555 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5556 ok(ret == 0, "got %d\n", ret); 5557 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 5558 "header notify, parent", FALSE); 5559 ok(nmhdr.hdr.code == HDN_BEGINTRACKW, "Expected Unicode notification code\n"); 5560 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5561 nmhdr.hdr.code = HDN_ENDTRACKW; 5562 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5563 ok(ret == 0, "got %d\n", ret); 5564 parent_header_notify_seq[0].id = HDN_ENDTRACKA; 5565 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, 5566 "header notify, parent", FALSE); 5567 ok(nmhdr.hdr.code == HDN_ENDTRACKA, "Expected ANSI notification code\n"); 5568 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5569 nmhdr.hdr.code = HDN_TRACKW; 5570 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5571 ok(ret == 0, "got %d\n", ret); 5572 parent_header_notify_seq[0].id = HDN_TRACKA; 5573 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, 5574 "header notify, parent", FALSE); 5575 ok(nmhdr.hdr.code == HDN_TRACKA, "Expected ANSI notification code\n"); 5576 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5577 nmhdr.hdr.code = HDN_BEGINDRAG; 5578 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5579 ok(ret == 1, "got %d\n", ret); 5580 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 5581 "header notify, parent", FALSE); 5582 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5583 nmhdr.hdr.code = HDN_ENDDRAG; 5584 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5585 ok(ret == 0, "got %d\n", ret); 5586 parent_header_notify_seq[0].id = HDN_ENDDRAG; 5587 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, 5588 "header notify, parent", FALSE); 5589 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5590 nmhdr.hdr.code = HDN_FILTERCHANGE; 5591 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5592 ok(ret == 0, "got %d\n", ret); 5593 parent_header_notify_seq[0].id = HDN_FILTERCHANGE; 5594 parent_header_notify_seq[0].flags |= optional; /* NT4 does not send this message */ 5595 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq, 5596 "header notify, parent", FALSE); 5597 parent_header_notify_seq[0].flags &= ~optional; 5598 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5599 nmhdr.hdr.code = HDN_BEGINFILTEREDIT; 5600 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5601 ok(ret == 0, "got %d\n", ret); 5602 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 5603 "header notify, parent", FALSE); 5604 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5605 nmhdr.hdr.code = HDN_ENDFILTEREDIT; 5606 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5607 ok(ret == 0, "got %d\n", ret); 5608 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 5609 "header notify, parent", FALSE); 5610 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5611 nmhdr.hdr.code = HDN_ITEMSTATEICONCLICK; 5612 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5613 ok(ret == 0, "got %d\n", ret); 5614 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 5615 "header notify, parent", FALSE); 5616 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5617 nmhdr.hdr.code = HDN_ITEMKEYDOWN; 5618 ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr); 5619 ok(ret == 0, "got %d\n", ret); 5620 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, 5621 "header notify, parent", FALSE); 5622 5623 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5624 5625 DestroyWindow(list); 5626 } 5627 5628 static void test_createdragimage(void) 5629 { 5630 HIMAGELIST himl; 5631 POINT pt; 5632 HWND list; 5633 5634 list = create_listview_control(LVS_ICON); 5635 ok(list != NULL, "failed to create listview window\n"); 5636 5637 insert_item(list, 0); 5638 5639 /* NULL point */ 5640 himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, 0); 5641 ok(himl == NULL, "got %p\n", himl); 5642 5643 himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, (LPARAM)&pt); 5644 ok(himl != NULL, "got %p\n", himl); 5645 pImageList_Destroy(himl); 5646 5647 DestroyWindow(list); 5648 } 5649 5650 static void test_dispinfo(void) 5651 { 5652 static const char testA[] = "TEST"; 5653 WCHAR buff[10]; 5654 LVITEMA item; 5655 HWND hwnd; 5656 DWORD ret; 5657 5658 hwnd = create_listview_control(LVS_ICON); 5659 ok(hwnd != NULL, "failed to create listview window\n"); 5660 5661 insert_item(hwnd, 0); 5662 5663 memset(&item, 0, sizeof(item)); 5664 item.pszText = LPSTR_TEXTCALLBACKA; 5665 ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); 5666 expect(1, ret); 5667 5668 g_disp_A_to_W = TRUE; 5669 item.pszText = (char*)buff; 5670 item.cchTextMax = sizeof(buff)/sizeof(WCHAR); 5671 ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item); 5672 ok(ret == sizeof(testA)-1, "got %d, expected 4\n", ret); 5673 g_disp_A_to_W = FALSE; 5674 5675 ok(memcmp(item.pszText, testA, sizeof(testA)) == 0, 5676 "got %s, expected %s\n", item.pszText, testA); 5677 5678 DestroyWindow(hwnd); 5679 } 5680 5681 static void test_LVM_SETITEMTEXT(void) 5682 { 5683 static char testA[] = "TEST"; 5684 LVITEMA item; 5685 HWND hwnd; 5686 DWORD ret; 5687 5688 hwnd = create_listview_control(LVS_ICON); 5689 ok(hwnd != NULL, "failed to create listview window\n"); 5690 5691 insert_item(hwnd, 0); 5692 5693 /* null item pointer */ 5694 ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, 0); 5695 expect(FALSE, ret); 5696 5697 ret = SendMessageA(hwnd, LVM_SETITEMTEXTW, 0, 0); 5698 expect(FALSE, ret); 5699 5700 /* index out of bounds */ 5701 item.pszText = testA; 5702 item.cchTextMax = 0; /* ignored */ 5703 item.iSubItem = 0; 5704 5705 ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 1, (LPARAM)&item); 5706 expect(FALSE, ret); 5707 5708 ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, -1, (LPARAM)&item); 5709 expect(FALSE, ret); 5710 5711 ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item); 5712 expect(TRUE, ret); 5713 5714 DestroyWindow(hwnd); 5715 } 5716 5717 static void test_LVM_REDRAWITEMS(void) 5718 { 5719 HWND list; 5720 DWORD ret; 5721 5722 list = create_listview_control(LVS_ICON); 5723 ok(list != NULL, "failed to create listview window\n"); 5724 5725 ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0); 5726 expect(TRUE, ret); 5727 5728 insert_item(list, 0); 5729 5730 ret = SendMessageA(list, LVM_REDRAWITEMS, -1, 0); 5731 expect(TRUE, ret); 5732 5733 ret = SendMessageA(list, LVM_REDRAWITEMS, 0, -1); 5734 expect(TRUE, ret); 5735 5736 ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0); 5737 expect(TRUE, ret); 5738 5739 ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 1); 5740 expect(TRUE, ret); 5741 5742 ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 2); 5743 expect(TRUE, ret); 5744 5745 ret = SendMessageA(list, LVM_REDRAWITEMS, 1, 0); 5746 expect(TRUE, ret); 5747 5748 ret = SendMessageA(list, LVM_REDRAWITEMS, 2, 3); 5749 expect(TRUE, ret); 5750 5751 DestroyWindow(list); 5752 } 5753 5754 static void test_imagelists(void) 5755 { 5756 HWND hwnd, header; 5757 HIMAGELIST himl1, himl2, himl3; 5758 LRESULT ret; 5759 5760 himl1 = pImageList_Create(40, 40, 0, 4, 4); 5761 himl2 = pImageList_Create(40, 40, 0, 4, 4); 5762 himl3 = pImageList_Create(40, 40, 0, 4, 4); 5763 ok(himl1 != NULL, "Failed to create imagelist\n"); 5764 ok(himl2 != NULL, "Failed to create imagelist\n"); 5765 ok(himl3 != NULL, "Failed to create imagelist\n"); 5766 5767 hwnd = create_listview_control(LVS_REPORT | LVS_SHAREIMAGELISTS); 5768 header = subclass_header(hwnd); 5769 5770 ok(header != NULL, "Expected header\n"); 5771 ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0); 5772 ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); 5773 5774 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5775 5776 ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl1); 5777 ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); 5778 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, 5779 "set normal image list", FALSE); 5780 5781 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5782 5783 ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl2); 5784 ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); 5785 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, 5786 "set state image list", TRUE); 5787 5788 ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0); 5789 ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); 5790 5791 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5792 5793 ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl3); 5794 ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); 5795 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_header_set_imagelist, 5796 "set small image list", FALSE); 5797 5798 ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0); 5799 ok((HIMAGELIST)ret == himl3, "Expected imagelist %p, got %p\n", himl3, (HIMAGELIST)ret); 5800 DestroyWindow(hwnd); 5801 5802 hwnd = create_listview_control(WS_VISIBLE | LVS_ICON); 5803 5804 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5805 5806 ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl1); 5807 ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); 5808 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, 5809 "set normal image list", FALSE); 5810 5811 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5812 5813 ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl2); 5814 ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); 5815 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, 5816 "set state image list", FALSE); 5817 5818 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5819 5820 ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl3); 5821 ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret); 5822 ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist, 5823 "set small image list", FALSE); 5824 5825 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 5826 ok(header == NULL, "Expected no header, got %p\n", header); 5827 5828 SetWindowLongPtrA(hwnd, GWL_STYLE, GetWindowLongPtrA(hwnd, GWL_STYLE) | LVS_REPORT); 5829 5830 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 5831 ok(header != NULL, "Expected header, got NULL\n"); 5832 5833 ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0); 5834 ok((HIMAGELIST)ret == himl3, "Expected imagelist %p, got %p\n", himl3, (HIMAGELIST)ret); 5835 5836 DestroyWindow(hwnd); 5837 } 5838 5839 static void test_deleteitem(void) 5840 { 5841 LVITEMA item; 5842 UINT state; 5843 HWND hwnd; 5844 BOOL ret; 5845 5846 hwnd = create_listview_control(LVS_REPORT); 5847 5848 insert_item(hwnd, 0); 5849 insert_item(hwnd, 0); 5850 insert_item(hwnd, 0); 5851 insert_item(hwnd, 0); 5852 insert_item(hwnd, 0); 5853 5854 g_focus_test_LVN_DELETEITEM = TRUE; 5855 5856 /* delete focused item (not the last index) */ 5857 item.stateMask = LVIS_FOCUSED; 5858 item.state = LVIS_FOCUSED; 5859 ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 2, (LPARAM)&item); 5860 ok(ret == TRUE, "got %d\n", ret); 5861 ret = SendMessageA(hwnd, LVM_DELETEITEM, 2, 0); 5862 ok(ret == TRUE, "got %d\n", ret); 5863 /* next item gets focus */ 5864 state = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_FOCUSED); 5865 ok(state == LVIS_FOCUSED, "got %x\n", state); 5866 5867 /* focus last item and delete it */ 5868 item.stateMask = LVIS_FOCUSED; 5869 item.state = LVIS_FOCUSED; 5870 ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 3, (LPARAM)&item); 5871 ok(ret == TRUE, "got %d\n", ret); 5872 ret = SendMessageA(hwnd, LVM_DELETEITEM, 3, 0); 5873 ok(ret == TRUE, "got %d\n", ret); 5874 /* new last item gets focus */ 5875 state = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_FOCUSED); 5876 ok(state == LVIS_FOCUSED, "got %x\n", state); 5877 5878 /* focus first item and delete it */ 5879 item.stateMask = LVIS_FOCUSED; 5880 item.state = LVIS_FOCUSED; 5881 ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 5882 ok(ret == TRUE, "got %d\n", ret); 5883 ret = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0); 5884 ok(ret == TRUE, "got %d\n", ret); 5885 /* new first item gets focus */ 5886 state = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED); 5887 ok(state == LVIS_FOCUSED, "got %x\n", state); 5888 5889 g_focus_test_LVN_DELETEITEM = FALSE; 5890 5891 DestroyWindow(hwnd); 5892 } 5893 5894 static void test_insertitem(void) 5895 { 5896 LVITEMA item; 5897 UINT state; 5898 HWND hwnd; 5899 INT ret; 5900 5901 hwnd = create_listview_control(LVS_REPORT); 5902 5903 /* insert item 0 focused */ 5904 item.mask = LVIF_STATE; 5905 item.state = LVIS_FOCUSED; 5906 item.stateMask = LVIS_FOCUSED; 5907 item.iItem = 0; 5908 item.iSubItem = 0; 5909 ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 5910 ok(ret == 0, "got %d\n", ret); 5911 5912 state = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED); 5913 ok(state == LVIS_FOCUSED, "got %x\n", state); 5914 5915 flush_sequences(sequences, NUM_MSG_SEQUENCES); 5916 5917 /* insert item 1, focus shift */ 5918 item.mask = LVIF_STATE; 5919 item.state = LVIS_FOCUSED; 5920 item.stateMask = LVIS_FOCUSED; 5921 item.iItem = 1; 5922 item.iSubItem = 0; 5923 ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 5924 ok(ret == 1, "got %d\n", ret); 5925 5926 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_insert_focused_seq, "insert focused", TRUE); 5927 5928 state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED); 5929 ok(state == LVIS_FOCUSED, "got %x\n", state); 5930 5931 /* insert item 2, no focus shift */ 5932 item.mask = LVIF_STATE; 5933 item.state = 0; 5934 item.stateMask = LVIS_FOCUSED; 5935 item.iItem = 2; 5936 item.iSubItem = 0; 5937 ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 5938 ok(ret == 2, "got %d\n", ret); 5939 5940 state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED); 5941 ok(state == LVIS_FOCUSED, "got %x\n", state); 5942 5943 DestroyWindow(hwnd); 5944 } 5945 5946 static void test_header_proc(void) 5947 { 5948 HWND hwnd, header, hdr; 5949 WNDPROC proc1, proc2; 5950 5951 hwnd = create_listview_control(LVS_REPORT); 5952 5953 header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0); 5954 ok(header != NULL, "got %p\n", header); 5955 5956 hdr = CreateWindowExA(0, WC_HEADERA, NULL, 5957 WS_BORDER|WS_VISIBLE|HDS_BUTTONS|HDS_HORZ, 5958 0, 0, 0, 0, 5959 NULL, NULL, NULL, NULL); 5960 ok(hdr != NULL, "got %p\n", hdr); 5961 5962 proc1 = (WNDPROC)GetWindowLongPtrW(header, GWLP_WNDPROC); 5963 proc2 = (WNDPROC)GetWindowLongPtrW(hdr, GWLP_WNDPROC); 5964 ok(proc1 == proc2, "got %p, expected %p\n", proc1, proc2); 5965 5966 DestroyWindow(hdr); 5967 DestroyWindow(hwnd); 5968 } 5969 5970 static void flush_events(void) 5971 { 5972 MSG msg; 5973 int diff = 200; 5974 int min_timeout = 100; 5975 DWORD time = GetTickCount() + diff; 5976 5977 while (diff > 0) 5978 { 5979 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break; 5980 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 5981 diff = time - GetTickCount(); 5982 } 5983 } 5984 5985 static void test_oneclickactivate(void) 5986 { 5987 TRACKMOUSEEVENT track; 5988 char item1[] = "item1"; 5989 LVITEMA item; 5990 HWND hwnd, fg; 5991 RECT rect; 5992 INT r; 5993 POINT orig_pos; 5994 5995 hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", WS_VISIBLE|WS_CHILD|LVS_LIST, 5996 10, 10, 100, 200, hwndparent, NULL, NULL, NULL); 5997 ok(hwnd != NULL, "failed to create listview window\n"); 5998 r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_ONECLICKACTIVATE); 5999 ok(r == 0, "should return zero\n"); 6000 6001 SetForegroundWindow(hwndparent); 6002 flush_events(); 6003 fg = GetForegroundWindow(); 6004 if (fg != hwndparent) 6005 { 6006 skip("Window is not in the foreground. Skipping oneclickactivate tests.\n"); 6007 DestroyWindow(hwnd); 6008 return; 6009 } 6010 6011 item.mask = LVIF_TEXT; 6012 item.iItem = 0; 6013 item.iSubItem = 0; 6014 item.iImage = 0; 6015 item.pszText = item1; 6016 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item); 6017 ok(r == 0, "should not fail\n"); 6018 6019 GetWindowRect(hwnd, &rect); 6020 GetCursorPos(&orig_pos); 6021 SetCursorPos(rect.left+5, rect.top+5); 6022 flush_events(); 6023 r = SendMessageA(hwnd, WM_MOUSEMOVE, MAKELONG(1, 1), 0); 6024 expect(0, r); 6025 6026 track.cbSize = sizeof(track); 6027 track.dwFlags = TME_QUERY; 6028 p_TrackMouseEvent(&track); 6029 ok(track.hwndTrack == hwnd, "hwndTrack != hwnd\n"); 6030 ok(track.dwFlags == TME_LEAVE, "dwFlags = %x\n", track.dwFlags); 6031 6032 r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 6033 expect(0, r); 6034 r = SendMessageA(hwnd, WM_MOUSEHOVER, MAKELONG(1, 1), 0); 6035 expect(0, r); 6036 r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0); 6037 expect(1, r); 6038 6039 DestroyWindow(hwnd); 6040 SetCursorPos(orig_pos.x, orig_pos.y); 6041 } 6042 6043 static void test_callback_mask(void) 6044 { 6045 LVITEMA item; 6046 DWORD mask; 6047 HWND hwnd; 6048 BOOL ret; 6049 6050 hwnd = create_listview_control(LVS_REPORT); 6051 6052 ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, ~0u, 0); 6053 ok(ret, "got %d\n", ret); 6054 6055 ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, ~0u, 1); 6056 ok(ret, "got %d\n", ret); 6057 6058 mask = SendMessageA(hwnd, LVM_GETCALLBACKMASK, 0, 0); 6059 ok(mask == ~0u, "got 0x%08x\n", mask); 6060 6061 DestroyWindow(hwnd); 6062 6063 /* LVS_OWNERDATA, mask LVIS_FOCUSED */ 6064 hwnd = create_listview_control(LVS_REPORT | LVS_OWNERDATA); 6065 6066 mask = SendMessageA(hwnd, LVM_GETCALLBACKMASK, 0, 0); 6067 ok(mask == 0, "Unexpected callback mask %#x.\n", mask); 6068 6069 ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_FOCUSED, 0); 6070 ok(ret, "Failed to set callback mask, %d\n", ret); 6071 6072 mask = SendMessageA(hwnd, LVM_GETCALLBACKMASK, 0, 0); 6073 ok(mask == LVIS_FOCUSED, "Unexpected callback mask %#x.\n", mask); 6074 6075 ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); 6076 ok(ret, "Failed to set item count.\n"); 6077 6078 ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 6079 ok(ret == -1, "Unexpected selection mark, %d\n", ret); 6080 6081 item.stateMask = LVIS_FOCUSED; 6082 item.state = LVIS_FOCUSED; 6083 ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 6084 ok(ret, "Failed to set item state.\n"); 6085 6086 flush_sequences(sequences, NUM_MSG_SEQUENCES); 6087 6088 ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 6089 todo_wine 6090 ok(ret == 0, "Unexpected focused item, ret %d\n", ret); 6091 6092 ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 6093 todo_wine 6094 ok(ret == 0, "Unexpected selection mark, %d\n", ret); 6095 6096 ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 0, 0); 6097 ok(ret, "Failed to set item count.\n"); 6098 6099 ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 6100 ok(ret == -1, "Unexpected focused item, ret %d\n", ret); 6101 6102 ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 6103 ok(ret == -1, "Unexpected selection mark, %d\n", ret); 6104 6105 ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); 6106 ok(ret, "Failed to set item count.\n"); 6107 6108 ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 6109 ok(ret == -1, "Unexpected focused item, ret %d\n", ret); 6110 6111 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "parent seq, owner data/focus 1", FALSE); 6112 6113 /* LVS_OWNDERDATA, empty mask */ 6114 ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, 0, 0); 6115 ok(ret, "Failed to set callback mask, %d\n", ret); 6116 6117 ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); 6118 ok(ret, "Failed to set item count.\n"); 6119 6120 ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 6121 ok(ret == -1, "Unexpected selection mark, %d\n", ret); 6122 6123 item.stateMask = LVIS_FOCUSED; 6124 item.state = LVIS_FOCUSED; 6125 ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 6126 ok(ret, "Failed to set item state.\n"); 6127 6128 ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 6129 ok(ret == 0, "Unexpected selection mark, %d\n", ret); 6130 6131 flush_sequences(sequences, NUM_MSG_SEQUENCES); 6132 6133 ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 6134 ok(ret == 0, "Unexpected focused item, ret %d\n", ret); 6135 6136 ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 0, 0); 6137 ok(ret, "Failed to set item count.\n"); 6138 6139 ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 6140 ok(ret == -1, "Unexpected focused item, ret %d\n", ret); 6141 6142 ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0); 6143 todo_wine 6144 ok(ret == -1, "Unexpected selection mark, %d\n", ret); 6145 6146 ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); 6147 ok(ret, "Failed to set item count.\n"); 6148 6149 ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 6150 ok(ret == -1, "Unexpected focused item, ret %d\n", ret); 6151 6152 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "parent seq, owner data/focus 2", FALSE); 6153 6154 /* 2 items, focus on index 0, reduce to 1 item. */ 6155 flush_sequences(sequences, NUM_MSG_SEQUENCES); 6156 6157 ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 2, 0); 6158 ok(ret, "Failed to set item count.\n"); 6159 6160 ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item); 6161 ok(ret, "Failed to set item state.\n"); 6162 6163 ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 6164 ok(ret == 0, "Unexpected focused item, ret %d\n", ret); 6165 6166 ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0); 6167 ok(ret, "Failed to set item count.\n"); 6168 6169 ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 6170 ok(ret == 0, "Unexpected focused item, ret %d\n", ret); 6171 6172 ok_sequence(sequences, PARENT_SEQ_INDEX, parent_focus_change_ownerdata_seq, 6173 "parent seq, owner data/focus 3", TRUE); 6174 6175 DestroyWindow(hwnd); 6176 } 6177 6178 static void test_state_image(void) 6179 { 6180 static const DWORD styles[] = 6181 { 6182 LVS_ICON, 6183 LVS_REPORT, 6184 LVS_SMALLICON, 6185 LVS_LIST, 6186 }; 6187 int i; 6188 6189 for (i = 0; i < sizeof(styles)/sizeof(styles[0]); i++) 6190 { 6191 static char text[] = "Item"; 6192 static char subtext[] = "Subitem"; 6193 char buff[16]; 6194 LVITEMA item; 6195 HWND hwnd; 6196 int r; 6197 6198 hwnd = create_listview_control(styles[i]); 6199 6200 insert_column(hwnd, 0); 6201 insert_column(hwnd, 1); 6202 6203 item.mask = LVIF_TEXT | LVIF_PARAM; 6204 item.iItem = 0; 6205 item.iSubItem = 0; 6206 item.pszText = text; 6207 item.lParam = 123456; 6208 r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item); 6209 ok(r == 0, "Failed to insert an item.\n"); 6210 6211 item.mask = LVIF_STATE; 6212 item.state = INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED | LVIS_FOCUSED; 6213 item.stateMask = LVIS_STATEIMAGEMASK | LVIS_SELECTED | LVIS_FOCUSED; 6214 item.iItem = 0; 6215 item.iSubItem = 0; 6216 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 6217 ok(r, "Failed to set item state.\n"); 6218 6219 item.mask = LVIF_TEXT; 6220 item.iItem = 0; 6221 item.iSubItem = 1; 6222 item.pszText = subtext; 6223 r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item); 6224 ok(r, "Failed to set subitem text.\n"); 6225 6226 item.mask = LVIF_STATE | LVIF_PARAM; 6227 item.stateMask = ~0u; 6228 item.state = 0; 6229 item.iItem = 0; 6230 item.iSubItem = 0; 6231 item.lParam = 0; 6232 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 6233 ok(r, "Failed to get item state.\n"); 6234 ok(item.state == (INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED | LVIS_FOCUSED), 6235 "Unexpected item state %#x.\n", item.state); 6236 ok(item.lParam == 123456, "Unexpected lParam %ld.\n", item.lParam); 6237 6238 item.mask = 0; 6239 item.stateMask = ~0u; 6240 item.state = INDEXTOSTATEIMAGEMASK(2); 6241 item.iItem = 0; 6242 item.iSubItem = 1; 6243 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 6244 ok(r, "Failed to get subitem state.\n"); 6245 ok(item.state == INDEXTOSTATEIMAGEMASK(2), "Unexpected state %#x.\n", item.state); 6246 6247 item.mask = LVIF_STATE | LVIF_PARAM; 6248 item.stateMask = ~0u; 6249 item.state = INDEXTOSTATEIMAGEMASK(2); 6250 item.iItem = 0; 6251 item.iSubItem = 1; 6252 item.lParam = 0; 6253 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 6254 ok(r, "Failed to get subitem state.\n"); 6255 ok(item.state == 0, "Unexpected state %#x.\n", item.state); 6256 ok(item.lParam == 123456, "Unexpected lParam %ld.\n", item.lParam); 6257 6258 item.mask = LVIF_STATE; 6259 item.stateMask = LVIS_FOCUSED; 6260 item.state = 0; 6261 item.iItem = 0; 6262 item.iSubItem = 1; 6263 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 6264 ok(r, "Failed to get subitem state.\n"); 6265 ok(item.state == 0, "Unexpected state %#x.\n", item.state); 6266 6267 item.mask = LVIF_STATE; 6268 item.stateMask = ~0u; 6269 item.state = INDEXTOSTATEIMAGEMASK(2); 6270 item.iItem = 0; 6271 item.iSubItem = 2; 6272 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 6273 ok(r, "Failed to get subitem state.\n"); 6274 todo_wine 6275 ok(item.state == 0, "Unexpected state %#x.\n", item.state); 6276 6277 item.mask = LVIF_TEXT; 6278 item.iItem = 0; 6279 item.iSubItem = 1; 6280 item.pszText = buff; 6281 item.cchTextMax = sizeof(buff); 6282 r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item); 6283 ok(r, "Failed to get subitem text %d.\n", r); 6284 ok(!strcmp(buff, subtext), "Unexpected subitem text %s.\n", buff); 6285 6286 DestroyWindow(hwnd); 6287 } 6288 } 6289 6290 static void test_LVSCW_AUTOSIZE(void) 6291 { 6292 int width, width2; 6293 HWND hwnd; 6294 BOOL ret; 6295 6296 hwnd = create_listview_control(LVS_REPORT); 6297 ok(hwnd != NULL, "failed to create a listview window\n"); 6298 6299 insert_column(hwnd, 0); 6300 insert_column(hwnd, 1); 6301 insert_item(hwnd, 0); 6302 6303 ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE); 6304 ok(ret, "Failed to set column width.\n"); 6305 6306 width = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); 6307 ok(width > 0, "Unexpected column width %d.\n", width); 6308 6309 /* Turn on checkboxes. */ 6310 ret = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); 6311 ok(ret == 0, "Unexpected previous extended style.\n"); 6312 6313 ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE); 6314 ok(ret, "Failed to set column width.\n"); 6315 6316 width2 = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); 6317 ok(width2 > 0, "Unexpected column width %d.\n", width2); 6318 ok(width2 > width, "Expected increased column width.\n"); 6319 6320 /* Turn off checkboxes. */ 6321 ret = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0); 6322 ok(ret == LVS_EX_CHECKBOXES, "Unexpected previous extended style.\n"); 6323 6324 ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE); 6325 ok(ret, "Failed to set column width.\n"); 6326 6327 width = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0); 6328 ok(width > 0, "Unexpected column width %d.\n", width2); 6329 ok(width2 > width, "Expected reduced column width.\n"); 6330 6331 DestroyWindow(hwnd); 6332 } 6333 6334 START_TEST(listview) 6335 { 6336 ULONG_PTR ctx_cookie; 6337 HANDLE hCtx; 6338 6339 init_functions(); 6340 6341 init_msg_sequences(sequences, NUM_MSG_SEQUENCES); 6342 6343 hwndparent = create_parent_window(FALSE); 6344 flush_sequences(sequences, NUM_MSG_SEQUENCES); 6345 6346 g_is_below_5 = is_below_comctl_5(); 6347 6348 test_header_notification(); 6349 test_header_notification2(); 6350 test_images(); 6351 test_checkboxes(); 6352 test_items(); 6353 test_create(FALSE); 6354 test_redraw(); 6355 test_customdraw(); 6356 test_icon_spacing(); 6357 test_color(); 6358 test_item_count(); 6359 test_item_position(); 6360 test_columns(); 6361 test_getorigin(); 6362 test_multiselect(); 6363 test_getitemrect(); 6364 test_subitem_rect(); 6365 test_sorting(); 6366 test_ownerdata(); 6367 test_norecompute(); 6368 test_nosortheader(); 6369 test_setredraw(); 6370 test_hittest(); 6371 test_getviewrect(); 6372 test_getitemposition(); 6373 test_columnscreation(); 6374 test_editbox(); 6375 test_notifyformat(); 6376 test_indentation(); 6377 test_getitemspacing(); 6378 test_getcolumnwidth(); 6379 test_approximate_viewrect(); 6380 test_finditem(); 6381 test_hover(); 6382 test_destroynotify(); 6383 test_createdragimage(); 6384 test_dispinfo(); 6385 test_LVM_SETITEMTEXT(); 6386 test_LVM_REDRAWITEMS(); 6387 test_imagelists(); 6388 test_deleteitem(); 6389 test_insertitem(); 6390 test_header_proc(); 6391 test_oneclickactivate(); 6392 test_callback_mask(); 6393 test_state_image(); 6394 test_LVSCW_AUTOSIZE(); 6395 6396 if (!load_v6_module(&ctx_cookie, &hCtx)) 6397 { 6398 DestroyWindow(hwndparent); 6399 return; 6400 } 6401 6402 init_functions(); 6403 6404 /* comctl32 version 6 tests start here */ 6405 test_get_set_view(); 6406 test_canceleditlabel(); 6407 test_mapidindex(); 6408 test_scrollnotify(); 6409 test_LVS_EX_TRANSPARENTBKGND(); 6410 test_LVS_EX_HEADERINALLVIEWS(); 6411 test_deleteitem(); 6412 test_multiselect(); 6413 test_insertitem(); 6414 test_header_proc(); 6415 test_images(); 6416 test_checkboxes(); 6417 test_items(); 6418 test_create(TRUE); 6419 test_color(); 6420 test_columns(); 6421 test_sorting(); 6422 test_ownerdata(); 6423 test_norecompute(); 6424 test_nosortheader(); 6425 test_columnscreation(); 6426 test_indentation(); 6427 test_finditem(); 6428 test_hover(); 6429 test_destroynotify(); 6430 test_createdragimage(); 6431 test_dispinfo(); 6432 test_LVM_SETITEMTEXT(); 6433 test_LVM_REDRAWITEMS(); 6434 test_oneclickactivate(); 6435 test_state_image(); 6436 test_LVSCW_AUTOSIZE(); 6437 6438 unload_v6_module(ctx_cookie, hCtx); 6439 6440 DestroyWindow(hwndparent); 6441 } 6442