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