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