4 * Copyright 2006 Mike McCormack for CodeWeavers
5 * Copyright 2007 George Gov
6 * Copyright 2009-2014 Nikolay Sivov
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.
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.
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
28 #include "wine/test.h"
32 static HIMAGELIST (WINAPI
*pImageList_Create
)(int, int, UINT
, int, int);
33 static BOOL (WINAPI
*pImageList_Destroy
)(HIMAGELIST
);
34 static int (WINAPI
*pImageList_Add
)(HIMAGELIST
, HBITMAP
, HBITMAP
);
35 static BOOL (WINAPI
*p_TrackMouseEvent
)(TRACKMOUSEEVENT
*);
39 PARENT_FULL_SEQ_INDEX
,
41 PARENT_ODSTATECHANGED_SEQ_INDEX
,
51 #define expect(expected,got) expect_(__LINE__, expected, got)
52 static inline void expect_(unsigned line
, DWORD expected
, DWORD got
)
54 ok_(__FILE__
, line
)(expected
== got
, "Expected %ld, got %ld\n", expected
, got
);
57 #define expect2(expected1, expected2, got1, got2) expect2_(__LINE__, expected1, expected2, got1, got2)
58 static inline void expect2_(unsigned line
, DWORD expected1
, DWORD expected2
, DWORD got1
, DWORD got2
)
60 ok_(__FILE__
, line
)(expected1
== got1
&& expected2
== got2
,
61 "expected (%ld,%ld), got (%ld,%ld)\n",
62 expected1
, expected2
, got1
, got2
);
65 static HWND hwndparent
, hwndparentW
;
66 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
67 static BOOL blockEdit
;
68 /* return nonzero on NM_HOVER */
69 static BOOL g_block_hover
;
70 /* notification data for LVN_ITEMCHANGED */
71 static NMLISTVIEW g_nmlistview
;
72 /* notification data for LVN_ITEMCHANGING */
73 static NMLISTVIEW g_nmlistview_changing
;
74 /* format reported to control:
75 -1 falls to defproc, anything else returned */
76 static INT notifyFormat
;
77 /* item data passed to LVN_GETDISPINFOA */
78 static LVITEMA g_itema
;
79 /* alter notification code A->W */
80 static BOOL g_disp_A_to_W
;
81 /* dispinfo data sent with LVN_LVN_ENDLABELEDIT */
82 static NMLVDISPINFOA g_editbox_disp_info
;
83 /* when this is set focus will be tested on LVN_DELETEITEM */
84 static BOOL g_focus_test_LVN_DELETEITEM
;
85 /* Whether to send WM_KILLFOCUS to the edit control during LVN_ENDLABELEDIT */
86 static BOOL g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT
;
88 static HWND
subclass_editbox(HWND hwndListview
);
90 static void init_functions(void)
92 HMODULE hComCtl32
= LoadLibraryA("comctl32.dll");
94 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
102 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
104 static const struct message create_ownerdrawfixed_parent_seq
[] = {
105 { WM_NOTIFYFORMAT
, sent
},
106 { WM_QUERYUISTATE
, sent
|optional
}, /* Win2K and higher */
107 { WM_MEASUREITEM
, sent
},
108 { WM_PARENTNOTIFY
, sent
},
112 static const struct message redraw_listview_seq
[] = {
113 { WM_PAINT
, sent
|id
, 0, 0, LISTVIEW_ID
},
114 { WM_PAINT
, sent
|id
, 0, 0, HEADER_ID
},
115 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
116 { WM_ERASEBKGND
, sent
|id
|defwinproc
|optional
, 0, 0, HEADER_ID
},
117 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
118 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
119 { WM_ERASEBKGND
, sent
|id
|defwinproc
|optional
, 0, 0, LISTVIEW_ID
},
123 static const struct message listview_icon_spacing_seq
[] = {
124 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(20, 30) },
125 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(25, 35) },
126 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(-1, -1) },
130 static const struct message listview_color_seq
[] = {
131 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
132 { LVM_GETBKCOLOR
, sent
},
133 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
134 { LVM_GETTEXTCOLOR
, sent
},
135 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
136 { LVM_GETTEXTBKCOLOR
, sent
},
138 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
139 { LVM_GETBKCOLOR
, sent
},
140 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
141 { LVM_GETTEXTCOLOR
, sent
},
142 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
143 { LVM_GETTEXTBKCOLOR
, sent
},
145 { LVM_SETBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
146 { LVM_GETBKCOLOR
, sent
},
147 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, CLR_NONE
},
148 { LVM_GETTEXTCOLOR
, sent
},
149 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
150 { LVM_GETTEXTBKCOLOR
, sent
},
152 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
153 { LVM_GETBKCOLOR
, sent
},
154 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
155 { LVM_GETTEXTCOLOR
, sent
},
156 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
157 { LVM_GETTEXTBKCOLOR
, sent
},
161 static const struct message listview_item_count_seq
[] = {
162 { LVM_GETITEMCOUNT
, sent
},
163 { LVM_INSERTITEMA
, sent
},
164 { LVM_INSERTITEMA
, sent
},
165 { LVM_INSERTITEMA
, sent
},
166 { LVM_GETITEMCOUNT
, sent
},
167 { LVM_DELETEITEM
, sent
|wparam
, 2 },
168 { WM_NCPAINT
, sent
|optional
},
169 { WM_ERASEBKGND
, sent
|optional
},
170 { LVM_GETITEMCOUNT
, sent
},
171 { LVM_DELETEALLITEMS
, sent
},
172 { LVM_GETITEMCOUNT
, sent
},
173 { LVM_INSERTITEMA
, sent
},
174 { LVM_INSERTITEMA
, sent
},
175 { LVM_GETITEMCOUNT
, sent
},
176 { LVM_INSERTITEMA
, sent
},
177 { LVM_GETITEMCOUNT
, sent
},
181 static const struct message listview_itempos_seq
[] = {
182 { LVM_INSERTITEMA
, sent
},
183 { LVM_INSERTITEMA
, sent
},
184 { LVM_INSERTITEMA
, sent
},
185 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 1, MAKELPARAM(10,5) },
186 { WM_NCPAINT
, sent
|optional
},
187 { WM_ERASEBKGND
, sent
|optional
},
188 { LVM_GETITEMPOSITION
, sent
|wparam
, 1 },
189 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 2, MAKELPARAM(0,0) },
190 { LVM_GETITEMPOSITION
, sent
|wparam
, 2 },
191 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 0, MAKELPARAM(20,20) },
192 { LVM_GETITEMPOSITION
, sent
|wparam
, 0 },
196 static const struct message listview_ownerdata_switchto_seq
[] = {
197 { WM_STYLECHANGING
, sent
},
198 { WM_STYLECHANGED
, sent
},
202 static const struct message listview_getorderarray_seq
[] = {
203 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
204 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
205 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 0, 0, LISTVIEW_ID
},
206 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 0, 0, HEADER_ID
},
210 static const struct message listview_setorderarray_seq
[] = {
211 { LVM_SETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
212 { HDM_SETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
213 { LVM_SETCOLUMNORDERARRAY
, sent
|id
|wparam
, 0, 0, LISTVIEW_ID
},
214 { HDM_SETORDERARRAY
, sent
|id
|wparam
, 0, 0, HEADER_ID
},
218 static const struct message empty_seq
[] = {
222 static const struct message parent_focus_change_ownerdata_seq
[] = {
223 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
224 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
228 static const struct message forward_erasebkgnd_parent_seq
[] = {
229 { WM_ERASEBKGND
, sent
},
233 static const struct message ownerdata_select_focus_parent_seq
[] = {
234 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
235 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
236 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, LVN_GETDISPINFOA
}, /* version 4.7x */
240 static const struct message ownerdata_setstate_all_parent_seq
[] = {
241 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
245 static const struct message ownerdata_defocus_all_parent_seq
[] = {
246 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
247 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
248 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, LVN_GETDISPINFOA
},
249 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
253 static const struct message ownerdata_deselect_all_parent_seq
[] = {
254 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODCACHEHINT
},
255 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
259 static const struct message ownerdata_multiselect_select_0_to_1_odstatechanged_seq
[] = {
260 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
261 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODSTATECHANGED
},
262 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
263 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
267 static const struct message ownerdata_multiselect_select_0_odstatechanged_seq
[] = {
268 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
269 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
270 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
274 static const struct message ownerdata_multiselect_select_0_modkey_odstatechanged_seq
[] = {
275 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
276 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
277 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
278 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
282 static const struct message ownerdata_multiselect_move_0_to_1_odstatechanged_seq
[] = {
283 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
284 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
288 static const struct message ownerdata_multiselect_select_0_to_2_odstatechanged_seq
[] = {
289 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
290 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODSTATECHANGED
},
291 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
292 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
296 static const struct message ownerdata_multiselect_select_3_odstatechanged_seq
[] = {
297 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
298 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
299 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
303 static const struct message ownerdata_multiselect_select_3_modkey_odstatechanged_seq
[] = {
304 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
305 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
306 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
307 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
311 static const struct message ownerdata_multiselect_select_3_to_2_odstatechanged_seq
[] = {
312 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
313 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODSTATECHANGED
},
314 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
315 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
319 static const struct message ownerdata_multiselect_move_3_to_2_odstatechanged_seq
[] = {
320 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
321 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
325 static const struct message ownerdata_multiselect_select_3_to_1_odstatechanged_seq
[] = {
326 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
327 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODSTATECHANGED
},
328 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
329 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
333 static const struct message change_all_parent_seq
[] = {
334 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
335 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
337 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
338 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
340 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
341 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
343 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
344 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
346 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
347 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
351 static const struct message changing_all_parent_seq
[] = {
352 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
353 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
354 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
355 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
356 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
360 static const struct message textcallback_set_again_parent_seq
[] = {
361 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
362 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
366 static const struct message single_getdispinfo_parent_seq
[] = {
367 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
371 static const struct message getitemposition_seq1
[] = {
372 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
376 static const struct message getitemposition_seq2
[] = {
377 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
378 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
382 static const struct message getsubitemrect_seq
[] = {
383 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, -1, 0, LISTVIEW_ID
},
384 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
385 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, 0, 0, LISTVIEW_ID
},
386 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
387 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, -10, 0, LISTVIEW_ID
},
388 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
389 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, 20, 0, LISTVIEW_ID
},
390 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
394 static const struct message editbox_create_pos
[] = {
395 /* sequence sent after LVN_BEGINLABELEDIT */
396 /* next two are 4.7x specific */
397 { WM_WINDOWPOSCHANGING
, sent
},
398 { WM_WINDOWPOSCHANGED
, sent
|optional
},
400 { WM_WINDOWPOSCHANGING
, sent
|optional
},
401 { WM_NCCALCSIZE
, sent
},
402 { WM_WINDOWPOSCHANGED
, sent
},
403 { WM_MOVE
, sent
|defwinproc
},
404 { WM_SIZE
, sent
|defwinproc
},
405 /* the rest is todo, skipped in 4.7x */
406 { WM_WINDOWPOSCHANGING
, sent
|optional
},
407 { WM_WINDOWPOSCHANGED
, sent
|optional
},
411 static const struct message scroll_parent_seq
[] = {
412 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_BEGINSCROLL
},
413 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDSCROLL
},
417 static const struct message setredraw_seq
[] = {
418 { WM_SETREDRAW
, sent
|id
|wparam
, FALSE
, 0, LISTVIEW_ID
},
422 static const struct message lvs_ex_transparentbkgnd_seq
[] = {
423 { WM_PRINTCLIENT
, sent
|lparam
, 0, PRF_ERASEBKGND
},
427 static const struct message edit_end_nochange
[] = {
428 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDLABELEDITA
},
429 { WM_NOTIFY
, sent
|id
, 0, 0, NM_CUSTOMDRAW
}, /* todo */
430 { WM_NOTIFY
, sent
|id
, 0, 0, NM_SETFOCUS
},
434 static const struct message hover_parent
[] = {
435 { WM_GETDLGCODE
, sent
}, /* todo_wine */
436 { WM_NOTIFY
, sent
|id
, 0, 0, NM_HOVER
},
440 static const struct message listview_destroy
[] = {
441 { 0x0090, sent
|optional
}, /* Vista */
442 { WM_PARENTNOTIFY
, sent
},
443 { WM_SHOWWINDOW
, sent
},
444 { WM_WINDOWPOSCHANGING
, sent
},
445 { WM_WINDOWPOSCHANGED
, sent
|optional
},
446 { WM_DESTROY
, sent
},
447 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_DELETEALLITEMS
},
448 { WM_NCDESTROY
, sent
},
452 static const struct message listview_ownerdata_destroy
[] = {
453 { 0x0090, sent
|optional
}, /* Vista */
454 { WM_PARENTNOTIFY
, sent
},
455 { WM_SHOWWINDOW
, sent
},
456 { WM_WINDOWPOSCHANGING
, sent
},
457 { WM_WINDOWPOSCHANGED
, sent
|optional
},
458 { WM_DESTROY
, sent
},
459 { WM_NCDESTROY
, sent
},
463 static const struct message listview_ownerdata_deleteall
[] = {
464 { LVM_DELETEALLITEMS
, sent
},
465 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_DELETEALLITEMS
},
469 static const struct message listview_header_changed_seq
[] = {
470 { LVM_SETCOLUMNA
, sent
},
471 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
472 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
476 static const struct message parent_header_click_seq
[] = {
477 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_COLUMNCLICK
},
478 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_ITEMCLICKA
},
482 static const struct message parent_header_divider_dclick_seq
[] = {
483 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_ITEMCHANGINGA
},
484 { WM_NOTIFY
, sent
|id
, 0, 0, NM_CUSTOMDRAW
},
485 { WM_NOTIFY
, sent
|id
, 0, 0, NM_CUSTOMDRAW
},
486 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_ITEMCHANGEDA
},
487 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_DIVIDERDBLCLICKA
},
491 static const struct message listview_set_imagelist
[] = {
492 { LVM_SETIMAGELIST
, sent
|id
, 0, 0, LISTVIEW_ID
},
496 static const struct message listview_header_set_imagelist
[] = {
497 { LVM_SETIMAGELIST
, sent
|id
, 0, 0, LISTVIEW_ID
},
498 { HDM_SETIMAGELIST
, sent
|id
, 0, 0, HEADER_ID
},
502 static const struct message parent_report_cd_seq
[] = {
503 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_PREPAINT
},
504 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
},
505 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
|CDDS_SUBITEM
},
506 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
|CDDS_SUBITEM
},
507 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
|CDDS_SUBITEM
},
508 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
|CDDS_SUBITEM
},
509 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
},
510 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_POSTPAINT
},
514 static const struct message parent_list_cd_seq
[] = {
515 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_PREPAINT
},
516 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
},
517 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
},
518 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_POSTPAINT
},
522 static const struct message listview_end_label_edit
[] = {
523 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDLABELEDITA
},
524 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
525 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
526 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, NM_CUSTOMDRAW
}, /* XP */
527 { WM_NOTIFY
, sent
|id
, 0, 0, NM_SETFOCUS
},
531 static const struct message listview_end_label_edit_kill_focus
[] = {
532 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDLABELEDITA
},
533 { WM_COMMAND
, sent
|id
|optional
, 0, 0, EN_KILLFOCUS
}, /* todo: not sent by wine yet */
534 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
535 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
536 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, NM_CUSTOMDRAW
}, /* XP */
537 { WM_NOTIFY
, sent
|id
, 0, 0, NM_SETFOCUS
},
541 static void hold_key(int vk
)
546 res
= GetKeyboardState(kstate
);
547 ok(res
, "GetKeyboardState failed.\n");
549 res
= SetKeyboardState(kstate
);
550 ok(res
, "SetKeyboardState failed.\n");
553 static void release_key(int vk
)
558 res
= GetKeyboardState(kstate
);
559 ok(res
, "GetKeyboardState failed.\n");
561 res
= SetKeyboardState(kstate
);
562 ok(res
, "SetKeyboardState failed.\n");
565 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
567 static LONG defwndproc_counter
= 0;
571 msg
.message
= message
;
572 msg
.flags
= sent
|wparam
|lparam
;
573 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
576 if (message
== WM_NOTIFY
&& lParam
)
578 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
580 msg
.id
= nmlv
->hdr
.code
;
581 if (msg
.id
== LVN_ITEMCHANGING
|| msg
.id
== LVN_ITEMCHANGED
)
583 msg
.wParam
= nmlv
->iItem
;
584 msg
.lParam
= nmlv
->uChanged
;
587 if (message
== WM_COMMAND
) msg
.id
= HIWORD(wParam
);
589 /* log system messages, except for painting */
590 if (message
< WM_USER
&&
591 message
!= WM_PAINT
&&
592 message
!= WM_ERASEBKGND
&&
593 message
!= WM_NCPAINT
&&
594 message
!= WM_NCHITTEST
&&
595 message
!= WM_GETTEXT
&&
596 message
!= WM_GETICON
&&
597 message
!= WM_DEVICECHANGE
)
599 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
600 add_message(sequences
, COMBINED_SEQ_INDEX
, &msg
);
602 /* log change messages for single and multiple items changing in ownerdata listviews */
603 if (message
== WM_NOTIFY
&& (msg
.id
== LVN_ITEMCHANGED
|| msg
.id
== LVN_ODSTATECHANGED
))
604 add_message(sequences
, PARENT_ODSTATECHANGED_SEQ_INDEX
, &msg
);
606 add_message(sequences
, PARENT_FULL_SEQ_INDEX
, &msg
);
612 switch (((NMHDR
*)lParam
)->code
)
614 case LVN_BEGINLABELEDITA
:
618 /* subclass edit box */
620 edit
= subclass_editbox(((NMHDR
*)lParam
)->hwndFrom
);
624 INT len
= SendMessageA(edit
, EM_GETLIMITTEXT
, 0, 0);
625 ok(len
== 259 || broken(len
== 260) /* includes NULL in NT4 */,
626 "text limit %d, expected 259\n", len
);
631 case LVN_ENDLABELEDITA
:
635 /* always accept new item text */
636 NMLVDISPINFOA
*di
= (NMLVDISPINFOA
*)lParam
;
637 g_editbox_disp_info
= *di
;
639 /* edit control still available from this notification */
640 edit
= (HWND
)SendMessageA(((NMHDR
*)lParam
)->hwndFrom
, LVM_GETEDITCONTROL
, 0, 0);
641 ok(IsWindow(edit
), "expected valid edit control handle\n");
642 ok((GetWindowLongA(edit
, GWL_STYLE
) & ES_MULTILINE
) == 0, "edit is multiline\n");
644 if (g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT
)
645 SendMessageA(edit
, WM_KILLFOCUS
, 0, 0);
649 case LVN_ITEMCHANGING
:
651 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
652 g_nmlistview_changing
= *nmlv
;
655 case LVN_ITEMCHANGED
:
657 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
658 g_nmlistview
= *nmlv
;
661 case LVN_GETDISPINFOA
:
663 NMLVDISPINFOA
*dispinfo
= (NMLVDISPINFOA
*)lParam
;
664 g_itema
= dispinfo
->item
;
666 if (g_disp_A_to_W
&& (dispinfo
->item
.mask
& LVIF_TEXT
))
668 dispinfo
->hdr
.code
= LVN_GETDISPINFOW
;
669 lstrcpyW((WCHAR
*)dispinfo
->item
.pszText
, L
"TEST");
672 /* test control buffer size for text, 10 used to mask cases when control
673 is using caller buffer to process LVM_GETITEM for example */
674 if (dispinfo
->item
.mask
& LVIF_TEXT
&& dispinfo
->item
.cchTextMax
> 10)
675 ok(dispinfo
->item
.cchTextMax
== 260 ||
676 broken(dispinfo
->item
.cchTextMax
== 264) /* NT4 reports aligned size */,
677 "buffer size %d\n", dispinfo
->item
.cchTextMax
);
681 if (g_focus_test_LVN_DELETEITEM
)
683 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
686 state
= SendMessageA(((NMHDR
*)lParam
)->hwndFrom
, LVM_GETITEMSTATE
, nmlv
->iItem
, LVIS_FOCUSED
);
687 ok(state
== 0, "got state %x\n", state
);
691 if (g_block_hover
) return 1;
696 case WM_NOTIFYFORMAT
:
698 /* force to return format */
699 if (lParam
== NF_QUERY
&& notifyFormat
!= -1) return notifyFormat
;
704 defwndproc_counter
++;
705 if (IsWindowUnicode(hwnd
))
706 ret
= DefWindowProcW(hwnd
, message
, wParam
, lParam
);
708 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
709 defwndproc_counter
--;
714 static BOOL
register_parent_wnd_class(BOOL Unicode
)
722 clsW
.lpfnWndProc
= parent_wnd_proc
;
725 clsW
.hInstance
= GetModuleHandleW(NULL
);
727 clsW
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
728 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
729 clsW
.lpszMenuName
= NULL
;
730 clsW
.lpszClassName
= L
"Listview test parentW";
735 clsA
.lpfnWndProc
= parent_wnd_proc
;
738 clsA
.hInstance
= GetModuleHandleA(NULL
);
740 clsA
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
741 clsA
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
742 clsA
.lpszMenuName
= NULL
;
743 clsA
.lpszClassName
= "Listview test parent class";
746 return Unicode
? RegisterClassW(&clsW
) : RegisterClassA(&clsA
);
749 static HWND
create_parent_window(BOOL Unicode
)
753 if (!register_parent_wnd_class(Unicode
))
760 hwnd
= CreateWindowExW(0, L
"Listview test parentW", L
"testparentnameW",
761 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
762 WS_MAXIMIZEBOX
| WS_VISIBLE
,
764 GetDesktopWindow(), NULL
, GetModuleHandleW(NULL
), NULL
);
766 hwnd
= CreateWindowExA(0, "Listview test parent class",
767 "Listview test parent window",
768 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
769 WS_MAXIMIZEBOX
| WS_VISIBLE
,
771 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
772 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
776 static LRESULT WINAPI
listview_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
778 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
779 static LONG defwndproc_counter
= 0;
783 msg
.message
= message
;
784 msg
.flags
= sent
|wparam
|lparam
;
785 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
788 msg
.id
= LISTVIEW_ID
;
789 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
790 add_message(sequences
, COMBINED_SEQ_INDEX
, &msg
);
792 defwndproc_counter
++;
793 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
794 defwndproc_counter
--;
798 static HWND
create_listview_control(DWORD style
)
804 GetClientRect(hwndparent
, &rect
);
805 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo",
806 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
807 0, 0, rect
.right
, rect
.bottom
,
808 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
809 ok(hwnd
!= NULL
, "gle=%ld\n", GetLastError());
811 if (!hwnd
) return NULL
;
813 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
814 (LONG_PTR
)listview_subclass_proc
);
815 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
820 /* unicode listview window with specified parent */
821 static HWND
create_listview_controlW(DWORD style
, HWND parent
)
827 GetClientRect(parent
, &rect
);
828 hwnd
= CreateWindowExW(0, WC_LISTVIEWW
, L
"foo",
829 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
830 0, 0, rect
.right
, rect
.bottom
,
831 parent
, NULL
, GetModuleHandleW(NULL
), NULL
);
832 ok(hwnd
!= NULL
, "gle=%ld\n", GetLastError());
834 if (!hwnd
) return NULL
;
836 oldproc
= (WNDPROC
)SetWindowLongPtrW(hwnd
, GWLP_WNDPROC
,
837 (LONG_PTR
)listview_subclass_proc
);
838 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
844 static LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
846 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
847 static LONG defwndproc_counter
= 0;
848 struct message msg
= { 0 };
851 msg
.message
= message
;
852 msg
.flags
= sent
|wparam
|lparam
;
853 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
857 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
859 defwndproc_counter
++;
860 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
861 defwndproc_counter
--;
865 static HWND
subclass_header(HWND hwndListview
)
870 hwnd
= (HWND
)SendMessageA(hwndListview
, LVM_GETHEADER
, 0, 0);
871 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
872 (LONG_PTR
)header_subclass_proc
);
873 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
878 static LRESULT WINAPI
editbox_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
880 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
881 static LONG defwndproc_counter
= 0;
882 struct message msg
= { 0 };
885 msg
.message
= message
;
886 msg
.flags
= sent
|wparam
|lparam
;
887 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
891 /* all we need is sizing */
892 if (message
== WM_WINDOWPOSCHANGING
||
893 message
== WM_NCCALCSIZE
||
894 message
== WM_WINDOWPOSCHANGED
||
895 message
== WM_MOVE
||
898 add_message(sequences
, EDITBOX_SEQ_INDEX
, &msg
);
901 defwndproc_counter
++;
902 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
903 defwndproc_counter
--;
907 static HWND
subclass_editbox(HWND hwndListview
)
912 hwnd
= (HWND
)SendMessageA(hwndListview
, LVM_GETEDITCONTROL
, 0, 0);
913 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
914 (LONG_PTR
)editbox_subclass_proc
);
915 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
920 /* Performs a single LVM_HITTEST test */
921 static void test_lvm_hittest_(HWND hwnd
, INT x
, INT y
, INT item
, UINT flags
, UINT broken_flags
,
922 BOOL todo_item
, BOOL todo_flags
, int line
)
931 ret
= SendMessageA(hwnd
, LVM_HITTEST
, 0, (LPARAM
)&lpht
);
933 todo_wine_if(todo_item
)
935 ok_(__FILE__
, line
)(ret
== item
, "Expected %d retval, got %d\n", item
, ret
);
936 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
937 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
943 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags 0x%x, got 0x%x\n", flags
, lpht
.flags
);
945 else if (broken_flags
)
946 ok_(__FILE__
, line
)(lpht
.flags
== flags
|| broken(lpht
.flags
== broken_flags
),
947 "Expected flags %x, got %x\n", flags
, lpht
.flags
);
949 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags 0x%x, got 0x%x\n", flags
, lpht
.flags
);
952 #define test_lvm_hittest(a,b,c,d,e,f,g,h) test_lvm_hittest_(a,b,c,d,e,f,g,h,__LINE__)
954 /* Performs a single LVM_SUBITEMHITTEST test */
955 static void test_lvm_subitemhittest_(HWND hwnd
, INT x
, INT y
, INT item
, INT subitem
, UINT flags
,
956 BOOL todo_item
, BOOL todo_subitem
, BOOL todo_flags
, int line
)
964 ret
= SendMessageA(hwnd
, LVM_SUBITEMHITTEST
, 0, (LPARAM
)&lpht
);
966 todo_wine_if(todo_item
)
968 ok_(__FILE__
, line
)(ret
== item
, "Expected %d retval, got %d\n", item
, ret
);
969 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
972 todo_wine_if(todo_subitem
)
973 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
975 todo_wine_if(todo_flags
)
976 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags 0x%x, got 0x%x\n", flags
, lpht
.flags
);
979 #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__)
981 static void test_images(void)
989 static CHAR hello
[] = "hello";
991 himl
= pImageList_Create(40, 40, 0, 4, 4);
992 ok(himl
!= NULL
, "failed to create imagelist\n");
994 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
995 ok(hbmp
!= NULL
, "failed to create bitmap\n");
997 r
= pImageList_Add(himl
, hbmp
, 0);
998 ok(r
== 0, "should be zero\n");
1000 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_OWNERDRAWFIXED
,
1001 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1002 ok(hwnd
!= NULL
, "failed to create listview window\n");
1004 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0,
1005 LVS_EX_UNDERLINEHOT
| LVS_EX_FLATSB
| LVS_EX_ONECLICKACTIVATE
);
1007 ok(r
== 0, "should return zero\n");
1009 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
1010 ok(r
== 0, "should return zero\n");
1012 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELONG(100,50));
1013 ok(r
!= 0, "got 0\n");
1015 /* returns dimensions */
1017 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1018 ok(r
== 0, "should be zero items\n");
1020 item
.mask
= LVIF_IMAGE
| LVIF_TEXT
;
1025 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1026 ok(r
== -1, "should fail\n");
1029 item
.pszText
= hello
;
1030 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1031 ok(r
== 0, "should not fail\n");
1033 SetRect(&r1
, LVIR_ICON
, 0, 0, 0);
1034 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r1
);
1037 r
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1038 ok(r
== TRUE
, "should not fail\n");
1041 item
.pszText
= hello
;
1042 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1043 ok(r
== 0, "should not fail\n");
1045 SetRect(&r2
, LVIR_ICON
, 0, 0, 0);
1046 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r2
);
1049 ok(EqualRect(&r1
, &r2
), "rectangle should be the same\n");
1051 DestroyWindow(hwnd
);
1053 /* I_IMAGECALLBACK set for item, try to get image with invalid subitem. */
1054 hwnd
= create_listview_control(LVS_REPORT
);
1055 ok(hwnd
!= NULL
, "Failed to create listview.\n");
1057 memset(&item
, 0, sizeof(item
));
1058 item
.mask
= LVIF_IMAGE
;
1059 item
.iImage
= I_IMAGECALLBACK
;
1060 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
1061 ok(!r
, "Failed to insert item.\n");
1063 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1065 memset(&item
, 0, sizeof(item
));
1066 item
.mask
= LVIF_IMAGE
;
1067 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
1068 ok(r
, "Failed to get item.\n");
1070 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
, "get image dispinfo 1", FALSE
);
1072 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1074 memset(&item
, 0, sizeof(item
));
1075 item
.mask
= LVIF_IMAGE
;
1077 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
1078 ok(r
, "Failed to get item.\n");
1080 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "get image dispinfo 2", FALSE
);
1082 DestroyWindow(hwnd
);
1085 static void test_checkboxes(void)
1090 static CHAR text
[] = "Text",
1094 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_REPORT
,
1095 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1096 ok(hwnd
!= NULL
, "failed to create listview window\n");
1098 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
1099 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
1100 item
.stateMask
= 0xffff;
1101 item
.state
= 0xfccc;
1104 item
.pszText
= text
;
1105 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1109 item
.mask
= LVIF_STATE
;
1110 item
.stateMask
= 0xffff;
1111 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1113 ok(item
.state
== 0xfccc, "state %x\n", item
.state
);
1115 /* Don't set LVIF_STATE */
1116 item
.mask
= LVIF_TEXT
;
1117 item
.stateMask
= 0xffff;
1118 item
.state
= 0xfccc;
1121 item
.pszText
= text
;
1122 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1126 item
.mask
= LVIF_STATE
;
1127 item
.stateMask
= 0xffff;
1128 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1130 ok(item
.state
== 0, "state %x\n", item
.state
);
1132 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
1135 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
1137 item
.mask
= LVIF_STATE
;
1138 item
.stateMask
= 0xffff;
1139 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1142 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
1144 item
.mask
= LVIF_TEXT
;
1146 item
.pszText
= text2
;
1147 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1151 item
.mask
= LVIF_STATE
;
1152 item
.stateMask
= 0xffff;
1153 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1155 ok(item
.state
== 0x1000, "state %x\n", item
.state
);
1157 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
1159 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
1160 item
.stateMask
= 0xffff;
1161 item
.state
= 0x2aaa;
1162 item
.pszText
= text3
;
1163 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1167 item
.mask
= LVIF_STATE
;
1168 item
.stateMask
= 0xffff;
1169 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1171 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
1173 /* Set an item's state to checked */
1175 item
.mask
= LVIF_STATE
;
1176 item
.stateMask
= 0xf000;
1177 item
.state
= 0x2000;
1178 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1182 item
.mask
= LVIF_STATE
;
1183 item
.stateMask
= 0xffff;
1184 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1186 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
1188 /* Check that only the bits we asked for are returned,
1189 * and that all the others are set to zero
1192 item
.mask
= LVIF_STATE
;
1193 item
.stateMask
= 0xf000;
1194 item
.state
= 0xffff;
1195 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1197 ok(item
.state
== 0x2000, "state %x\n", item
.state
);
1199 /* Set the style again and check that doesn't change an item's state */
1200 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
1201 ok(r
== LVS_EX_CHECKBOXES
, "ret %lx\n", r
);
1204 item
.mask
= LVIF_STATE
;
1205 item
.stateMask
= 0xffff;
1206 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1208 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
1210 /* Unsetting the checkbox extended style doesn't change an item's state */
1211 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
1212 ok(r
== LVS_EX_CHECKBOXES
, "ret %lx\n", r
);
1215 item
.mask
= LVIF_STATE
;
1216 item
.stateMask
= 0xffff;
1217 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1219 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
1221 /* Now setting the style again will change an item's state */
1222 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
1226 item
.mask
= LVIF_STATE
;
1227 item
.stateMask
= 0xffff;
1228 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1230 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
1232 /* Toggle checkbox tests (bug 9934) */
1233 memset (&item
, 0xcc, sizeof(item
));
1234 item
.mask
= LVIF_STATE
;
1237 item
.state
= LVIS_FOCUSED
;
1238 item
.stateMask
= LVIS_FOCUSED
;
1239 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1243 item
.mask
= LVIF_STATE
;
1244 item
.stateMask
= 0xffff;
1245 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1247 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
1249 r
= SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
1251 r
= SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
1255 item
.mask
= LVIF_STATE
;
1256 item
.stateMask
= 0xffff;
1257 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1259 ok(item
.state
== 0x2aab, "state %x\n", item
.state
);
1261 r
= SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
1263 r
= SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
1267 item
.mask
= LVIF_STATE
;
1268 item
.stateMask
= 0xffff;
1269 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1271 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
1273 DestroyWindow(hwnd
);
1276 static void insert_column(HWND hwnd
, int idx
)
1281 memset(&column
, 0xcc, sizeof(column
));
1282 column
.mask
= LVCF_SUBITEM
;
1283 column
.iSubItem
= idx
;
1285 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, idx
, (LPARAM
)&column
);
1289 static void insert_item(HWND hwnd
, int idx
)
1291 static CHAR text
[] = "foo";
1296 memset(&item
, 0xcc, sizeof (item
));
1297 item
.mask
= LVIF_TEXT
;
1300 item
.pszText
= text
;
1302 rc
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
1306 static void test_items(void)
1308 const LPARAM lparamTest
= 0x42;
1309 static CHAR text
[] = "Text";
1315 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_REPORT
,
1316 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1317 ok(hwnd
!= NULL
, "failed to create listview window\n");
1320 * Test setting/getting item params
1323 /* Set up two columns */
1324 insert_column(hwnd
, 0);
1325 insert_column(hwnd
, 1);
1327 /* LVIS_SELECTED with zero stateMask */
1329 memset (&item
, 0, sizeof (item
));
1330 item
.mask
= LVIF_STATE
;
1331 item
.state
= LVIS_SELECTED
;
1335 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1338 memset (&item
, 0xcc, sizeof (item
));
1339 item
.mask
= LVIF_STATE
;
1340 item
.stateMask
= LVIS_SELECTED
;
1344 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1346 ok(item
.state
& LVIS_SELECTED
, "Expected LVIS_SELECTED\n");
1347 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
1348 ok(r
, "got %ld\n", r
);
1350 /* LVIS_SELECTED with zero stateMask */
1352 memset (&item
, 0, sizeof (item
));
1353 item
.mask
= LVIF_STATE
;
1354 item
.state
= LVIS_FOCUSED
;
1358 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1361 memset (&item
, 0xcc, sizeof (item
));
1362 item
.mask
= LVIF_STATE
;
1363 item
.stateMask
= LVIS_FOCUSED
;
1367 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1369 ok(item
.state
& LVIS_FOCUSED
, "Expected LVIS_FOCUSED\n");
1370 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
1371 ok(r
, "got %ld\n", r
);
1373 /* LVIS_CUT with LVIS_FOCUSED stateMask */
1375 memset (&item
, 0, sizeof (item
));
1376 item
.mask
= LVIF_STATE
;
1377 item
.state
= LVIS_CUT
;
1378 item
.stateMask
= LVIS_FOCUSED
;
1381 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1384 memset (&item
, 0xcc, sizeof (item
));
1385 item
.mask
= LVIF_STATE
;
1386 item
.stateMask
= LVIS_CUT
;
1390 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1392 ok(item
.state
& LVIS_CUT
, "Expected LVIS_CUT\n");
1393 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
1394 ok(r
, "got %ld\n", r
);
1396 /* Insert an item with just a param */
1397 memset (&item
, 0xcc, sizeof (item
));
1398 item
.mask
= LVIF_PARAM
;
1401 item
.lParam
= lparamTest
;
1402 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1405 /* Test getting of the param */
1406 memset (&item
, 0xcc, sizeof (item
));
1407 item
.mask
= LVIF_PARAM
;
1410 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1412 ok(item
.lParam
== lparamTest
, "got lParam %Ix, expected %Ix\n", item
.lParam
, lparamTest
);
1414 /* Set up a subitem */
1415 memset (&item
, 0xcc, sizeof (item
));
1416 item
.mask
= LVIF_TEXT
;
1419 item
.pszText
= text
;
1420 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1423 item
.mask
= LVIF_TEXT
;
1426 item
.pszText
= buffA
;
1427 item
.cchTextMax
= sizeof(buffA
);
1428 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1430 ok(!memcmp(item
.pszText
, text
, sizeof(text
)), "got text %s, expected %s\n", item
.pszText
, text
);
1432 /* set up with extra flag */
1433 /* 1. reset subitem text */
1434 item
.mask
= LVIF_TEXT
;
1437 item
.pszText
= NULL
;
1438 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1441 item
.mask
= LVIF_TEXT
;
1444 item
.pszText
= buffA
;
1446 item
.cchTextMax
= sizeof(buffA
);
1447 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1449 ok(item
.pszText
[0] == 0, "got %p\n", item
.pszText
);
1451 /* 2. set new text with extra flag specified */
1452 item
.mask
= LVIF_TEXT
| LVIF_DI_SETITEM
;
1455 item
.pszText
= text
;
1456 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1457 ok(r
== 1 || broken(r
== 0) /* NT4 */, "ret %ld\n", r
);
1461 item
.mask
= LVIF_TEXT
;
1464 item
.pszText
= buffA
;
1466 item
.cchTextMax
= sizeof(buffA
);
1467 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1469 ok(!memcmp(item
.pszText
, text
, sizeof(text
)), "got %s, expected %s\n", item
.pszText
, text
);
1472 /* Query param from subitem: returns main item param */
1473 memset (&item
, 0xcc, sizeof (item
));
1474 item
.mask
= LVIF_PARAM
;
1477 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1479 ok(item
.lParam
== lparamTest
, "got lParam %Ix, expected %Ix\n", item
.lParam
, lparamTest
);
1481 /* Set up param on first subitem: no effect */
1482 memset (&item
, 0xcc, sizeof (item
));
1483 item
.mask
= LVIF_PARAM
;
1486 item
.lParam
= lparamTest
+1;
1487 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1490 /* Query param from subitem again: should still return main item param */
1491 memset (&item
, 0xcc, sizeof (item
));
1492 item
.mask
= LVIF_PARAM
;
1495 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1497 ok(item
.lParam
== lparamTest
, "got lParam %Ix, expected %Ix\n", item
.lParam
, lparamTest
);
1499 /**** Some tests of state highlighting ****/
1500 memset (&item
, 0xcc, sizeof (item
));
1501 item
.mask
= LVIF_STATE
;
1504 item
.state
= LVIS_SELECTED
;
1505 item
.stateMask
= LVIS_SELECTED
| LVIS_DROPHILITED
;
1506 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1509 item
.state
= LVIS_DROPHILITED
;
1510 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1513 memset (&item
, 0xcc, sizeof (item
));
1514 item
.mask
= LVIF_STATE
;
1517 item
.stateMask
= -1;
1518 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1520 ok(item
.state
== LVIS_SELECTED
, "got state %x, expected %x\n", item
.state
, LVIS_SELECTED
);
1522 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1524 todo_wine
ok(item
.state
== LVIS_DROPHILITED
, "got state %x, expected %x\n", item
.state
, LVIS_DROPHILITED
);
1526 /* some notnull but meaningless masks */
1527 memset (&item
, 0, sizeof(item
));
1528 item
.mask
= LVIF_NORECOMPUTE
;
1531 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1533 memset (&item
, 0, sizeof(item
));
1534 item
.mask
= LVIF_DI_SETITEM
;
1537 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1540 /* set text to callback value already having it */
1541 r
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1543 memset (&item
, 0, sizeof (item
));
1544 item
.mask
= LVIF_TEXT
;
1545 item
.pszText
= LPSTR_TEXTCALLBACKA
;
1547 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1549 memset (&item
, 0, sizeof (item
));
1551 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1553 item
.pszText
= LPSTR_TEXTCALLBACKA
;
1554 r
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0 , (LPARAM
) &item
);
1557 ok_sequence(sequences
, PARENT_SEQ_INDEX
, textcallback_set_again_parent_seq
,
1558 "check callback text comparison rule", FALSE
);
1560 DestroyWindow(hwnd
);
1563 static void test_columns(void)
1572 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_LIST
,
1573 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1574 ok(hwnd
!= NULL
, "failed to create listview window\n");
1576 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1577 ok(header
== NULL
, "got %p\n", header
);
1579 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1580 ok(rc
== 0, "got %ld\n", rc
);
1582 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1583 ok(header
== NULL
, "got %p\n", header
);
1585 DestroyWindow(hwnd
);
1587 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_REPORT
,
1588 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1589 ok(hwnd
!= NULL
, "failed to create listview window\n");
1591 rc
= SendMessageA(hwnd
, LVM_DELETECOLUMN
, -1, 0);
1592 ok(!rc
, "got %ld\n", rc
);
1594 rc
= SendMessageA(hwnd
, LVM_DELETECOLUMN
, 0, 0);
1595 ok(!rc
, "got %ld\n", rc
);
1597 /* Add a column with no mask */
1598 memset(&column
, 0xcc, sizeof(column
));
1600 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&column
);
1601 ok(rc
== 0, "Inserting column with no mask failed with %ld\n", rc
);
1603 /* Check its width */
1604 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
1605 ok(rc
== 10, "Inserting column with no mask failed to set width to 10 with %ld\n", rc
);
1607 DestroyWindow(hwnd
);
1609 /* LVM_GETCOLUMNORDERARRAY */
1610 hwnd
= create_listview_control(LVS_REPORT
);
1611 subclass_header(hwnd
);
1613 memset(&column
, 0, sizeof(column
));
1614 column
.mask
= LVCF_WIDTH
;
1616 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&column
);
1620 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 1, (LPARAM
)&column
);
1623 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1625 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1627 ok(order
[0] == 0, "Expected order 0, got %d\n", order
[0]);
1628 ok(order
[1] == 1, "Expected order 1, got %d\n", order
[1]);
1630 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNORDERARRAY
, 0, 0);
1633 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_getorderarray_seq
, "get order array", FALSE
);
1635 /* LVM_SETCOLUMNORDERARRAY */
1636 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1640 rc
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1643 rc
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 0, 0);
1646 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_setorderarray_seq
, "set order array", FALSE
);
1648 /* after column added subitem is considered as present */
1649 insert_item(hwnd
, 0);
1651 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1653 item
.pszText
= buff
;
1654 item
.cchTextMax
= sizeof(buff
);
1657 item
.mask
= LVIF_TEXT
;
1658 memset(&g_itema
, 0, sizeof(g_itema
));
1659 rc
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
1661 ok(g_itema
.iSubItem
== 1, "got %d\n", g_itema
.iSubItem
);
1663 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
1664 "get subitem text after column added", FALSE
);
1666 DestroyWindow(hwnd
);
1668 /* Columns are not created right away. */
1669 hwnd
= create_listview_control(LVS_REPORT
);
1670 ok(hwnd
!= NULL
, "Failed to create a listview window.\n");
1672 insert_item(hwnd
, 0);
1674 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1675 ok(IsWindow(header
), "Expected header handle.\n");
1676 rc
= SendMessageA(header
, HDM_GETITEMCOUNT
, 0, 0);
1677 ok(!rc
, "Unexpected column count.\n");
1679 DestroyWindow(hwnd
);
1682 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1683 static WNDPROC listviewWndProc
;
1684 static HIMAGELIST test_create_imagelist
;
1686 static LRESULT CALLBACK
create_test_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1690 if (uMsg
== WM_CREATE
)
1692 CREATESTRUCTA
*lpcs
= (CREATESTRUCTA
*)lParam
;
1693 lpcs
->style
|= LVS_REPORT
;
1695 ret
= CallWindowProcA(listviewWndProc
, hwnd
, uMsg
, wParam
, lParam
);
1696 if (uMsg
== WM_CREATE
) SendMessageA(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)test_create_imagelist
);
1700 /* Header creation is delayed in classic implementation. */
1701 #define TEST_NO_HEADER(a) test_header_presence_(a, FALSE, __LINE__)
1702 #define TEST_HEADER_EXPECTED(a) test_header_presence_(a, TRUE, __LINE__)
1703 #define TEST_NO_HEADER2(a, b) test_header_presence_(a, b, __LINE__)
1704 static void test_header_presence_(HWND hwnd
, BOOL present
, int line
)
1706 HWND header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1710 ok_(__FILE__
, line
)(IsWindow(header
), "Header should have been created.\n");
1711 if (header
) /* FIXME: remove when todo's are fixed */
1712 ok_(__FILE__
, line
)(header
== GetDlgItem(hwnd
, 0), "Dialog item expected.\n");
1716 ok_(__FILE__
, line
)(!IsWindow(header
), "Header shouldn't be created.\n");
1717 ok_(__FILE__
, line
)(NULL
== GetDlgItem(hwnd
, 0), "NULL dialog item expected.\n");
1721 static void test_create(BOOL is_version_6
)
1734 cls
.cbSize
= sizeof(WNDCLASSEXA
);
1735 r
= GetClassInfoExA(GetModuleHandleA(NULL
), WC_LISTVIEWA
, &cls
);
1736 ok(r
, "Failed to get class info.\n");
1737 listviewWndProc
= cls
.lpfnWndProc
;
1738 cls
.lpfnWndProc
= create_test_wndproc
;
1739 cls
.lpszClassName
= "MyListView32";
1740 class = RegisterClassExA(&cls
);
1741 ok(class, "Failed to register class.\n");
1743 test_create_imagelist
= pImageList_Create(16, 16, 0, 5, 10);
1744 hList
= CreateWindowA("MyListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1745 ok((HIMAGELIST
)SendMessageA(hList
, LVM_GETIMAGELIST
, 0, 0) == test_create_imagelist
, "Image list not obtained\n");
1746 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1747 ok(IsWindow(hHeader
) && IsWindowVisible(hHeader
), "Listview not in report mode\n");
1748 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1749 DestroyWindow(hList
);
1751 /* header isn't created on LVS_ICON and LVS_LIST styles */
1752 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1753 TEST_NO_HEADER(hList
);
1756 memset(&col
, 0, sizeof(LVCOLUMNA
));
1757 col
.mask
= LVCF_WIDTH
;
1759 r
= SendMessageA(hList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
1761 TEST_HEADER_EXPECTED(hList
);
1762 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1763 style
= GetWindowLongA(hHeader
, GWL_STYLE
);
1764 ok(!(style
& HDS_HIDDEN
), "Not expected HDS_HIDDEN\n");
1765 DestroyWindow(hList
);
1767 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1768 GetModuleHandleA(NULL
), 0);
1769 TEST_NO_HEADER(hList
);
1771 memset(&col
, 0, sizeof(LVCOLUMNA
));
1772 col
.mask
= LVCF_WIDTH
;
1774 r
= SendMessageA(hList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
1776 TEST_HEADER_EXPECTED(hList
);
1777 DestroyWindow(hList
);
1779 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1780 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1781 GetModuleHandleA(NULL
), 0);
1782 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
, GetWindowLongPtrA(hList
, GWL_STYLE
) | LVS_REPORT
);
1783 ok(ret
& WS_VISIBLE
, "Style wrong, should have WS_VISIBLE\n");
1784 TEST_HEADER_EXPECTED(hList
);
1785 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
, GetWindowLongA(hList
, GWL_STYLE
) & ~LVS_REPORT
);
1786 ok((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1787 TEST_HEADER_EXPECTED(hList
);
1788 DestroyWindow(hList
);
1790 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1791 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1792 GetModuleHandleA(NULL
), 0);
1793 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
,
1794 (GetWindowLongPtrA(hList
, GWL_STYLE
) & ~LVS_LIST
) | LVS_REPORT
);
1795 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_LIST
)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1796 TEST_HEADER_EXPECTED(hList
);
1797 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
, (GetWindowLongPtrA(hList
, GWL_STYLE
) & ~LVS_REPORT
) | LVS_LIST
);
1798 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1799 TEST_HEADER_EXPECTED(hList
);
1800 DestroyWindow(hList
);
1802 /* LVS_REPORT without WS_VISIBLE */
1803 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1804 GetModuleHandleA(NULL
), 0);
1805 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1806 todo_wine_if(is_version_6
)
1807 TEST_NO_HEADER2(hList
, is_version_6
);
1810 memset(&col
, 0, sizeof(LVCOLUMNA
));
1811 col
.mask
= LVCF_WIDTH
;
1813 r
= SendMessageA(hList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
1815 TEST_HEADER_EXPECTED(hList
);
1816 DestroyWindow(hList
);
1818 /* LVS_REPORT without WS_VISIBLE, try to show it */
1819 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1820 GetModuleHandleA(NULL
), 0);
1821 todo_wine_if(is_version_6
)
1822 TEST_NO_HEADER2(hList
, is_version_6
);
1824 ShowWindow(hList
, SW_SHOW
);
1825 TEST_HEADER_EXPECTED(hList
);
1826 DestroyWindow(hList
);
1828 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1829 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
|LVS_NOCOLUMNHEADER
|WS_VISIBLE
,
1830 0, 0, 100, 100, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1831 TEST_HEADER_EXPECTED(hList
);
1832 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1833 /* HDS_DRAGDROP set by default */
1834 ok(GetWindowLongPtrA(hHeader
, GWL_STYLE
) & HDS_DRAGDROP
, "Expected header to have HDS_DRAGDROP\n");
1835 DestroyWindow(hList
);
1837 /* setting LVS_EX_HEADERDRAGDROP creates header */
1838 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1839 GetModuleHandleA(NULL
), 0);
1840 todo_wine_if(is_version_6
)
1841 TEST_NO_HEADER2(hList
, is_version_6
);
1843 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1844 TEST_HEADER_EXPECTED(hList
);
1845 DestroyWindow(hList
);
1847 /* setting LVS_EX_GRIDLINES creates header */
1848 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1849 GetModuleHandleA(NULL
), 0);
1850 todo_wine_if(is_version_6
)
1851 TEST_NO_HEADER2(hList
, is_version_6
);
1853 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_GRIDLINES
);
1854 TEST_HEADER_EXPECTED(hList
);
1855 DestroyWindow(hList
);
1857 /* setting LVS_EX_FULLROWSELECT creates header */
1858 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1859 GetModuleHandleA(NULL
), 0);
1860 todo_wine_if(is_version_6
)
1861 TEST_NO_HEADER2(hList
, is_version_6
);
1862 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
1863 TEST_HEADER_EXPECTED(hList
);
1864 DestroyWindow(hList
);
1866 /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1867 hList
= create_listview_control(LVS_ICON
);
1868 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1869 r
= SendMessageA(hList
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1870 ok(r
& LVS_EX_HEADERDRAGDROP
, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1871 DestroyWindow(hList
);
1873 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1874 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1875 GetModuleHandleA(NULL
), 0);
1876 todo_wine_if(is_version_6
)
1877 TEST_NO_HEADER2(hList
, is_version_6
);
1879 SetRect(&rect
, LVIR_BOUNDS
, 1, -10, -10);
1880 r
= SendMessageA(hList
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1881 ok(r
== 1, "Unexpected ret value %ld.\n", r
);
1882 /* right value contains garbage, probably because header columns are not set up */
1883 ok(rect
.bottom
>= 0, "Unexpected rectangle.\n");
1885 todo_wine_if(is_version_6
)
1886 TEST_NO_HEADER2(hList
, is_version_6
);
1887 DestroyWindow(hList
);
1889 /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1890 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1891 hList
= create_listview_control(LVS_OWNERDRAWFIXED
| LVS_REPORT
);
1892 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_ownerdrawfixed_parent_seq
,
1893 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE
);
1894 DestroyWindow(hList
);
1896 /* Test that window text is preserved. */
1897 hList
= CreateWindowExA(0, WC_LISTVIEWA
, "test text", WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
1898 0, 0, 100, 100, hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
1899 ok(hList
!= NULL
, "Failed to create ListView window.\n");
1901 GetWindowTextA(hList
, buff
, sizeof(buff
));
1902 ok(!strcmp(buff
, "test text"), "Unexpected window text %s.\n", buff
);
1903 DestroyWindow(hList
);
1905 hList
= CreateWindowExW(0, WC_LISTVIEWW
, L
"test text", WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
1906 0, 0, 100, 100, hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
1907 ok(hList
!= NULL
, "Failed to create ListView window.\n");
1909 GetWindowTextA(hList
, buff
, sizeof(buff
));
1910 ok(!strcmp(buff
, "test text"), "Unexpected window text %s.\n", buff
);
1911 DestroyWindow(hList
);
1913 r
= UnregisterClassA("MyListView32", NULL
);
1914 ok(r
, "Failed to unregister test class.\n");
1917 static void test_redraw(void)
1925 hwnd
= create_listview_control(LVS_REPORT
);
1926 subclass_header(hwnd
);
1928 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1930 InvalidateRect(hwnd
, NULL
, TRUE
);
1932 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, redraw_listview_seq
, "redraw listview", FALSE
);
1934 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1936 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1937 /* 1. Without backbuffer */
1938 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
1941 hdc
= GetWindowDC(hwndparent
);
1943 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1944 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1945 ok(r
== 1, "Expected not zero result\n");
1946 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1947 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1949 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_DEFAULT
);
1952 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1953 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1955 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1956 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1958 /* 2. With backbuffer */
1959 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_DOUBLEBUFFER
,
1960 LVS_EX_DOUBLEBUFFER
);
1961 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
1964 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1965 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1967 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1968 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1970 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_DEFAULT
);
1973 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1974 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1975 todo_wine
expect(1, r
);
1976 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1977 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1979 ReleaseDC(hwndparent
, hdc
);
1981 /* test setting the window style to what it already was */
1983 SetWindowLongA(hwnd
, GWL_STYLE
, GetWindowLongA(hwnd
, GWL_STYLE
));
1984 GetUpdateRect(hwnd
, &rect
, FALSE
);
1985 ok(rect
.left
== 0 && rect
.top
== 0 && rect
.right
== 0 && rect
.bottom
== 0,
1986 "Expected empty update rect, got %s\n", wine_dbgstr_rect(&rect
));
1988 DestroyWindow(hwnd
);
1991 static LRESULT WINAPI
cd_wndproc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1993 COLORREF clr
, c0ffee
= RGB(0xc0, 0xff, 0xee);
1995 if(message
== WM_NOTIFY
) {
1996 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
1997 if(nmhdr
->code
== NM_CUSTOMDRAW
) {
1998 NMLVCUSTOMDRAW
*nmlvcd
= (NMLVCUSTOMDRAW
*)nmhdr
;
1999 BOOL showsel_always
= !!(GetWindowLongA(nmlvcd
->nmcd
.hdr
.hwndFrom
, GWL_STYLE
) & LVS_SHOWSELALWAYS
);
2000 BOOL is_selected
= !!(nmlvcd
->nmcd
.uItemState
& CDIS_SELECTED
);
2003 msg
.message
= message
;
2004 msg
.flags
= sent
|wparam
|lparam
|custdraw
;
2005 msg
.wParam
= wParam
;
2006 msg
.lParam
= lParam
;
2007 msg
.id
= nmhdr
->code
;
2008 msg
.stage
= nmlvcd
->nmcd
.dwDrawStage
;
2009 add_message(sequences
, PARENT_CD_SEQ_INDEX
, &msg
);
2011 switch(nmlvcd
->nmcd
.dwDrawStage
) {
2013 SetBkColor(nmlvcd
->nmcd
.hdc
, c0ffee
);
2014 return CDRF_NOTIFYITEMDRAW
|CDRF_NOTIFYPOSTPAINT
;
2015 case CDDS_ITEMPREPAINT
:
2016 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
2017 todo_wine_if(nmlvcd
->iSubItem
)
2018 ok(clr
== c0ffee
, "Unexpected background color %#lx.\n", clr
);
2019 nmlvcd
->clrTextBk
= CLR_DEFAULT
;
2020 nmlvcd
->clrText
= RGB(0, 255, 0);
2021 return CDRF_NOTIFYSUBITEMDRAW
|CDRF_NOTIFYPOSTPAINT
;
2022 case CDDS_ITEMPREPAINT
| CDDS_SUBITEM
:
2023 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
2024 ok(nmlvcd
->clrTextBk
== CLR_DEFAULT
, "Unexpected text background %#lx.\n", nmlvcd
->clrTextBk
);
2025 ok(nmlvcd
->clrText
== RGB(0, 255, 0), "Unexpected text color %#lx.\n", nmlvcd
->clrText
);
2026 if (showsel_always
&& is_selected
&& nmlvcd
->iSubItem
)
2027 ok(clr
== GetSysColor(COLOR_3DFACE
), "Unexpected background color %#lx.\n", clr
);
2029 todo_wine_if(nmlvcd
->iSubItem
)
2030 ok(clr
== c0ffee
, "clr=%.8lx\n", clr
);
2031 return CDRF_NOTIFYPOSTPAINT
;
2032 case CDDS_ITEMPOSTPAINT
| CDDS_SUBITEM
:
2033 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
2034 if (showsel_always
&& is_selected
)
2035 ok(clr
== GetSysColor(COLOR_3DFACE
), "Unexpected background color %#lx.\n", clr
);
2039 ok(clr
== c0ffee
, "Unexpected background color %#lx.\n", clr
);
2042 ok(nmlvcd
->clrTextBk
== CLR_DEFAULT
, "Unexpected text background color %#lx.\n", nmlvcd
->clrTextBk
);
2043 ok(nmlvcd
->clrText
== RGB(0, 255, 0), "got 0x%lx\n", nmlvcd
->clrText
);
2044 return CDRF_DODEFAULT
;
2046 return CDRF_DODEFAULT
;
2050 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2053 static void test_customdraw(void)
2059 hwnd
= create_listview_control(LVS_REPORT
);
2061 insert_column(hwnd
, 0);
2062 insert_column(hwnd
, 1);
2063 insert_item(hwnd
, 0);
2065 oldwndproc
= (WNDPROC
)SetWindowLongPtrA(hwndparent
, GWLP_WNDPROC
,
2066 (LONG_PTR
)cd_wndproc
);
2068 InvalidateRect(hwnd
, NULL
, TRUE
);
2072 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2073 InvalidateRect(hwnd
, NULL
, TRUE
);
2075 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_report_cd_seq
, "parent customdraw, LVS_REPORT", FALSE
);
2077 /* Check colors when item is selected. */
2078 item
.mask
= LVIF_STATE
;
2079 item
.stateMask
= LVIS_SELECTED
;
2080 item
.state
= LVIS_SELECTED
;
2081 SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2083 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2084 InvalidateRect(hwnd
, NULL
, TRUE
);
2086 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_report_cd_seq
,
2087 "parent customdraw, item selected, LVS_REPORT, selection", FALSE
);
2089 SetWindowLongW(hwnd
, GWL_STYLE
, GetWindowLongW(hwnd
, GWL_STYLE
) | LVS_SHOWSELALWAYS
);
2090 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2091 InvalidateRect(hwnd
, NULL
, TRUE
);
2093 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_report_cd_seq
,
2094 "parent customdraw, item selected, LVS_SHOWSELALWAYS, LVS_REPORT", FALSE
);
2096 DestroyWindow(hwnd
);
2098 hwnd
= create_listview_control(LVS_LIST
);
2100 insert_column(hwnd
, 0);
2101 insert_column(hwnd
, 1);
2102 insert_item(hwnd
, 0);
2104 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2105 InvalidateRect(hwnd
, NULL
, TRUE
);
2107 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_list_cd_seq
, "parent customdraw, LVS_LIST", FALSE
);
2109 SetWindowLongPtrA(hwndparent
, GWLP_WNDPROC
, (LONG_PTR
)oldwndproc
);
2110 DestroyWindow(hwnd
);
2113 static void test_icon_spacing(void)
2115 /* LVM_SETICONSPACING */
2116 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
2122 hwnd
= create_listview_control(LVS_ICON
);
2123 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2125 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, (WPARAM
)hwndparent
, NF_REQUERY
);
2126 expect(NFR_ANSI
, r
);
2128 /* reset the icon spacing to defaults */
2129 SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
2131 /* now we can request what the defaults are */
2132 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
2136 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2138 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(20, 30));
2139 ok(r
== MAKELONG(w
, h
) ||
2140 broken(r
== MAKELONG(w
, w
)), /* win98 */
2141 "Expected %ld, got %d\n", MAKELONG(w
, h
), r
);
2143 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(25, 35));
2144 expect(MAKELONG(20,30), r
);
2146 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1,-1));
2147 expect(MAKELONG(25,35), r
);
2149 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_icon_spacing_seq
, "test icon spacing seq", FALSE
);
2151 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2152 DestroyWindow(hwnd
);
2155 static void test_color(void)
2163 COLORREF colors
[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE
, RGB(255,255,255)};
2165 hwnd
= create_listview_control(LVS_REPORT
);
2166 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2168 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2170 for (i
= 0; i
< 4; i
++)
2174 r
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, color
);
2176 r
= SendMessageA(hwnd
, LVM_GETBKCOLOR
, 0, 0);
2179 r
= SendMessageA(hwnd
, LVM_SETTEXTCOLOR
, 0, color
);
2181 r
= SendMessageA(hwnd
, LVM_GETTEXTCOLOR
, 0, 0);
2184 r
= SendMessageA(hwnd
, LVM_SETTEXTBKCOLOR
, 0, color
);
2186 r
= SendMessageA(hwnd
, LVM_GETTEXTBKCOLOR
, 0, 0);
2190 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_color_seq
, "test color seq", FALSE
);
2191 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2193 /* invalidation test done separately to avoid a message chain mess */
2194 r
= ValidateRect(hwnd
, NULL
);
2196 r
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, colors
[0]);
2199 rect
.right
= rect
.bottom
= 1;
2200 r
= GetUpdateRect(hwnd
, &rect
, TRUE
);
2201 todo_wine
expect(FALSE
, r
);
2202 ok(rect
.right
== 0 && rect
.bottom
== 0, "got update rectangle\n");
2204 r
= ValidateRect(hwnd
, NULL
);
2206 r
= SendMessageA(hwnd
, LVM_SETTEXTCOLOR
, 0, colors
[0]);
2209 rect
.right
= rect
.bottom
= 1;
2210 r
= GetUpdateRect(hwnd
, &rect
, TRUE
);
2211 todo_wine
expect(FALSE
, r
);
2212 ok(rect
.right
== 0 && rect
.bottom
== 0, "got update rectangle\n");
2214 r
= ValidateRect(hwnd
, NULL
);
2216 r
= SendMessageA(hwnd
, LVM_SETTEXTBKCOLOR
, 0, colors
[0]);
2219 rect
.right
= rect
.bottom
= 1;
2220 r
= GetUpdateRect(hwnd
, &rect
, TRUE
);
2221 todo_wine
expect(FALSE
, r
);
2222 ok(rect
.right
== 0 && rect
.bottom
== 0, "got update rectangle\n");
2224 DestroyWindow(hwnd
);
2227 static void test_item_count(void)
2229 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
2242 static CHAR item0text
[] = "item0";
2243 static CHAR item1text
[] = "item1";
2244 static CHAR item2text
[] = "item2";
2246 hwnd
= create_listview_control(LVS_REPORT
);
2247 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2249 /* resize in dpiaware manner to fit all 3 items added */
2251 hOldFont
= SelectObject(hdc
, GetStockObject(SYSTEM_FONT
));
2252 GetTextMetricsA(hdc
, &tm
);
2253 /* 2 extra pixels for bounds and header border */
2254 height
= tm
.tmHeight
+ 2;
2255 SelectObject(hdc
, hOldFont
);
2258 GetWindowRect(hwnd
, &rect
);
2259 /* 3 items + 1 header + 1 to be sure */
2260 MoveWindow(hwnd
, 0, 0, rect
.right
- rect
.left
, 5 * height
, FALSE
);
2262 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2264 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2268 item0
.mask
= LVIF_TEXT
;
2271 item0
.pszText
= item0text
;
2272 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item0
);
2275 /* [item0, item1] */
2276 item1
.mask
= LVIF_TEXT
;
2279 item1
.pszText
= item1text
;
2280 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2283 /* [item0, item1, item2] */
2284 item2
.mask
= LVIF_TEXT
;
2287 item2
.pszText
= item2text
;
2288 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item2
);
2291 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2294 /* [item0, item1] */
2295 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 2, 0);
2298 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2302 r
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
2305 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2309 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2312 /* [item0, item1] */
2313 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2316 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2319 /* [item0, item1, item2] */
2320 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item2
);
2323 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2326 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_item_count_seq
, "test item count seq", FALSE
);
2328 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2329 DestroyWindow(hwnd
);
2332 static void test_item_position(void)
2334 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
2343 static CHAR item0text
[] = "item0";
2344 static CHAR item1text
[] = "item1";
2345 static CHAR item2text
[] = "item2";
2347 hwnd
= create_listview_control(LVS_ICON
);
2348 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2350 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2353 item0
.mask
= LVIF_TEXT
;
2356 item0
.pszText
= item0text
;
2357 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item0
);
2360 /* [item0, item1] */
2361 item1
.mask
= LVIF_TEXT
;
2364 item1
.pszText
= item1text
;
2365 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2368 /* [item0, item1, item2] */
2369 item2
.mask
= LVIF_TEXT
;
2372 item2
.pszText
= item2text
;
2373 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item2
);
2376 r
= SendMessageA(hwnd
, LVM_SETITEMPOSITION
, 1, MAKELPARAM(10,5));
2378 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 1, (LPARAM
) &position
);
2380 expect2(10, 5, position
.x
, position
.y
);
2382 r
= SendMessageA(hwnd
, LVM_SETITEMPOSITION
, 2, MAKELPARAM(0,0));
2384 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 2, (LPARAM
) &position
);
2386 expect2(0, 0, position
.x
, position
.y
);
2388 r
= SendMessageA(hwnd
, LVM_SETITEMPOSITION
, 0, MAKELPARAM(20,20));
2390 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
) &position
);
2392 expect2(20, 20, position
.x
, position
.y
);
2394 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_itempos_seq
, "test item position seq", TRUE
);
2396 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2397 DestroyWindow(hwnd
);
2400 static void test_getorigin(void)
2408 position
.x
= position
.y
= 0;
2410 hwnd
= create_listview_control(LVS_ICON
);
2411 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2412 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2414 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2416 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2417 DestroyWindow(hwnd
);
2419 hwnd
= create_listview_control(LVS_SMALLICON
);
2420 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2421 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2423 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2425 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2426 DestroyWindow(hwnd
);
2428 hwnd
= create_listview_control(LVS_LIST
);
2429 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2430 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2432 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2434 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2435 DestroyWindow(hwnd
);
2437 hwnd
= create_listview_control(LVS_REPORT
);
2438 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2439 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2441 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2443 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2444 DestroyWindow(hwnd
);
2447 static void test_multiselect(void)
2449 typedef struct t_select_task
2461 static const int items
=5;
2467 static struct t_select_task task_list
[] = {
2468 { "using VK_DOWN", 0, VK_DOWN
, -1, -1 },
2469 { "using VK_UP", -1, VK_UP
, -1, -1 },
2470 { "using VK_END", 0, VK_END
, 1, -1 },
2471 { "using VK_HOME", -1, VK_HOME
, 1, -1 }
2474 hwnd
= create_listview_control(LVS_REPORT
);
2476 for (i
= 0; i
< items
; i
++)
2477 insert_item(hwnd
, 0);
2479 item_count
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2480 expect(items
, item_count
);
2482 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2483 ok(r
== -1, "got %d\n", r
);
2485 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, 0);
2486 ok(r
== -1, "got %d\n", r
);
2488 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, 0);
2489 ok(r
== 0, "got %d\n", r
);
2491 /* out of range index */
2492 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, items
);
2493 ok(r
== 0, "got %d\n", r
);
2495 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2496 ok(r
== 0, "got %d\n", r
);
2498 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -2);
2499 ok(r
== 0, "got %d\n", r
);
2501 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2502 ok(r
== 0, "got %d\n", r
);
2504 for (i
= 0; i
< ARRAY_SIZE(task_list
); i
++) {
2505 DWORD selected_count
;
2508 task
= task_list
[i
];
2510 /* deselect all items */
2512 item
.stateMask
= LVIS_SELECTED
;
2513 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2514 ok(r
, "got %d\n", r
);
2515 SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2517 /* set initial position */
2518 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, (task
.initPos
== -1 ? item_count
-1 : task
.initPos
));
2519 ok(r
, "got %d\n", r
);
2521 item
.state
= LVIS_SELECTED
;
2522 item
.stateMask
= LVIS_SELECTED
;
2523 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, task
.initPos
== -1 ? item_count
-1 : task
.initPos
, (LPARAM
)&item
);
2524 ok(r
, "got %d\n", r
);
2526 selected_count
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2527 ok(selected_count
== 1, "expected 1, got %ld\n", selected_count
);
2531 for (j
=1;j
<=(task
.count
== -1 ? item_count
: task
.count
);j
++) {
2532 r
= SendMessageA(hwnd
, WM_KEYDOWN
, task
.loopVK
, 0);
2534 r
= SendMessageA(hwnd
, WM_KEYUP
, task
.loopVK
, 0);
2538 selected_count
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2540 ok((task
.result
== -1 ? item_count
: task
.result
) == selected_count
,
2541 "Failed multiple selection %s. There should be %ld selected items (is %ld)\n",
2542 task
.descr
, item_count
, selected_count
);
2544 release_key(VK_SHIFT
);
2546 DestroyWindow(hwnd
);
2548 /* make multiple selection, then switch to LVS_SINGLESEL */
2549 hwnd
= create_listview_control(LVS_REPORT
);
2550 for (i
=0;i
<items
;i
++) {
2551 insert_item(hwnd
, 0);
2553 item_count
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2554 expect(items
,item_count
);
2556 /* try with NULL pointer */
2557 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, 0);
2560 /* select all, check notifications */
2562 item
.stateMask
= LVIS_SELECTED
;
2563 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2564 ok(r
, "got %d\n", r
);
2566 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2568 item
.stateMask
= LVIS_SELECTED
;
2569 item
.state
= LVIS_SELECTED
;
2570 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2573 ok_sequence(sequences
, PARENT_SEQ_INDEX
, change_all_parent_seq
,
2574 "select all notification", FALSE
);
2576 /* select all again (all selected already) */
2577 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2579 memset(&g_nmlistview_changing
, 0xcc, sizeof(g_nmlistview_changing
));
2581 item
.stateMask
= LVIS_SELECTED
;
2582 item
.state
= LVIS_SELECTED
;
2583 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2586 ok(g_nmlistview_changing
.uNewState
== LVIS_SELECTED
, "got 0x%x\n", g_nmlistview_changing
.uNewState
);
2587 ok(g_nmlistview_changing
.uOldState
== LVIS_SELECTED
, "got 0x%x\n", g_nmlistview_changing
.uOldState
);
2588 ok(g_nmlistview_changing
.uChanged
== LVIF_STATE
, "got 0x%x\n", g_nmlistview_changing
.uChanged
);
2590 ok_sequence(sequences
, PARENT_SEQ_INDEX
, changing_all_parent_seq
,
2591 "select all notification 2", FALSE
);
2593 /* deselect all items */
2594 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2597 item
.stateMask
= LVIS_SELECTED
;
2598 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2599 ok(r
, "got %d\n", r
);
2601 ok_sequence(sequences
, PARENT_SEQ_INDEX
, change_all_parent_seq
,
2602 "deselect all notification", FALSE
);
2604 /* deselect all items again */
2605 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2607 item
.stateMask
= LVIS_SELECTED
;
2608 SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2609 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "deselect all notification 2", FALSE
);
2611 /* any non-zero state value does the same */
2612 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2614 memset(&g_nmlistview_changing
, 0xcc, sizeof(g_nmlistview_changing
));
2616 item
.stateMask
= LVIS_SELECTED
;
2617 item
.state
= LVIS_CUT
;
2618 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2621 ok(g_nmlistview_changing
.uNewState
== 0, "got 0x%x\n", g_nmlistview_changing
.uNewState
);
2622 ok(g_nmlistview_changing
.uOldState
== 0, "got 0x%x\n", g_nmlistview_changing
.uOldState
);
2623 ok(g_nmlistview_changing
.uChanged
== LVIF_STATE
, "got 0x%x\n", g_nmlistview_changing
.uChanged
);
2625 ok_sequence(sequences
, PARENT_SEQ_INDEX
, changing_all_parent_seq
,
2626 "set state all notification 3", FALSE
);
2628 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2629 ok(r
, "got %d\n", r
);
2630 for (i
= 0; i
< 3; i
++) {
2631 item
.state
= LVIS_SELECTED
;
2632 item
.stateMask
= LVIS_SELECTED
;
2633 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
2634 ok(r
, "got %d\n", r
);
2637 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2639 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2642 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2643 ok(!(style
& LVS_SINGLESEL
), "LVS_SINGLESEL isn't expected\n");
2644 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SINGLESEL
);
2645 /* check that style is accepted */
2646 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2647 ok(style
& LVS_SINGLESEL
, "LVS_SINGLESEL expected\n");
2650 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, i
, LVIS_SELECTED
);
2651 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
2653 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2655 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2656 ok(r
== -1, "got %d\n", r
);
2658 /* select one more */
2659 item
.state
= LVIS_SELECTED
;
2660 item
.stateMask
= LVIS_SELECTED
;
2661 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 3, (LPARAM
)&item
);
2662 ok(r
, "got %d\n", r
);
2665 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, i
, LVIS_SELECTED
);
2666 ok(!(r
& LVIS_SELECTED
), "Expected item %d to be unselected\n", i
);
2669 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 3, LVIS_SELECTED
);
2670 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
2672 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2674 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2677 /* try to select all on LVS_SINGLESEL */
2678 memset(&item
, 0, sizeof(item
));
2679 item
.stateMask
= LVIS_SELECTED
;
2680 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2682 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2683 ok(r
== -1, "got %d\n", r
);
2685 item
.stateMask
= LVIS_SELECTED
;
2686 item
.state
= LVIS_SELECTED
;
2687 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2690 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2692 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2695 /* try to deselect all on LVS_SINGLESEL */
2696 item
.stateMask
= LVIS_SELECTED
;
2697 item
.state
= LVIS_SELECTED
;
2698 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2701 item
.stateMask
= LVIS_SELECTED
;
2703 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2705 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2708 /* 1. selection mark is update when new focused item is set */
2709 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2710 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SINGLESEL
);
2712 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2715 item
.stateMask
= LVIS_FOCUSED
;
2716 item
.state
= LVIS_FOCUSED
;
2717 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2720 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2723 /* it's not updated if already set */
2724 item
.stateMask
= LVIS_FOCUSED
;
2725 item
.state
= LVIS_FOCUSED
;
2726 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 1, (LPARAM
)&item
);
2729 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2732 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2735 item
.stateMask
= LVIS_FOCUSED
;
2736 item
.state
= LVIS_FOCUSED
;
2737 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 1, (LPARAM
)&item
);
2740 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2743 /* need to reset focused item first */
2744 item
.stateMask
= LVIS_FOCUSED
;
2746 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2749 item
.stateMask
= LVIS_FOCUSED
;
2750 item
.state
= LVIS_FOCUSED
;
2751 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 2, (LPARAM
)&item
);
2754 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2757 item
.stateMask
= LVIS_FOCUSED
;
2759 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2762 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2765 /* 2. same tests, with LVM_SETITEM */
2766 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2767 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SINGLESEL
);
2769 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2772 item
.stateMask
= LVIS_FOCUSED
;
2773 item
.state
= LVIS_FOCUSED
;
2774 item
.mask
= LVIF_STATE
;
2775 item
.iItem
= item
.iSubItem
= 0;
2776 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2779 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2782 /* it's not updated if already set */
2783 item
.stateMask
= LVIS_FOCUSED
;
2784 item
.state
= LVIS_FOCUSED
;
2785 item
.mask
= LVIF_STATE
;
2788 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2791 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2794 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2797 item
.stateMask
= LVIS_FOCUSED
;
2798 item
.state
= LVIS_FOCUSED
;
2799 item
.mask
= LVIF_STATE
;
2802 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2805 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2808 /* need to reset focused item first */
2809 item
.stateMask
= LVIS_FOCUSED
;
2811 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2814 item
.stateMask
= LVIS_FOCUSED
;
2815 item
.state
= LVIS_FOCUSED
;
2816 item
.mask
= LVIF_STATE
;
2819 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2822 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2825 item
.stateMask
= LVIS_FOCUSED
;
2827 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2830 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2833 DestroyWindow(hwnd
);
2836 static void test_subitem_rect(void)
2844 /* test LVM_GETSUBITEMRECT for header */
2845 hwnd
= create_listview_control(LVS_REPORT
);
2846 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2847 /* add some columns */
2848 memset(&col
, 0, sizeof(LVCOLUMNA
));
2849 col
.mask
= LVCF_WIDTH
;
2851 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
2854 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 1, (LPARAM
)&col
);
2857 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 2, (LPARAM
)&col
);
2859 /* item = -1 means header, subitem index is 1 based */
2860 SetRect(&rect
, LVIR_BOUNDS
, 0, 0, 0);
2861 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2864 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2865 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2868 expect(100, rect
.left
);
2869 expect(250, rect
.right
);
2870 expect(3, rect
.top
);
2872 SetRect(&rect
, LVIR_BOUNDS
, 2, 0, 0);
2873 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2876 expect(250, rect
.left
);
2877 expect(450, rect
.right
);
2878 expect(3, rect
.top
);
2880 /* item LVS_REPORT padding isn't applied to subitems */
2881 insert_item(hwnd
, 0);
2883 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2884 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2886 expect(100, rect
.left
);
2887 expect(250, rect
.right
);
2889 SetRect(&rect
, LVIR_ICON
, 1, 0, 0);
2890 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2892 /* no icon attached - zero width rectangle, with no left padding */
2893 expect(100, rect
.left
);
2894 expect(100, rect
.right
);
2896 SetRect(&rect
, LVIR_LABEL
, 1, 0, 0);
2897 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2899 /* same as full LVIR_BOUNDS */
2900 expect(100, rect
.left
);
2901 expect(250, rect
.right
);
2903 r
= SendMessageA(hwnd
, LVM_SCROLL
, 10, 0);
2904 ok(r
, "got %ld\n", r
);
2906 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2907 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2909 expect(90, rect
.left
);
2910 expect(240, rect
.right
);
2912 SendMessageA(hwnd
, LVM_SCROLL
, -10, 0);
2914 /* test header interaction */
2915 subclass_header(hwnd
);
2916 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2918 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2919 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2922 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2923 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2926 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2927 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -10, (LPARAM
)&rect
);
2930 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2931 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 20, (LPARAM
)&rect
);
2934 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getsubitemrect_seq
, "LVM_GETSUBITEMRECT negative index", FALSE
);
2936 DestroyWindow(hwnd
);
2938 /* test subitem rects after re-arranging columns */
2939 hwnd
= create_listview_control(LVS_REPORT
);
2940 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2941 memset(&col
, 0, sizeof(LVCOLUMNA
));
2942 col
.mask
= LVCF_WIDTH
;
2945 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
2949 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 1, (LPARAM
)&col
);
2953 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 2, (LPARAM
)&col
);
2956 insert_item(hwnd
, 0);
2957 insert_item(hwnd
, 1);
2959 /* wrong item is refused for main item */
2960 SetRect(&rect
, LVIR_BOUNDS
, 0, -1, -1);
2961 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 2, (LPARAM
)&rect
);
2964 /* for subitems rectangle is calculated even if there's no item added */
2965 SetRect(&rect
, LVIR_BOUNDS
, 1, -1, -1);
2966 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 1, (LPARAM
)&rect
);
2969 SetRect(&rect2
, LVIR_BOUNDS
, 1, -1, -1);
2970 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 2, (LPARAM
)&rect2
);
2972 expect(rect
.right
, rect2
.right
);
2973 expect(rect
.left
, rect2
.left
);
2974 expect(rect
.bottom
, rect2
.top
);
2975 ok(rect2
.bottom
> rect2
.top
, "expected not zero height\n");
2977 arr
[0] = 1; arr
[1] = 0; arr
[2] = 2;
2978 r
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 3, (LPARAM
)arr
);
2981 SetRect(&rect
, LVIR_BOUNDS
, 0, -1, -1);
2982 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2984 expect(0, rect
.left
);
2985 expect(600, rect
.right
);
2987 SetRect(&rect
, LVIR_BOUNDS
, 1, -1, -1);
2988 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2990 expect(0, rect
.left
);
2991 expect(200, rect
.right
);
2993 SetRect(&rect2
, LVIR_BOUNDS
, 1, -1, -1);
2994 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 1, (LPARAM
)&rect2
);
2996 expect(0, rect2
.left
);
2997 expect(200, rect2
.right
);
2998 /* items are of the same height */
2999 ok(rect2
.top
> 0, "expected positive item height\n");
3000 expect(rect
.bottom
, rect2
.top
);
3001 expect(rect
.bottom
* 2 - rect
.top
, rect2
.bottom
);
3003 SetRect(&rect
, LVIR_BOUNDS
, 2, -1, -1);
3004 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
3006 expect(300, rect
.left
);
3007 expect(600, rect
.right
);
3009 DestroyWindow(hwnd
);
3011 /* try it for non LVS_REPORT style */
3012 hwnd
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_ICON
, 0, 0, 100, 100, NULL
, NULL
,
3013 GetModuleHandleA(NULL
), 0);
3014 SetRect(&rect
, LVIR_BOUNDS
, 1, -10, -10);
3015 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
3017 /* rect is unchanged */
3018 expect(0, rect
.left
);
3019 expect(-10, rect
.right
);
3020 expect(1, rect
.top
);
3021 expect(-10, rect
.bottom
);
3022 DestroyWindow(hwnd
);
3025 /* comparison callback for test_sorting */
3026 static INT WINAPI
test_CallBackCompare(LPARAM first
, LPARAM second
, LPARAM lParam
)
3028 if (first
== second
) return 0;
3029 return (first
> second
? 1 : -1);
3032 static void test_sorting(void)
3038 static CHAR names
[][5] = {"A", "B", "C", "D", "0"};
3041 hwnd
= create_listview_control(LVS_REPORT
);
3042 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3044 /* insert some items */
3045 item
.mask
= LVIF_PARAM
| LVIF_STATE
;
3046 item
.state
= LVIS_SELECTED
;
3050 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3053 item
.mask
= LVIF_PARAM
;
3057 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3060 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
3061 item
.state
= LVIS_SELECTED
;
3065 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3068 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
3071 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3074 r
= SendMessageA(hwnd
, LVM_SORTITEMS
, 0, (LPARAM
)test_CallBackCompare
);
3077 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3079 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
3081 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_SELECTED
);
3083 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_SELECTED
);
3084 expect(LVIS_SELECTED
, r
);
3085 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_SELECTED
);
3086 expect(LVIS_SELECTED
, r
);
3088 DestroyWindow(hwnd
);
3090 /* switch to LVS_SORTASCENDING when some items added */
3091 hwnd
= create_listview_control(LVS_REPORT
);
3092 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3094 item
.mask
= LVIF_TEXT
;
3097 item
.pszText
= names
[1];
3098 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3101 item
.mask
= LVIF_TEXT
;
3104 item
.pszText
= names
[2];
3105 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3108 item
.mask
= LVIF_TEXT
;
3111 item
.pszText
= names
[0];
3112 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3115 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3116 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
3117 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3118 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
3120 /* no sorting performed when switched to LVS_SORTASCENDING */
3121 item
.mask
= LVIF_TEXT
;
3123 item
.pszText
= buff
;
3124 item
.cchTextMax
= sizeof(buff
);
3125 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3127 ok(lstrcmpA(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
3130 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3132 ok(lstrcmpA(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
3135 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3137 ok(lstrcmpA(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
3139 /* adding new item doesn't resort list */
3140 item
.mask
= LVIF_TEXT
;
3143 item
.pszText
= names
[3];
3144 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3147 item
.mask
= LVIF_TEXT
;
3149 item
.pszText
= buff
;
3150 item
.cchTextMax
= sizeof(buff
);
3151 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3153 ok(lstrcmpA(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
3156 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3158 ok(lstrcmpA(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
3161 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3163 ok(lstrcmpA(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
3166 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3168 ok(lstrcmpA(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
3170 /* corner case - item should be placed at first position */
3171 item
.mask
= LVIF_TEXT
;
3174 item
.pszText
= names
[4];
3175 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3179 item
.pszText
= buff
;
3180 item
.cchTextMax
= sizeof(buff
);
3181 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3183 ok(lstrcmpA(buff
, names
[4]) == 0, "Expected '%s', got '%s'\n", names
[4], buff
);
3186 item
.pszText
= buff
;
3187 item
.cchTextMax
= sizeof(buff
);
3188 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3190 ok(lstrcmpA(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
3193 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3195 ok(lstrcmpA(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
3198 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3200 ok(lstrcmpA(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
3203 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3205 ok(lstrcmpA(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
3207 DestroyWindow(hwnd
);
3210 static void test_ownerdata(void)
3212 static char test_str
[] = "test";
3215 LONG_PTR style
, ret
;
3219 /* Setting LVS_OWNERDATA after creation leads to crash on older versions < 5.80 */
3220 hwnd
= create_listview_control(LVS_REPORT
);
3221 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3222 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3223 ok(!(style
& LVS_OWNERDATA
) && style
, "LVS_OWNERDATA isn't expected\n");
3225 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3227 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
3228 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
3229 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
3230 "try to switch to LVS_OWNERDATA seq", FALSE
);
3232 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3233 ok(!(style
& LVS_OWNERDATA
), "LVS_OWNERDATA isn't expected\n");
3234 DestroyWindow(hwnd
);
3236 /* try to set LVS_OWNERDATA after creation just having it */
3237 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3238 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3239 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3240 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
3242 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3244 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
3245 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
3246 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
3247 "try to switch to LVS_OWNERDATA seq", FALSE
);
3248 DestroyWindow(hwnd
);
3250 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3251 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3252 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3253 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
3255 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3257 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_OWNERDATA
);
3258 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
3259 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
3260 "try to switch to LVS_OWNERDATA seq", FALSE
);
3261 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3262 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
3263 DestroyWindow(hwnd
);
3265 /* try select an item */
3266 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3267 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3268 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3270 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3272 memset(&item
, 0, sizeof(item
));
3273 item
.stateMask
= LVIS_SELECTED
;
3274 item
.state
= LVIS_SELECTED
;
3275 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3277 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3279 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
3281 DestroyWindow(hwnd
);
3283 /* LVM_SETITEM and LVM_SETITEMTEXT is unsupported on LVS_OWNERDATA */
3284 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3285 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3286 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3288 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
3290 memset(&item
, 0, sizeof(item
));
3291 item
.mask
= LVIF_STATE
;
3293 item
.stateMask
= LVIS_SELECTED
;
3294 item
.state
= LVIS_SELECTED
;
3295 res
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
3297 memset(&item
, 0, sizeof(item
));
3298 item
.pszText
= test_str
;
3299 res
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
3301 DestroyWindow(hwnd
);
3303 /* check notifications after focused/selected changed */
3304 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3305 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3306 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 20, 0);
3309 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3311 memset(&item
, 0, sizeof(item
));
3312 item
.stateMask
= LVIS_SELECTED
;
3313 item
.state
= LVIS_SELECTED
;
3314 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3317 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_select_focus_parent_seq
,
3318 "ownerdata select notification", TRUE
);
3320 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3322 memset(&item
, 0, sizeof(item
));
3323 item
.stateMask
= LVIS_FOCUSED
;
3324 item
.state
= LVIS_FOCUSED
;
3325 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3328 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_select_focus_parent_seq
,
3329 "ownerdata focus notification", TRUE
);
3331 /* select all, check notifications */
3332 item
.stateMask
= LVIS_SELECTED
;
3334 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3337 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3339 item
.stateMask
= LVIS_SELECTED
;
3340 item
.state
= LVIS_SELECTED
;
3342 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3343 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3345 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3346 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3347 ok(g_nmlistview
.uNewState
== LVIS_SELECTED
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3348 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3349 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3350 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3351 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3353 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3354 "ownerdata select all notification", FALSE
);
3356 /* select all again, note that all items are selected already */
3357 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3358 item
.stateMask
= LVIS_SELECTED
;
3359 item
.state
= LVIS_SELECTED
;
3361 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3362 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
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
== LVIS_SELECTED
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3367 ok(g_nmlistview
.uOldState
== 0, "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");
3372 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3373 "ownerdata select all notification", FALSE
);
3376 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3377 item
.stateMask
= LVIS_SELECTED
;
3380 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3381 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3383 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3384 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3385 ok(g_nmlistview
.uNewState
== 0, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3386 ok(g_nmlistview
.uOldState
== LVIS_SELECTED
, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3387 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3388 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3389 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3391 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_deselect_all_parent_seq
,
3392 "ownerdata deselect all notification", TRUE
);
3394 /* nothing selected, deselect all again */
3395 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3396 item
.stateMask
= LVIS_SELECTED
;
3399 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3402 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "ownerdata deselect all notification", FALSE
);
3404 /* select one, then deselect all */
3405 item
.stateMask
= LVIS_SELECTED
;
3406 item
.state
= LVIS_SELECTED
;
3407 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3409 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3410 item
.stateMask
= LVIS_SELECTED
;
3413 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3414 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3416 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3417 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3418 ok(g_nmlistview
.uNewState
== 0, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3419 ok(g_nmlistview
.uOldState
== LVIS_SELECTED
, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3420 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3421 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3422 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3424 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_deselect_all_parent_seq
,
3425 "ownerdata select all notification", TRUE
);
3427 /* remove focused, try to focus all */
3428 item
.stateMask
= LVIS_FOCUSED
;
3429 item
.state
= LVIS_FOCUSED
;
3430 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3432 item
.stateMask
= LVIS_FOCUSED
;
3434 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3436 item
.stateMask
= LVIS_FOCUSED
;
3437 res
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_FOCUSED
);
3440 /* setting all to focused returns failure value */
3441 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3442 item
.stateMask
= LVIS_FOCUSED
;
3443 item
.state
= LVIS_FOCUSED
;
3445 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3448 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3449 "ownerdata focus all notification", FALSE
);
3451 /* focus single item, remove all */
3452 item
.stateMask
= LVIS_FOCUSED
;
3453 item
.state
= LVIS_FOCUSED
;
3454 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3456 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3457 item
.stateMask
= LVIS_FOCUSED
;
3460 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3461 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3463 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3464 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3465 ok(g_nmlistview
.uNewState
== 0, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3466 ok(g_nmlistview
.uOldState
== LVIS_FOCUSED
, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3467 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3468 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3469 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3471 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_defocus_all_parent_seq
,
3472 "ownerdata remove focus all notification", TRUE
);
3475 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3476 item
.stateMask
= LVIS_CUT
;
3477 item
.state
= LVIS_CUT
;
3479 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3480 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3482 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3483 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3484 ok(g_nmlistview
.uNewState
== LVIS_CUT
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3485 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3486 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3487 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3488 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3490 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3491 "ownerdata cut all notification", FALSE
);
3493 /* all marked cut, try again */
3494 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3495 item
.stateMask
= LVIS_CUT
;
3496 item
.state
= LVIS_CUT
;
3498 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3499 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3501 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3502 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3503 ok(g_nmlistview
.uNewState
== LVIS_CUT
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3504 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3505 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3506 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3507 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3509 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3510 "ownerdata cut all notification #2", FALSE
);
3512 DestroyWindow(hwnd
);
3514 /* check notifications on LVM_GETITEM */
3515 /* zero callback mask */
3516 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3517 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3518 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3521 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3523 memset(&item
, 0, sizeof(item
));
3524 item
.stateMask
= LVIS_SELECTED
;
3525 item
.mask
= LVIF_STATE
;
3526 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3529 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3530 "ownerdata getitem selected state 1", FALSE
);
3532 /* non zero callback mask but not we asking for */
3533 res
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_OVERLAYMASK
, 0);
3536 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3538 memset(&item
, 0, sizeof(item
));
3539 item
.stateMask
= LVIS_SELECTED
;
3540 item
.mask
= LVIF_STATE
;
3541 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3544 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3545 "ownerdata getitem selected state 2", FALSE
);
3547 /* LVIS_OVERLAYMASK callback mask, asking for index */
3548 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3550 memset(&item
, 0, sizeof(item
));
3551 item
.stateMask
= LVIS_OVERLAYMASK
;
3552 item
.mask
= LVIF_STATE
;
3553 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3556 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
3557 "ownerdata getitem selected state 2", FALSE
);
3559 DestroyWindow(hwnd
);
3561 /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
3562 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_SORTASCENDING
| LVS_REPORT
);
3563 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3564 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3565 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
3566 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
3567 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SORTASCENDING
);
3568 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3569 ok(!(style
& LVS_SORTASCENDING
), "Expected LVS_SORTASCENDING not set\n");
3570 DestroyWindow(hwnd
);
3571 /* apparently it's allowed to switch these style on after creation */
3572 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3573 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3574 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3575 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
3576 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
3577 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3578 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
3579 DestroyWindow(hwnd
);
3581 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3582 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3583 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3584 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
3585 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTDESCENDING
);
3586 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3587 ok(style
& LVS_SORTDESCENDING
, "Expected LVS_SORTDESCENDING to be set\n");
3588 DestroyWindow(hwnd
);
3590 /* The focused item is updated after the invalidation */
3591 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3592 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3593 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 3, 0);
3596 memset(&item
, 0, sizeof(item
));
3597 item
.stateMask
= LVIS_FOCUSED
;
3598 item
.state
= LVIS_FOCUSED
;
3599 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3602 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3603 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 0, 0);
3605 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3606 "ownerdata setitemcount", FALSE
);
3608 res
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
3610 DestroyWindow(hwnd
);
3613 static void test_ownerdata_multiselect(void)
3626 UINT selected_count
;
3627 const char *context
;
3628 const struct message
*expected
;
3633 /* First down then up */
3634 { TRUE
, FALSE
, VK_DOWN
, 2, "select multiple via SHIFT+DOWN",
3635 ownerdata_multiselect_select_0_to_1_odstatechanged_seq
, FALSE
},
3636 { TRUE
, FALSE
, VK_UP
, 1, "select one item via SHIFT+UP",
3637 ownerdata_multiselect_select_0_modkey_odstatechanged_seq
, TRUE
},
3638 { TRUE
, TRUE
, VK_DOWN
, 2, "select multiple via SHIFT+CONTROL+DOWN",
3639 ownerdata_multiselect_select_0_to_1_odstatechanged_seq
, FALSE
},
3640 { TRUE
, TRUE
, VK_UP
, 1, "select one item via SHIFT+CONTROL+UP",
3641 ownerdata_multiselect_select_0_modkey_odstatechanged_seq
, TRUE
},
3642 { FALSE
, TRUE
, VK_DOWN
, 1, "keep selection but move cursor via CONTROL+DOWN",
3643 ownerdata_multiselect_move_0_to_1_odstatechanged_seq
, FALSE
},
3644 { TRUE
, TRUE
, VK_DOWN
, 3, "select multiple after skip via SHIFT+CONTROL+DOWN",
3645 ownerdata_multiselect_select_0_to_2_odstatechanged_seq
, FALSE
},
3646 { FALSE
, FALSE
, VK_DOWN
, 1, "deselect all, select item 3 via DOWN",
3647 ownerdata_multiselect_select_3_odstatechanged_seq
, FALSE
},
3648 /* First up then down */
3649 { TRUE
, FALSE
, VK_UP
, 2, "select multiple via SHIFT+UP",
3650 ownerdata_multiselect_select_3_to_2_odstatechanged_seq
, FALSE
},
3651 { TRUE
, FALSE
, VK_DOWN
, 1, "select one item via SHIFT+DOWN",
3652 ownerdata_multiselect_select_3_modkey_odstatechanged_seq
, TRUE
},
3653 { TRUE
, TRUE
, VK_UP
, 2, "select multiple via SHIFT+CONTROL+UP",
3654 ownerdata_multiselect_select_3_to_2_odstatechanged_seq
, FALSE
},
3655 { TRUE
, TRUE
, VK_DOWN
, 1, "select one item via SHIFT+CONTROL+DOWN",
3656 ownerdata_multiselect_select_3_modkey_odstatechanged_seq
, TRUE
},
3657 { FALSE
, TRUE
, VK_UP
, 1, "keep selection but move cursor via CONTROL+UP",
3658 ownerdata_multiselect_move_3_to_2_odstatechanged_seq
, FALSE
},
3659 { TRUE
, TRUE
, VK_UP
, 3, "select multiple after skip via SHIFT+CONTROL+UP",
3660 ownerdata_multiselect_select_3_to_1_odstatechanged_seq
, FALSE
},
3661 { FALSE
, FALSE
, VK_UP
, 1, "deselect all, select item 0 via UP",
3662 ownerdata_multiselect_select_0_odstatechanged_seq
, FALSE
},
3665 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3666 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3667 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 20, 0);
3669 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3672 /* Select and focus the first row */
3673 memset(&item
, 0, sizeof(item
));
3674 item
.state
= LVIS_SELECTED
| LVIS_FOCUSED
;
3675 item
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
3676 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3678 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3680 res
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, 0);
3683 /* Select/deselect rows using UP/DOWN and SHIFT/CONTROL keys */
3684 for (i
= 0; i
< ARRAY_SIZE(key_tests
); i
++)
3686 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3688 if (key_tests
[i
].hold_shift
)
3690 if (key_tests
[i
].hold_control
)
3691 hold_key(VK_CONTROL
);
3693 res
= SendMessageA(hwnd
, WM_KEYDOWN
, key_tests
[i
].press_key
, 0);
3695 sprintf(buf
, "ownerdata multiselect: %s", key_tests
[i
].context
);
3696 ok_sequence(sequences
, PARENT_ODSTATECHANGED_SEQ_INDEX
, key_tests
[i
].expected
,
3697 buf
, key_tests
[i
].todo
);
3698 res
= SendMessageA(hwnd
, WM_KEYUP
, key_tests
[i
].press_key
, 0);
3701 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3702 expect(key_tests
[i
].selected_count
, res
);
3704 if (key_tests
[i
].hold_shift
)
3705 release_key(VK_SHIFT
);
3706 if (key_tests
[i
].hold_control
)
3707 release_key(VK_CONTROL
);
3710 DestroyWindow(hwnd
);
3713 static void test_norecompute(void)
3715 static CHAR testA
[] = "test";
3721 /* self containing control */
3722 hwnd
= create_listview_control(LVS_REPORT
);
3723 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3724 memset(&item
, 0, sizeof(item
));
3725 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
3727 item
.stateMask
= LVIS_SELECTED
;
3728 item
.state
= LVIS_SELECTED
;
3729 item
.pszText
= testA
;
3730 res
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3732 /* retrieve with LVIF_NORECOMPUTE */
3733 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
3735 item
.pszText
= buff
;
3736 item
.cchTextMax
= ARRAY_SIZE(buff
);
3737 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3739 ok(lstrcmpA(buff
, testA
) == 0, "Expected (%s), got (%s)\n", testA
, buff
);
3741 item
.mask
= LVIF_TEXT
;
3743 item
.pszText
= LPSTR_TEXTCALLBACKA
;
3744 res
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3747 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
3749 item
.pszText
= buff
;
3750 item
.cchTextMax
= ARRAY_SIZE(buff
);
3752 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3753 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3755 ok(item
.pszText
== LPSTR_TEXTCALLBACKA
, "Expected (%p), got (%p)\n",
3756 LPSTR_TEXTCALLBACKA
, (VOID
*)item
.pszText
);
3757 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq", FALSE
);
3759 DestroyWindow(hwnd
);
3762 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3763 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3765 item
.mask
= LVIF_STATE
;
3766 item
.stateMask
= LVIS_SELECTED
;
3767 item
.state
= LVIS_SELECTED
;
3769 res
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3772 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
3774 item
.pszText
= buff
;
3775 item
.cchTextMax
= ARRAY_SIZE(buff
);
3776 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3777 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3779 ok(item
.pszText
== LPSTR_TEXTCALLBACKA
, "Expected (%p), got (%p)\n",
3780 LPSTR_TEXTCALLBACKA
, (VOID
*)item
.pszText
);
3781 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE
);
3783 DestroyWindow(hwnd
);
3786 static void test_nosortheader(void)
3791 hwnd
= create_listview_control(LVS_REPORT
);
3792 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3794 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
3795 ok(IsWindow(header
), "header expected\n");
3797 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3798 ok(style
& HDS_BUTTONS
, "expected header to have HDS_BUTTONS\n");
3800 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3801 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_NOSORTHEADER
);
3802 /* HDS_BUTTONS retained */
3803 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3804 ok(style
& HDS_BUTTONS
, "expected header to retain HDS_BUTTONS\n");
3806 DestroyWindow(hwnd
);
3808 /* create with LVS_NOSORTHEADER */
3809 hwnd
= create_listview_control(LVS_NOSORTHEADER
| LVS_REPORT
);
3810 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3812 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
3813 ok(IsWindow(header
), "header expected\n");
3815 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3816 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
3818 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3819 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_NOSORTHEADER
);
3820 /* not changed here */
3821 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3822 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
3824 DestroyWindow(hwnd
);
3827 static void test_setredraw(void)
3835 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3836 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3838 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
3839 ListView seems to handle it internally without DefWinProc */
3841 /* default value first */
3842 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3845 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3846 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
3847 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3849 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3850 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
3851 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3854 /* check update rect after redrawing */
3855 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3857 InvalidateRect(hwnd
, NULL
, FALSE
);
3858 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
3859 rect
.right
= rect
.bottom
= 1;
3860 GetUpdateRect(hwnd
, &rect
, FALSE
);
3861 expect(0, rect
.right
);
3862 expect(0, rect
.bottom
);
3865 hdc
= GetWindowDC(hwndparent
);
3866 ret
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
3868 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3870 ret
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
3872 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3874 ReleaseDC(hwndparent
, hdc
);
3876 /* check notification messages to show that repainting is disabled */
3877 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3879 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3881 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3883 InvalidateRect(hwnd
, NULL
, TRUE
);
3885 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3886 "redraw after WM_SETREDRAW (FALSE)", FALSE
);
3888 ret
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
3890 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3891 InvalidateRect(hwnd
, NULL
, TRUE
);
3893 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3894 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE
);
3896 /* message isn't forwarded to header */
3897 subclass_header(hwnd
);
3898 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3899 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3901 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, setredraw_seq
,
3902 "WM_SETREDRAW: not forwarded to header", FALSE
);
3904 DestroyWindow(hwnd
);
3907 static void test_hittest(void)
3913 static CHAR text
[] = "1234567890ABCDEFGHIJKLMNOPQRST";
3917 HIMAGELIST himl
, himl2
;
3920 hwnd
= create_listview_control(LVS_REPORT
);
3921 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3923 /* LVS_REPORT with a single subitem (2 columns) */
3924 insert_column(hwnd
, 0);
3925 insert_column(hwnd
, 1);
3926 insert_item(hwnd
, 0);
3929 /* the only purpose of that line is to be as long as a half item rect */
3930 item
.pszText
= text
;
3931 r
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
3934 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
3936 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
3939 SetRect(&bounds
, LVIR_BOUNDS
, 0, 0, 0);
3940 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&bounds
);
3942 ok(bounds
.bottom
- bounds
.top
> 0, "Expected non zero item height\n");
3943 ok(bounds
.right
- bounds
.left
> 0, "Expected non zero item width\n");
3944 r
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, TRUE
, 0);
3946 ok(bounds
.bottom
- bounds
.top
== vert
,
3947 "Vertical spacing inconsistent (%ld != %d)\n", bounds
.bottom
- bounds
.top
, vert
);
3948 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pos
);
3951 /* LVS_EX_FULLROWSELECT not set, no icons attached */
3953 /* outside columns by x position - valid is [0, 199] */
3955 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3956 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TOLEFT
, 0, FALSE
, FALSE
);
3957 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3959 x
= pos
.x
+ 50; /* column half width */
3960 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3961 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMLABEL
, 0, FALSE
, FALSE
);
3962 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3963 x
= pos
.x
+ 150; /* outside column */
3964 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3965 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
3966 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3967 y
= (bounds
.bottom
- bounds
.top
) / 2;
3968 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
3969 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3970 /* outside possible client rectangle (to right) */
3972 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3973 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
3974 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3975 y
= (bounds
.bottom
- bounds
.top
) / 2;
3976 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
3977 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3978 /* subitem returned with -1 item too */
3980 y
= bounds
.top
- vert
;
3981 test_lvm_subitemhittest(hwnd
, x
, y
, -1, 1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3982 test_lvm_subitemhittest(hwnd
, x
, y
- vert
+ 1, -1, 1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3983 /* return values appear to underflow with negative indices */
3987 test_lvm_subitemhittest(hwnd
, x
, y
, i
, 1, LVHT_ONITEMLABEL
, TRUE
, FALSE
, TRUE
);
3988 test_lvm_subitemhittest(hwnd
, x
, y
- vert
+ 1, i
, 1, LVHT_ONITEMLABEL
, TRUE
, FALSE
, TRUE
);
3992 /* parent client area is 100x100 by default */
3993 MoveWindow(hwnd
, 0, 0, 300, 100, FALSE
);
3994 x
= pos
.x
+ 150; /* outside column */
3995 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3996 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, 0, FALSE
, FALSE
);
3997 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3998 y
= (bounds
.bottom
- bounds
.top
) / 2;
3999 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, 0, FALSE
, TRUE
);
4000 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4001 /* the same with LVS_EX_FULLROWSELECT */
4002 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
4003 x
= pos
.x
+ 150; /* outside column */
4004 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4005 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEM
, LVHT_ONITEMLABEL
, FALSE
, FALSE
);
4006 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4007 y
= (bounds
.bottom
- bounds
.top
) / 2;
4008 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4009 MoveWindow(hwnd
, 0, 0, 100, 100, FALSE
);
4010 x
= pos
.x
+ 150; /* outside column */
4011 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4012 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
4013 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4014 y
= (bounds
.bottom
- bounds
.top
) / 2;
4015 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
4016 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4017 /* outside possible client rectangle (to right) */
4019 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4020 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
4021 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
4022 y
= (bounds
.bottom
- bounds
.top
) / 2;
4023 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
4024 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
4025 /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
4026 himl
= pImageList_Create(16, 16, 0, 4, 4);
4027 ok(himl
!= NULL
, "failed to create imagelist\n");
4028 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
4029 ok(hbmp
!= NULL
, "failed to create bitmap\n");
4030 r
= pImageList_Add(himl
, hbmp
, 0);
4031 ok(r
== 0, "should be zero\n");
4032 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
4033 ok(hbmp
!= NULL
, "failed to create bitmap\n");
4034 r
= pImageList_Add(himl
, hbmp
, 0);
4035 ok(r
== 1, "should be one\n");
4037 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
4040 item
.mask
= LVIF_IMAGE
;
4044 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4048 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4049 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, 0, FALSE
, FALSE
);
4050 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
4051 y
= (bounds
.bottom
- bounds
.top
) / 2;
4052 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
4054 /* state icons indices are 1 based, check with valid index */
4055 item
.mask
= LVIF_STATE
;
4056 item
.state
= INDEXTOSTATEIMAGEMASK(1);
4057 item
.stateMask
= LVIS_STATEIMAGEMASK
;
4060 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4064 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4065 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, 0, FALSE
, FALSE
);
4066 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
4067 y
= (bounds
.bottom
- bounds
.top
) / 2;
4068 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
4070 himl2
= (HIMAGELIST
)SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, 0);
4071 ok(himl2
== himl
, "should return handle\n");
4073 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
4077 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4078 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMICON
, 0, FALSE
, FALSE
);
4079 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
);
4080 y
= (bounds
.bottom
- bounds
.top
) / 2;
4081 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
);
4083 DestroyWindow(hwnd
);
4086 static void test_getviewrect(void)
4093 hwnd
= create_listview_control(LVS_REPORT
);
4094 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4097 r
= SendMessageA(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
4100 insert_column(hwnd
, 0);
4101 insert_column(hwnd
, 1);
4103 memset(&item
, 0, sizeof(item
));
4106 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4107 ok(!r
, "got %ld\n", r
);
4109 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
4111 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(120, 0));
4114 SetRect(&rect
, -1, -1, -1, -1);
4115 r
= SendMessageA(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
4117 /* left is set to (2e31-1) - XP SP2 */
4118 expect(0, rect
.right
);
4119 expect(0, rect
.top
);
4120 expect(0, rect
.bottom
);
4122 /* switch to LVS_ICON */
4123 SetWindowLongA(hwnd
, GWL_STYLE
, GetWindowLongA(hwnd
, GWL_STYLE
) & ~LVS_REPORT
);
4125 SetRect(&rect
, -1, -1, -1, -1);
4126 r
= SendMessageA(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
4128 expect(0, rect
.left
);
4129 expect(0, rect
.top
);
4130 /* precise value differs for 2k, XP and Vista */
4131 ok(rect
.bottom
> 0, "Expected positive bottom value, got %ld\n", rect
.bottom
);
4132 ok(rect
.right
> 0, "Expected positive right value, got %ld\n", rect
.right
);
4134 DestroyWindow(hwnd
);
4137 static void test_getitemposition(void)
4144 hwnd
= create_listview_control(LVS_REPORT
);
4145 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4146 header
= subclass_header(hwnd
);
4148 /* LVS_REPORT, single item, no columns added */
4149 insert_item(hwnd
, 0);
4151 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4154 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
4156 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq1
, "get item position 1", FALSE
);
4158 /* LVS_REPORT, single item, single column */
4159 insert_column(hwnd
, 0);
4161 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4164 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
4166 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq2
, "get item position 2", TRUE
);
4168 SetRectEmpty(&rect
);
4169 r
= SendMessageA(header
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4170 ok(r
, "got %ld\n", r
);
4173 /* offset by header height */
4174 expect(rect
.bottom
- rect
.top
, pt
.y
);
4176 DestroyWindow(hwnd
);
4179 static void test_getitemrect(void)
4182 HIMAGELIST himl
, himl_ret
;
4191 /* rectangle isn't empty for empty text items */
4192 hwnd
= create_listview_control(LVS_LIST
);
4193 memset(&item
, 0, sizeof(item
));
4196 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4198 rect
.left
= LVIR_LABEL
;
4199 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4201 expect(0, rect
.left
);
4202 expect(0, rect
.top
);
4203 /* estimate it as width / height ratio */
4205 ok((rect
.right
/ rect
.bottom
) >= 5, "got right %ld, bottom %ld\n", rect
.right
, rect
.bottom
);
4206 DestroyWindow(hwnd
);
4208 hwnd
= create_listview_control(LVS_REPORT
);
4209 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4212 memset(&item
, 0, sizeof(item
));
4215 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4218 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4219 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4222 /* zero width rectangle with no padding */
4223 expect(0, rect
.left
);
4224 expect(0, rect
.right
);
4226 insert_column(hwnd
, 0);
4227 insert_column(hwnd
, 1);
4229 col
.mask
= LVCF_WIDTH
;
4231 r
= SendMessageA(hwnd
, LVM_SETCOLUMNA
, 0, (LPARAM
)&col
);
4234 col
.mask
= LVCF_WIDTH
;
4236 r
= SendMessageA(hwnd
, LVM_SETCOLUMNA
, 1, (LPARAM
)&col
);
4239 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4240 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4243 /* still no left padding */
4244 expect(0, rect
.left
);
4245 expect(150, rect
.right
);
4247 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4248 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4251 expect(2, rect
.left
);
4253 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4254 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4256 /* padding, column width */
4257 expect(2, rect
.left
);
4258 expect(50, rect
.right
);
4260 /* no icons attached */
4261 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4262 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4265 expect(2, rect
.left
);
4266 expect(2, rect
.right
);
4269 order
[0] = 1; order
[1] = 0;
4270 r
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
4273 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
4275 /* 1 indexed column width + padding */
4277 /* rect is at zero too */
4278 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4279 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4281 expect(0, rect
.left
);
4282 /* just width sum */
4283 expect(150, rect
.right
);
4285 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4286 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4288 /* column width + padding */
4289 expect(102, rect
.left
);
4291 /* back to initial order */
4292 order
[0] = 0; order
[1] = 1;
4293 r
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
4297 himl
= pImageList_Create(16, 16, 0, 2, 2);
4298 ok(himl
!= NULL
, "failed to create imagelist\n");
4299 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
4300 ok(hbm
!= NULL
, "failed to create bitmap\n");
4301 r
= pImageList_Add(himl
, hbm
, 0);
4303 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
4304 ok(hbm
!= NULL
, "failed to create bitmap\n");
4305 r
= pImageList_Add(himl
, hbm
, 0);
4308 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
4311 item
.mask
= LVIF_STATE
;
4312 item
.state
= INDEXTOSTATEIMAGEMASK(1);
4313 item
.stateMask
= LVIS_STATEIMAGEMASK
;
4316 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4320 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4321 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4323 /* padding + stateicon width */
4324 expect(18, rect
.left
);
4325 expect(18, rect
.right
);
4327 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4328 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4330 /* padding + stateicon width -> column width */
4331 expect(18, rect
.left
);
4332 expect(50, rect
.right
);
4334 himl_ret
= (HIMAGELIST
)SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, 0);
4335 ok(himl_ret
== himl
, "got %p, expected %p\n", himl_ret
, himl
);
4337 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
4340 item
.mask
= LVIF_STATE
| LVIF_IMAGE
;
4343 item
.stateMask
= ~0;
4346 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4350 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4351 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4353 /* padding, icon width */
4354 expect(2, rect
.left
);
4355 expect(18, rect
.right
);
4357 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4358 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4360 /* padding + icon width -> column width */
4361 expect(18, rect
.left
);
4362 expect(50, rect
.right
);
4365 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4366 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4368 /* padding, column width */
4369 expect(2, rect
.left
);
4370 expect(50, rect
.right
);
4372 /* try with indentation */
4373 item
.mask
= LVIF_INDENT
;
4377 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4381 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4382 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4384 /* padding + 1 icon width, column width */
4385 expect(0, rect
.left
);
4386 expect(150, rect
.right
);
4389 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4390 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4392 /* padding + 1 icon width, column width */
4393 expect(2 + 16, rect
.left
);
4394 expect(50, rect
.right
);
4397 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4398 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4400 /* padding + 2 icon widths, column width */
4401 expect(2 + 16*2, rect
.left
);
4402 expect(50, rect
.right
);
4405 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4406 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4408 /* padding + 1 icon width indentation, icon width */
4409 expect(2 + 16, rect
.left
);
4410 expect(34, rect
.right
);
4412 DestroyWindow(hwnd
);
4415 static void test_editbox(void)
4417 static CHAR testitemA
[] = "testitem";
4418 static CHAR testitem1A
[] = "testitem_quitelongname";
4419 static CHAR testitem2A
[] = "testITEM_quitelongname";
4420 static CHAR buffer
[25];
4421 HWND hwnd
, hwndedit
, hwndedit2
, header
;
4425 hwnd
= create_listview_control(LVS_EDITLABELS
| LVS_REPORT
);
4426 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4428 insert_column(hwnd
, 0);
4430 memset(&item
, 0, sizeof(item
));
4431 item
.mask
= LVIF_TEXT
;
4432 item
.pszText
= testitemA
;
4435 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4438 /* test notifications without edit created */
4439 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4440 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_SETFOCUS
), (LPARAM
)0xdeadbeef);
4442 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
4443 "edit box WM_COMMAND (EN_SETFOCUS), no edit created", FALSE
);
4444 /* same thing but with valid window */
4445 hwndedit
= CreateWindowA(WC_EDITA
, "Test edit", WS_VISIBLE
| WS_CHILD
, 0, 0, 20,
4446 10, hwnd
, (HMENU
)1, (HINSTANCE
)GetWindowLongPtrA(hwnd
, GWLP_HINSTANCE
), 0);
4447 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4448 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_SETFOCUS
), (LPARAM
)hwndedit
);
4450 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
4451 "edit box WM_COMMAND (EN_SETFOCUS), no edit created #2", FALSE
);
4452 DestroyWindow(hwndedit
);
4454 /* setting focus is necessary */
4456 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4457 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4459 /* test children Z-order after Edit box created */
4460 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4461 ok(IsWindow(header
), "Expected header to be created\n");
4462 ok(GetTopWindow(hwnd
) == header
, "Expected header to be on top\n");
4463 ok(GetNextWindow(header
, GW_HWNDNEXT
) == hwndedit
, "got %p\n", GetNextWindow(header
, GW_HWNDNEXT
));
4465 /* modify initial string */
4466 r
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
4469 /* edit window is resized and repositioned,
4470 check again for Z-order - it should be preserved */
4471 ok(GetTopWindow(hwnd
) == header
, "Expected header to be on top\n");
4472 ok(GetNextWindow(header
, GW_HWNDNEXT
) == hwndedit
, "got %p\n", GetNextWindow(header
, GW_HWNDNEXT
));
4474 /* return focus to listview */
4477 memset(&item
, 0, sizeof(item
));
4478 item
.mask
= LVIF_TEXT
;
4479 item
.pszText
= buffer
;
4480 item
.cchTextMax
= sizeof(buffer
);
4483 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
4486 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
4488 /* send LVM_EDITLABEL on already created edit */
4490 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4491 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4492 /* focus will be set to edit */
4493 ok(GetFocus() == hwndedit
, "Expected Edit window to be focused\n");
4494 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4495 ok(IsWindow(hwndedit2
), "Expected Edit window to be created\n");
4497 /* creating label disabled when control isn't focused */
4499 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4500 todo_wine
ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
4502 /* check EN_KILLFOCUS handling */
4503 memset(&item
, 0, sizeof(item
));
4504 item
.pszText
= testitemA
;
4507 r
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
4511 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4512 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4513 /* modify edit and notify control that it lost focus */
4514 r
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
4516 g_editbox_disp_info
.item
.pszText
= NULL
;
4517 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
4519 ok(g_editbox_disp_info
.item
.pszText
!= NULL
, "expected notification with not null text\n");
4521 memset(&item
, 0, sizeof(item
));
4522 item
.pszText
= buffer
;
4523 item
.cchTextMax
= sizeof(buffer
);
4526 r
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
4527 expect(lstrlenA(item
.pszText
), r
);
4528 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
4529 ok(!IsWindow(hwndedit
), "Expected Edit window to be freed\n");
4531 /* change item name to differ in casing only */
4533 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4534 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4535 /* modify edit and notify control that it lost focus */
4536 r
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem2A
);
4538 g_editbox_disp_info
.item
.pszText
= NULL
;
4539 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
4541 ok(g_editbox_disp_info
.item
.pszText
!= NULL
, "got %p\n", g_editbox_disp_info
.item
.pszText
);
4543 memset(&item
, 0, sizeof(item
));
4544 item
.pszText
= buffer
;
4545 item
.cchTextMax
= sizeof(buffer
);
4548 r
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
4549 expect(lstrlenA(item
.pszText
), r
);
4550 ok(strcmp(buffer
, testitem2A
) == 0, "got %s, expected %s\n", buffer
, testitem2A
);
4551 ok(!IsWindow(hwndedit
), "Expected Edit window to be freed\n");
4553 /* end edit without saving */
4555 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4556 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4557 r
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_ESCAPE
, 0);
4559 ok_sequence(sequences
, PARENT_SEQ_INDEX
, edit_end_nochange
,
4560 "edit box - end edit, no change, escape", TRUE
);
4561 /* end edit with saving */
4563 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4564 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4565 r
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_RETURN
, 0);
4567 ok_sequence(sequences
, PARENT_SEQ_INDEX
, edit_end_nochange
,
4568 "edit box - end edit, no change, return", TRUE
);
4570 memset(&item
, 0, sizeof(item
));
4571 item
.pszText
= buffer
;
4572 item
.cchTextMax
= sizeof(buffer
);
4575 r
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
4576 expect(lstrlenA(item
.pszText
), r
);
4577 ok(strcmp(buffer
, testitem2A
) == 0, "Expected item text to change\n");
4579 /* LVM_EDITLABEL with -1 destroys current edit */
4580 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_GETEDITCONTROL
, 0, 0);
4581 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
4582 /* no edit present */
4583 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, -1, 0);
4584 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
4585 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4586 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4588 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
4589 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, -1, 0);
4590 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
4591 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
4592 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
4593 /* check another negative value */
4594 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4595 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4596 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
4597 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, -2, 0);
4598 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
4599 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
4600 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
4601 /* and value greater than max item index */
4602 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4603 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4604 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
4605 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
4606 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, r
, 0);
4607 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
4608 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
4609 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
4611 /* messaging tests */
4613 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4615 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4616 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4617 /* testing only sizing messages */
4618 ok_sequence(sequences
, EDITBOX_SEQ_INDEX
, editbox_create_pos
,
4619 "edit box create - sizing", FALSE
);
4621 /* WM_COMMAND with EN_KILLFOCUS isn't forwarded to parent */
4623 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4624 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4625 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4626 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
4628 ok_sequence(sequences
, PARENT_SEQ_INDEX
, edit_end_nochange
,
4629 "edit box WM_COMMAND (EN_KILLFOCUS)", TRUE
);
4631 DestroyWindow(hwnd
);
4634 static void test_notifyformat(void)
4639 hwnd
= create_listview_control(LVS_REPORT
);
4640 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4642 /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
4643 CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
4644 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4646 SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
4648 r
= SendMessageA(hwnd
, LVM_SETUNICODEFORMAT
, 1, 0);
4650 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4651 ok(r
== 1, "Unexpected return value %ld.\n", r
);
4652 r
= SendMessageA(hwnd
, LVM_SETUNICODEFORMAT
, 0, 0);
4654 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4657 DestroyWindow(hwnd
);
4659 /* test failure in parent WM_NOTIFYFORMAT */
4661 hwnd
= create_listview_control(LVS_REPORT
);
4662 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4663 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4664 ok(IsWindow(header
), "expected header to be created\n");
4665 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4667 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4668 ok( r
== 1, "Expected 1, got %ld\n", r
);
4669 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
4670 ok(r
!= 0, "Expected valid format\n");
4672 notifyFormat
= NFR_UNICODE
;
4673 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
4674 expect(NFR_UNICODE
, r
);
4675 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4677 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4678 ok( r
== 1, "Expected 1, got %ld\n", r
);
4680 notifyFormat
= NFR_ANSI
;
4681 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
4682 expect(NFR_ANSI
, r
);
4683 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4685 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4686 ok( r
== 1, "Expected 1, got %ld\n", r
);
4688 DestroyWindow(hwnd
);
4690 hwndparentW
= create_parent_window(TRUE
);
4691 ok(IsWindow(hwndparentW
), "Unicode parent creation failed\n");
4692 if (!IsWindow(hwndparentW
)) return;
4695 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparentW
);
4696 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4697 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4698 ok(IsWindow(header
), "expected header to be created\n");
4699 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4701 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4703 DestroyWindow(hwnd
);
4704 /* receiving error code defaulting to ansi */
4706 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparentW
);
4707 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4708 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4709 ok(IsWindow(header
), "expected header to be created\n");
4710 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4712 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4714 DestroyWindow(hwnd
);
4715 /* receiving ansi code from unicode window, use it */
4716 notifyFormat
= NFR_ANSI
;
4717 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparentW
);
4718 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4719 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4720 ok(IsWindow(header
), "expected header to be created\n");
4721 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4723 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4725 DestroyWindow(hwnd
);
4726 /* unicode listview with ansi parent window */
4728 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparent
);
4729 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4730 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4731 ok(IsWindow(header
), "expected header to be created\n");
4732 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4734 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4736 DestroyWindow(hwnd
);
4737 /* unicode listview with ansi parent window, return error code */
4739 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparent
);
4740 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4741 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4742 ok(IsWindow(header
), "expected header to be created\n");
4743 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4745 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4747 DestroyWindow(hwnd
);
4749 DestroyWindow(hwndparentW
);
4752 static void test_indentation(void)
4758 hwnd
= create_listview_control(LVS_REPORT
);
4759 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4761 memset(&item
, 0, sizeof(item
));
4762 item
.mask
= LVIF_INDENT
;
4764 item
.iIndent
= I_INDENTCALLBACK
;
4765 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4768 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4771 item
.mask
= LVIF_INDENT
;
4772 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
4775 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
4776 "get indent dispinfo", FALSE
);
4778 /* Ask for iIndent with invalid subitem. */
4779 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4781 memset(&item
, 0, sizeof(item
));
4782 item
.mask
= LVIF_INDENT
;
4784 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
4785 ok(r
, "Failed to get item.\n");
4787 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "get indent dispinfo 2", FALSE
);
4789 DestroyWindow(hwnd
);
4792 static void test_get_set_view(void)
4798 /* test style->view mapping */
4799 hwnd
= create_listview_control(LVS_REPORT
);
4800 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4802 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4803 expect(LV_VIEW_DETAILS
, ret
);
4805 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4807 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_REPORT
);
4808 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4809 expect(LV_VIEW_ICON
, ret
);
4811 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4812 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SMALLICON
);
4813 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4814 expect(LV_VIEW_SMALLICON
, ret
);
4816 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4817 SetWindowLongPtrA(hwnd
, GWL_STYLE
, (style
& ~LVS_SMALLICON
) | LVS_LIST
);
4818 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4819 expect(LV_VIEW_LIST
, ret
);
4821 /* switching view doesn't touch window style */
4822 ret
= SendMessageA(hwnd
, LVM_SETVIEW
, LV_VIEW_DETAILS
, 0);
4824 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4825 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
4826 ret
= SendMessageA(hwnd
, LVM_SETVIEW
, LV_VIEW_ICON
, 0);
4828 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4829 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
4830 ret
= SendMessageA(hwnd
, LVM_SETVIEW
, LV_VIEW_SMALLICON
, 0);
4832 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4833 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
4835 /* now change window style to see if view is remapped */
4836 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4837 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SHOWSELALWAYS
);
4838 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4839 expect(LV_VIEW_SMALLICON
, ret
);
4841 DestroyWindow(hwnd
);
4844 static void test_canceleditlabel(void)
4846 HWND hwnd
, hwndedit
;
4850 static CHAR test
[] = "test";
4851 static const CHAR test1
[] = "test1";
4853 hwnd
= create_listview_control(LVS_EDITLABELS
| LVS_REPORT
);
4854 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4856 insert_item(hwnd
, 0);
4858 /* try without edit created */
4859 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4860 ret
= SendMessageA(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
4862 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
4863 "cancel edit label without edit", FALSE
);
4865 /* cancel without data change */
4867 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4868 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
4869 ret
= SendMessageA(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
4871 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
4873 /* cancel after data change */
4874 memset(&itema
, 0, sizeof(itema
));
4875 itema
.pszText
= test
;
4876 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&itema
);
4879 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4880 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
4881 ret
= SetWindowTextA(hwndedit
, test1
);
4883 ret
= SendMessageA(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
4885 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
4886 memset(&itema
, 0, sizeof(itema
));
4887 itema
.pszText
= buff
;
4888 itema
.cchTextMax
= ARRAY_SIZE(buff
);
4889 ret
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&itema
);
4891 ok(strcmp(buff
, test1
) == 0, "Expected label text not to change\n");
4893 DestroyWindow(hwnd
);
4896 static void test_mapidindex(void)
4901 /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
4902 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
4903 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4904 insert_item(hwnd
, 0);
4905 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4907 DestroyWindow(hwnd
);
4909 hwnd
= create_listview_control(LVS_REPORT
);
4910 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4912 /* LVM_MAPINDEXTOID with invalid index */
4913 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4916 insert_item(hwnd
, 0);
4917 insert_item(hwnd
, 1);
4919 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, -1, 0);
4921 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 2, 0);
4924 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4926 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
4928 /* remove 0 indexed item, id retained */
4929 SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
4930 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4932 /* new id starts from previous value */
4933 insert_item(hwnd
, 1);
4934 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
4937 /* get index by id */
4938 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, -1, 0);
4940 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, 0, 0);
4942 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, 1, 0);
4944 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, 2, 0);
4947 DestroyWindow(hwnd
);
4950 static void test_getitemspacing(void)
4955 HIMAGELIST himl40
, himl80
;
4957 cx
= GetSystemMetrics(SM_CXICONSPACING
) - GetSystemMetrics(SM_CXICON
);
4958 cy
= GetSystemMetrics(SM_CYICONSPACING
) - GetSystemMetrics(SM_CYICON
);
4961 hwnd
= create_listview_control(LVS_ICON
);
4962 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4963 expect(cx
, LOWORD(ret
));
4964 expect(cy
, HIWORD(ret
));
4966 /* now try with icons */
4967 himl40
= pImageList_Create(40, 40, 0, 4, 4);
4968 ok(himl40
!= NULL
, "failed to create imagelist\n");
4969 himl80
= pImageList_Create(80, 80, 0, 4, 4);
4970 ok(himl80
!= NULL
, "failed to create imagelist\n");
4971 ret
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl40
);
4974 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4975 /* spacing + icon size returned */
4976 expect(cx
+ 40, LOWORD(ret
));
4977 expect(cy
+ 40, HIWORD(ret
));
4978 /* try changing icon size */
4979 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl80
);
4981 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4982 /* spacing + icon size returned */
4983 expect(cx
+ 80, LOWORD(ret
));
4984 expect(cy
+ 80, HIWORD(ret
));
4986 /* set own icon spacing */
4987 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(100, 100));
4988 expect(cx
+ 80, LOWORD(ret
));
4989 expect(cy
+ 80, HIWORD(ret
));
4991 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4992 /* set size returned */
4993 expect(100, LOWORD(ret
));
4994 expect(100, HIWORD(ret
));
4996 /* now change image list - icon spacing should be unaffected */
4997 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl40
);
4999 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5000 /* set size returned */
5001 expect(100, LOWORD(ret
));
5002 expect(100, HIWORD(ret
));
5004 /* spacing = 0 - keep previous value */
5005 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(0, -1));
5006 expect(100, LOWORD(ret
));
5007 expect(100, HIWORD(ret
));
5009 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5010 expect(100, LOWORD(ret
));
5012 expect(0xFFFF, HIWORD(ret
));
5014 if (sizeof(void*) == 8)
5016 /* NOTE: -1 is not treated the same as (DWORD)-1 by 64bit listview */
5017 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, (DWORD
)-1);
5018 expect(100, LOWORD(ret
));
5019 expect(0xFFFF, HIWORD(ret
));
5021 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, -1);
5022 expect(0xFFFF, LOWORD(ret
));
5023 expect(0xFFFF, HIWORD(ret
));
5027 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, -1);
5028 expect(100, LOWORD(ret
));
5029 expect(0xFFFF, HIWORD(ret
));
5031 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5032 /* spacing + icon size returned */
5033 expect(cx
+ 40, LOWORD(ret
));
5034 expect(cy
+ 40, HIWORD(ret
));
5036 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, 0);
5037 pImageList_Destroy(himl80
);
5038 DestroyWindow(hwnd
);
5040 hwnd
= create_listview_control(LVS_SMALLICON
);
5041 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5042 expect(cx
, LOWORD(ret
));
5043 expect(cy
, HIWORD(ret
));
5045 /* spacing does not depend on selected view type */
5046 ret
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl40
);
5049 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5050 /* spacing + icon size returned */
5051 expect(cx
+ 40, LOWORD(ret
));
5052 expect(cy
+ 40, HIWORD(ret
));
5054 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, 0);
5055 pImageList_Destroy(himl40
);
5056 DestroyWindow(hwnd
);
5058 hwnd
= create_listview_control(LVS_REPORT
);
5059 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5060 expect(cx
, LOWORD(ret
));
5061 expect(cy
, HIWORD(ret
));
5063 DestroyWindow(hwnd
);
5065 hwnd
= create_listview_control(LVS_LIST
);
5066 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5067 expect(cx
, LOWORD(ret
));
5068 expect(cy
, HIWORD(ret
));
5070 DestroyWindow(hwnd
);
5073 static INT
get_current_font_height(HWND listview
)
5080 hwnd
= (HWND
)SendMessageA(listview
, LVM_GETHEADER
, 0, 0);
5084 hfont
= (HFONT
)SendMessageA(hwnd
, WM_GETFONT
, 0, 0);
5087 GetTextMetricsA(hdc
, &tm
);
5088 ReleaseDC(hwnd
, hdc
);
5094 oldfont
= SelectObject(hdc
, hfont
);
5095 GetTextMetricsA(hdc
, &tm
);
5096 SelectObject(hdc
, oldfont
);
5103 static void test_getcolumnwidth(void)
5112 /* default column width */
5113 hwnd
= create_listview_control(LVS_ICON
);
5114 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
5116 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5117 SetWindowLongA(hwnd
, GWL_STYLE
, style
| LVS_LIST
);
5118 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
5119 todo_wine
expect(8, ret
);
5120 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~LVS_LIST
;
5121 SetWindowLongA(hwnd
, GWL_STYLE
, style
| LVS_REPORT
);
5123 ret
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5125 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
5127 DestroyWindow(hwnd
);
5129 /* default column width with item added */
5130 hwnd
= create_listview_control(LVS_LIST
);
5131 memset(&itema
, 0, sizeof(itema
));
5132 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&itema
);
5133 ok(!ret
, "got %d\n", ret
);
5134 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
5135 height
= get_current_font_height(hwnd
);
5136 ok((ret
/ height
) >= 6, "got width %d, height %d\n", ret
, height
);
5137 DestroyWindow(hwnd
);
5140 static void test_scrollnotify(void)
5145 hwnd
= create_listview_control(LVS_REPORT
);
5147 insert_column(hwnd
, 0);
5148 insert_column(hwnd
, 1);
5149 insert_item(hwnd
, 0);
5151 /* make it scrollable - resize */
5152 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
5154 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
5157 /* try with dummy call */
5158 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5159 ret
= SendMessageA(hwnd
, LVM_SCROLL
, 0, 0);
5161 ok_sequence(sequences
, PARENT_SEQ_INDEX
, scroll_parent_seq
,
5162 "scroll notify 1", TRUE
);
5164 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5165 ret
= SendMessageA(hwnd
, LVM_SCROLL
, 1, 0);
5167 ok_sequence(sequences
, PARENT_SEQ_INDEX
, scroll_parent_seq
,
5168 "scroll notify 2", TRUE
);
5170 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5171 ret
= SendMessageA(hwnd
, LVM_SCROLL
, 1, 1);
5173 ok_sequence(sequences
, PARENT_SEQ_INDEX
, scroll_parent_seq
,
5174 "scroll notify 3", TRUE
);
5176 DestroyWindow(hwnd
);
5179 static void test_LVS_EX_TRANSPARENTBKGND(void)
5185 hwnd
= create_listview_control(LVS_REPORT
);
5187 ret
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, RGB(0, 0, 0));
5190 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_TRANSPARENTBKGND
,
5191 LVS_EX_TRANSPARENTBKGND
);
5193 ret
= SendMessageA(hwnd
, LVM_GETBKCOLOR
, 0, 0);
5194 if (ret
!= CLR_NONE
)
5196 win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n");
5197 DestroyWindow(hwnd
);
5201 /* try to set some back color and check this style bit */
5202 ret
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, RGB(0, 0, 0));
5204 ret
= SendMessageA(hwnd
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
5205 ok(!(ret
& LVS_EX_TRANSPARENTBKGND
), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
5207 /* now test what this style actually does */
5208 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_TRANSPARENTBKGND
,
5209 LVS_EX_TRANSPARENTBKGND
);
5211 hdc
= GetWindowDC(hwndparent
);
5213 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5214 SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
5215 ok_sequence(sequences
, PARENT_SEQ_INDEX
, lvs_ex_transparentbkgnd_seq
,
5216 "LVS_EX_TRANSPARENTBKGND parent", FALSE
);
5218 ReleaseDC(hwndparent
, hdc
);
5220 DestroyWindow(hwnd
);
5223 static void test_approximate_viewrect(void)
5225 static CHAR test
[] = "abracadabra, a very long item label";
5226 DWORD item_width
, item_height
, header_height
;
5227 static CHAR column_header
[] = "Header";
5228 unsigned const column_width
= 100;
5229 DWORD ret
, item_count
;
5237 hwnd
= create_listview_control(LVS_ICON
);
5238 himl
= pImageList_Create(40, 40, 0, 4, 4);
5239 ok(himl
!= NULL
, "failed to create imagelist\n");
5240 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
5241 ok(hbmp
!= NULL
, "failed to create bitmap\n");
5242 ret
= pImageList_Add(himl
, hbmp
, 0);
5244 ret
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
5247 itema
.mask
= LVIF_IMAGE
;
5251 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&itema
);
5254 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(75, 75));
5255 ok(ret
!= 0, "Unexpected return value %#lx.\n", ret
);
5257 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 11, MAKELPARAM(100,100));
5258 expect(MAKELONG(77,827), ret
);
5260 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(50, 50));
5261 ok(ret
!= 0, "got 0\n");
5263 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 11, MAKELPARAM(100,100));
5264 expect(MAKELONG(102,302), ret
);
5266 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, MAKELPARAM(100,100));
5267 expect(MAKELONG(52,52), ret
);
5269 itema
.pszText
= test
;
5270 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&itema
);
5272 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, MAKELPARAM(100,100));
5273 expect(MAKELONG(52,52), ret
);
5275 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, MAKELPARAM(100,100));
5276 expect(MAKELONG(52,2), ret
);
5277 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 1, MAKELPARAM(100,100));
5278 expect(MAKELONG(52,52), ret
);
5279 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, MAKELPARAM(100,100));
5280 expect(MAKELONG(102,52), ret
);
5281 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 3, MAKELPARAM(100,100));
5282 expect(MAKELONG(102,102), ret
);
5283 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 4, MAKELPARAM(100,100));
5284 expect(MAKELONG(102,102), ret
);
5285 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 5, MAKELPARAM(100,100));
5286 expect(MAKELONG(102,152), ret
);
5287 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 6, MAKELPARAM(100,100));
5288 expect(MAKELONG(102,152), ret
);
5289 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 7, MAKELPARAM(160,100));
5290 expect(MAKELONG(152,152), ret
);
5292 DestroyWindow(hwnd
);
5295 hwnd
= create_listview_control(LVS_REPORT
);
5297 /* Empty control without columns */
5298 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, MAKELPARAM(100, 100));
5300 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5301 ok(HIWORD(ret
) != 0, "Unexpected height %d.\n", HIWORD(ret
));
5303 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, 0);
5304 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5306 ok(HIWORD(ret
) != 0, "Unexpected height %d.\n", HIWORD(ret
));
5308 header_height
= HIWORD(ret
);
5310 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 1, 0);
5311 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5313 ok(HIWORD(ret
) > header_height
, "Unexpected height %d.\n", HIWORD(ret
));
5315 item_height
= HIWORD(ret
) - header_height
;
5317 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, 0);
5318 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5319 ok(HIWORD(ret
) == (header_height
- 2 * item_height
), "Unexpected height %d.\n", HIWORD(ret
)) ;
5321 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, 0);
5322 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5323 ok(HIWORD(ret
) == header_height
, "Unexpected height.\n");
5324 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, 0);
5325 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5326 ok(HIWORD(ret
) == header_height
+ 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5329 col
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
5330 col
.pszText
= column_header
;
5331 col
.cx
= column_width
;
5332 ret
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5333 ok(ret
== 0, "Unexpected return value %ld.\n", ret
);
5335 /* Empty control with column */
5336 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, 0);
5338 ok(LOWORD(ret
) >= column_width
, "Unexpected width %d.\n", LOWORD(ret
));
5339 ok(HIWORD(ret
) != 0, "Unexpected height %d.\n", HIWORD(ret
));
5341 header_height
= HIWORD(ret
);
5342 item_width
= LOWORD(ret
);
5344 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 1, 0);
5345 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5347 ok(HIWORD(ret
) > header_height
, "Unexpected height %d.\n", HIWORD(ret
));
5349 item_height
= HIWORD(ret
) - header_height
;
5351 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, 0);
5352 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5353 ok(HIWORD(ret
) == header_height
- 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5355 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, 0);
5356 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5357 ok(HIWORD(ret
) == header_height
, "Unexpected height %d.\n", HIWORD(ret
));
5359 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, 0);
5360 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5361 ok(HIWORD(ret
) == header_height
+ 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5363 for (item_count
= 1; item_count
<= 2; ++item_count
)
5365 itema
.mask
= LVIF_TEXT
;
5368 itema
.pszText
= test
;
5369 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&itema
);
5370 ok(ret
== 0, "Unexpected return value %ld.\n", ret
);
5372 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, 0);
5373 ok(LOWORD(ret
) >= column_width
, "Unexpected width %d.\n", LOWORD(ret
));
5375 ok(HIWORD(ret
) != 0, "Unexpected height %d.\n", HIWORD(ret
));
5377 header_height
= HIWORD(ret
);
5378 item_width
= LOWORD(ret
);
5380 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 1, 0);
5381 ok(LOWORD(ret
) == item_width
, "Unexpected width %d, item %ld\n", LOWORD(ret
), item_count
- 1);
5382 ok(HIWORD(ret
) > header_height
, "Unexpected height %d. item %ld.\n", HIWORD(ret
), item_count
- 1);
5384 item_height
= HIWORD(ret
) - header_height
;
5386 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, 0);
5387 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5389 ok(HIWORD(ret
) == header_height
- 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5391 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, 0);
5392 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5393 ok(HIWORD(ret
) == header_height
+ item_count
* item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5395 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, 0);
5396 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5397 ok(HIWORD(ret
) == header_height
+ 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5399 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, MAKELONG(item_width
* 2, header_height
+ 3 * item_height
));
5400 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5401 ok(HIWORD(ret
) == header_height
+ 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5403 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, MAKELONG(item_width
* 2, 0));
5404 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5406 ok(HIWORD(ret
) == header_height
- 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5408 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, MAKELONG(-1, -1));
5409 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5411 ok(HIWORD(ret
) == header_height
- 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5414 DestroyWindow(hwnd
);
5418 static void test_finditem(void)
5425 hwnd
= create_listview_control(LVS_REPORT
);
5426 insert_item(hwnd
, 0);
5428 memset(&fi
, 0, sizeof(fi
));
5430 /* full string search, inserted text was "foo" */
5432 fi
.flags
= LVFI_STRING
;
5434 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5437 fi
.flags
= LVFI_STRING
| LVFI_PARTIAL
;
5438 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5441 fi
.flags
= LVFI_PARTIAL
;
5442 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5445 /* partial string search, inserted text was "foo" */
5447 fi
.flags
= LVFI_STRING
| LVFI_PARTIAL
;
5449 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5452 fi
.flags
= LVFI_STRING
;
5453 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5456 fi
.flags
= LVFI_PARTIAL
;
5457 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5460 /* partial string search, part after start char */
5462 fi
.flags
= LVFI_STRING
| LVFI_PARTIAL
;
5464 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5467 /* try with LVFI_SUBSTRING */
5469 fi
.flags
= LVFI_SUBSTRING
;
5471 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5474 fi
.flags
= LVFI_SUBSTRING
;
5476 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5479 fi
.flags
= LVFI_SUBSTRING
;
5481 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5485 fi
.flags
= LVFI_SUBSTRING
| LVFI_PARTIAL
;
5487 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5491 fi
.flags
= LVFI_SUBSTRING
| LVFI_STRING
;
5493 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5496 fi
.flags
= LVFI_SUBSTRING
| LVFI_PARTIAL
;
5497 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5500 /* Case sensitivity. */
5502 fi
.flags
= LVFI_STRING
;
5504 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5505 ok(!r
, "Unexpected item index %d.\n", r
);
5508 fi
.flags
= LVFI_SUBSTRING
;
5510 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5511 ok(!r
, "Unexpected item index %d.\n", r
);
5513 DestroyWindow(hwnd
);
5516 static void test_LVS_EX_HEADERINALLVIEWS(void)
5521 hwnd
= create_listview_control(LVS_ICON
);
5523 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5524 LVS_EX_HEADERINALLVIEWS
);
5526 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5527 if (!IsWindow(header
))
5529 win_skip("LVS_EX_HEADERINALLVIEWS unsupported\n");
5530 DestroyWindow(hwnd
);
5534 /* LVS_NOCOLUMNHEADER works as before */
5535 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5536 SetWindowLongW(hwnd
, GWL_STYLE
, style
| LVS_NOCOLUMNHEADER
);
5537 style
= GetWindowLongA(header
, GWL_STYLE
);
5538 ok(style
& HDS_HIDDEN
, "Expected HDS_HIDDEN\n");
5539 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5540 SetWindowLongW(hwnd
, GWL_STYLE
, style
& ~LVS_NOCOLUMNHEADER
);
5541 style
= GetWindowLongA(header
, GWL_STYLE
);
5542 ok(!(style
& HDS_HIDDEN
), "Expected HDS_HIDDEN to be unset\n");
5544 /* try to remove style */
5545 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
, 0);
5546 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5547 ok(IsWindow(header
), "Expected header to be created\n");
5548 style
= GetWindowLongA(header
, GWL_STYLE
);
5549 ok(!(style
& HDS_HIDDEN
), "HDS_HIDDEN not expected\n");
5551 DestroyWindow(hwnd
);
5553 /* check other styles */
5554 hwnd
= create_listview_control(LVS_LIST
);
5555 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5556 LVS_EX_HEADERINALLVIEWS
);
5557 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5558 ok(IsWindow(header
), "Expected header to be created\n");
5559 DestroyWindow(hwnd
);
5561 hwnd
= create_listview_control(LVS_SMALLICON
);
5562 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5563 LVS_EX_HEADERINALLVIEWS
);
5564 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5565 ok(IsWindow(header
), "Expected header to be created\n");
5566 DestroyWindow(hwnd
);
5568 hwnd
= create_listview_control(LVS_REPORT
);
5569 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5570 LVS_EX_HEADERINALLVIEWS
);
5571 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5572 ok(IsWindow(header
), "Expected header to be created\n");
5573 DestroyWindow(hwnd
);
5576 static void test_hover(void)
5581 hwnd
= create_listview_control(LVS_ICON
);
5582 SetForegroundWindow(hwndparent
);
5583 fg
= GetForegroundWindow();
5584 if (fg
!= hwndparent
)
5586 skip("Window is not in the foreground. Skipping hover tests.\n");
5587 DestroyWindow(hwnd
);
5591 /* test WM_MOUSEHOVER forwarding */
5592 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5593 r
= SendMessageA(hwnd
, WM_MOUSEHOVER
, 0, 0);
5595 ok_sequence(sequences
, PARENT_SEQ_INDEX
, hover_parent
, "NM_HOVER allow test", TRUE
);
5596 g_block_hover
= TRUE
;
5597 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5598 r
= SendMessageA(hwnd
, WM_MOUSEHOVER
, 0, 0);
5600 ok_sequence(sequences
, PARENT_SEQ_INDEX
, hover_parent
, "NM_HOVER block test", TRUE
);
5601 g_block_hover
= FALSE
;
5603 r
= SendMessageA(hwnd
, LVM_SETHOVERTIME
, 0, 500);
5604 expect(HOVER_DEFAULT
, r
);
5605 r
= SendMessageA(hwnd
, LVM_GETHOVERTIME
, 0, 0);
5608 DestroyWindow(hwnd
);
5611 static void test_destroynotify(void)
5616 hwnd
= create_listview_control(LVS_REPORT
);
5617 ok(hwnd
!= NULL
, "failed to create listview window\n");
5619 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5620 DestroyWindow(hwnd
);
5621 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, listview_destroy
, "check destroy order", FALSE
);
5623 /* same for ownerdata list */
5624 hwnd
= create_listview_control(LVS_REPORT
|LVS_OWNERDATA
);
5625 ok(hwnd
!= NULL
, "failed to create listview window\n");
5627 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5628 DestroyWindow(hwnd
);
5629 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, listview_ownerdata_destroy
, "check destroy order, ownerdata", FALSE
);
5631 hwnd
= create_listview_control(LVS_REPORT
|LVS_OWNERDATA
);
5632 ok(hwnd
!= NULL
, "failed to create listview window\n");
5634 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5635 ret
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
5636 ok(ret
== TRUE
, "got %d\n", ret
);
5637 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, listview_ownerdata_deleteall
, "deleteall ownerdata", FALSE
);
5638 DestroyWindow(hwnd
);
5641 static void test_header_notification(void)
5643 static char textA
[] = "newtext";
5651 list
= create_listview_control(LVS_REPORT
);
5652 ok(list
!= NULL
, "failed to create listview window\n");
5654 memset(&col
, 0, sizeof(col
));
5655 col
.mask
= LVCF_WIDTH
;
5657 ret
= SendMessageA(list
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5660 /* check list parent notification after header item changed,
5661 this test should be placed before header subclassing to avoid
5662 Listview -> Header messages to be logged */
5663 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5665 col
.mask
= LVCF_TEXT
;
5666 col
.pszText
= textA
;
5667 r
= SendMessageA(list
, LVM_SETCOLUMNA
, 0, (LPARAM
)&col
);
5670 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_header_changed_seq
,
5671 "header notify, listview", FALSE
);
5672 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5673 "header notify, parent", FALSE
);
5675 header
= subclass_header(list
);
5677 ret
= SendMessageA(header
, HDM_GETITEMCOUNT
, 0, 0);
5680 memset(&item
, 0, sizeof(item
));
5681 item
.mask
= HDI_WIDTH
;
5682 ret
= SendMessageA(header
, HDM_GETITEMA
, 0, (LPARAM
)&item
);
5684 expect(100, item
.cxy
);
5686 nmh
.hdr
.hwndFrom
= header
;
5687 nmh
.hdr
.idFrom
= GetWindowLongPtrA(header
, GWLP_ID
);
5688 nmh
.hdr
.code
= HDN_ITEMCHANGEDA
;
5691 item
.mask
= HDI_WIDTH
;
5694 ret
= SendMessageA(list
, WM_NOTIFY
, 0, (LPARAM
)&nmh
);
5697 DestroyWindow(list
);
5700 static void test_header_notification2(void)
5702 static char textA
[] = "newtext";
5709 struct message parent_header_notify_seq
[] = {
5710 { WM_NOTIFY
, sent
|id
, 0, 0, 0 },
5714 list
= create_listview_control(LVS_REPORT
);
5715 ok(list
!= NULL
, "failed to create listview window\n");
5717 memset(&col
, 0, sizeof(col
));
5718 col
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
5720 col
.pszText
= textA
;
5721 ret
= SendMessageA(list
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5724 header
= (HWND
)SendMessageA(list
, LVM_GETHEADER
, 0, 0);
5725 ok(header
!= 0, "No header\n");
5726 memset(&itemW
, 0, sizeof(itemW
));
5727 itemW
.mask
= HDI_WIDTH
| HDI_ORDER
| HDI_TEXT
;
5728 itemW
.pszText
= buffer
;
5729 itemW
.cchTextMax
= ARRAY_SIZE(buffer
);
5730 ret
= SendMessageW(header
, HDM_GETITEMW
, 0, (LPARAM
)&itemW
);
5733 nmhdr
.hdr
.hwndFrom
= header
;
5734 nmhdr
.hdr
.idFrom
= GetWindowLongPtrW(header
, GWLP_ID
);
5737 nmhdr
.pitem
= &itemW
;
5739 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5740 nmhdr
.hdr
.code
= HDN_ITEMCHANGINGW
;
5741 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5742 ok(ret
== 0, "got %ld\n", ret
);
5743 parent_header_notify_seq
[0].id
= HDN_ITEMCHANGINGA
;
5744 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5745 "header notify, parent", TRUE
);
5747 ok(nmhdr
.hdr
.code
== HDN_ITEMCHANGINGA
, "Expected ANSI notification code\n");
5748 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5749 nmhdr
.hdr
.code
= HDN_ITEMCHANGEDW
;
5750 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5751 ok(ret
== 0, "got %ld\n", ret
);
5752 parent_header_notify_seq
[0].id
= HDN_ITEMCHANGEDA
;
5753 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5754 "header notify, parent", TRUE
);
5756 ok(nmhdr
.hdr
.code
== HDN_ITEMCHANGEDA
, "Expected ANSI notification code\n");
5757 /* HDN_ITEMCLICK sets focus to list, which generates messages we don't want to check */
5759 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5760 nmhdr
.hdr
.code
= HDN_ITEMCLICKW
;
5761 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5762 ok(ret
== 0, "got %ld\n", ret
);
5763 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_click_seq
,
5764 "header notify, parent", FALSE
);
5765 ok(nmhdr
.hdr
.code
== HDN_ITEMCLICKA
, "Expected ANSI notification code\n");
5766 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5767 nmhdr
.hdr
.code
= HDN_ITEMDBLCLICKW
;
5768 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5769 ok(ret
== 0, "got %ld\n", ret
);
5770 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5771 "header notify, parent", FALSE
);
5772 ok(nmhdr
.hdr
.code
== HDN_ITEMDBLCLICKW
, "Expected Unicode notification code\n");
5773 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5774 nmhdr
.hdr
.code
= HDN_DIVIDERDBLCLICKW
;
5775 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5776 ok(ret
== 0, "got %ld\n", ret
);
5777 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_divider_dclick_seq
,
5778 "header notify, parent", TRUE
);
5779 ok(nmhdr
.hdr
.code
== HDN_DIVIDERDBLCLICKA
, "Expected ANSI notification code\n");
5780 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5781 nmhdr
.hdr
.code
= HDN_BEGINTRACKW
;
5782 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5783 ok(ret
== 0, "got %ld\n", ret
);
5784 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5785 "header notify, parent", FALSE
);
5786 ok(nmhdr
.hdr
.code
== HDN_BEGINTRACKW
, "Expected Unicode notification code\n");
5787 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5788 nmhdr
.hdr
.code
= HDN_ENDTRACKW
;
5789 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5790 ok(ret
== 0, "got %ld\n", ret
);
5791 parent_header_notify_seq
[0].id
= HDN_ENDTRACKA
;
5792 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5793 "header notify, parent", FALSE
);
5794 ok(nmhdr
.hdr
.code
== HDN_ENDTRACKA
, "Expected ANSI notification code\n");
5795 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5796 nmhdr
.hdr
.code
= HDN_TRACKW
;
5797 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5798 ok(ret
== 0, "got %ld\n", ret
);
5799 parent_header_notify_seq
[0].id
= HDN_TRACKA
;
5800 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5801 "header notify, parent", FALSE
);
5802 ok(nmhdr
.hdr
.code
== HDN_TRACKA
, "Expected ANSI notification code\n");
5803 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5804 nmhdr
.hdr
.code
= HDN_BEGINDRAG
;
5805 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5806 ok(ret
== 1, "got %ld\n", ret
);
5807 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5808 "header notify, parent", FALSE
);
5809 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5810 nmhdr
.hdr
.code
= HDN_ENDDRAG
;
5811 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5812 ok(ret
== 0, "got %ld\n", ret
);
5813 parent_header_notify_seq
[0].id
= HDN_ENDDRAG
;
5814 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5815 "header notify, parent", FALSE
);
5816 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5817 nmhdr
.hdr
.code
= HDN_FILTERCHANGE
;
5818 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5819 ok(ret
== 0, "got %ld\n", ret
);
5820 parent_header_notify_seq
[0].id
= HDN_FILTERCHANGE
;
5821 parent_header_notify_seq
[0].flags
|= optional
; /* NT4 does not send this message */
5822 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5823 "header notify, parent", FALSE
);
5824 parent_header_notify_seq
[0].flags
&= ~optional
;
5825 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5826 nmhdr
.hdr
.code
= HDN_BEGINFILTEREDIT
;
5827 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5828 ok(ret
== 0, "got %ld\n", ret
);
5829 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5830 "header notify, parent", FALSE
);
5831 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5832 nmhdr
.hdr
.code
= HDN_ENDFILTEREDIT
;
5833 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5834 ok(ret
== 0, "got %ld\n", ret
);
5835 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5836 "header notify, parent", FALSE
);
5837 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5838 nmhdr
.hdr
.code
= HDN_ITEMSTATEICONCLICK
;
5839 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5840 ok(ret
== 0, "got %ld\n", ret
);
5841 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5842 "header notify, parent", FALSE
);
5843 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5844 nmhdr
.hdr
.code
= HDN_ITEMKEYDOWN
;
5845 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5846 ok(ret
== 0, "got %ld\n", ret
);
5847 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5848 "header notify, parent", FALSE
);
5850 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5852 DestroyWindow(list
);
5855 static void test_createdragimage(void)
5861 list
= create_listview_control(LVS_ICON
);
5862 ok(list
!= NULL
, "failed to create listview window\n");
5864 insert_item(list
, 0);
5867 himl
= (HIMAGELIST
)SendMessageA(list
, LVM_CREATEDRAGIMAGE
, 0, 0);
5868 ok(himl
== NULL
, "got %p\n", himl
);
5870 himl
= (HIMAGELIST
)SendMessageA(list
, LVM_CREATEDRAGIMAGE
, 0, (LPARAM
)&pt
);
5871 ok(himl
!= NULL
, "got %p\n", himl
);
5872 pImageList_Destroy(himl
);
5874 DestroyWindow(list
);
5877 static void test_dispinfo(void)
5879 static const char testA
[] = "TEST";
5885 hwnd
= create_listview_control(LVS_ICON
);
5886 ok(hwnd
!= NULL
, "failed to create listview window\n");
5888 insert_item(hwnd
, 0);
5890 memset(&item
, 0, sizeof(item
));
5891 item
.pszText
= LPSTR_TEXTCALLBACKA
;
5892 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
5895 g_disp_A_to_W
= TRUE
;
5896 item
.pszText
= (char*)buff
;
5897 item
.cchTextMax
= ARRAY_SIZE(buff
);
5898 ret
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
5899 ok(ret
== sizeof(testA
)-1, "got %ld, expected 4\n", ret
);
5900 g_disp_A_to_W
= FALSE
;
5902 ok(memcmp(item
.pszText
, testA
, sizeof(testA
)) == 0,
5903 "got %s, expected %s\n", item
.pszText
, testA
);
5905 DestroyWindow(hwnd
);
5908 static void test_LVM_SETITEMTEXT(void)
5910 static char testA
[] = "TEST";
5915 hwnd
= create_listview_control(LVS_ICON
);
5916 ok(hwnd
!= NULL
, "failed to create listview window\n");
5918 insert_item(hwnd
, 0);
5920 /* null item pointer */
5921 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, 0);
5924 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTW
, 0, 0);
5927 /* index out of bounds */
5928 item
.pszText
= testA
;
5929 item
.cchTextMax
= 0; /* ignored */
5932 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 1, (LPARAM
)&item
);
5935 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, -1, (LPARAM
)&item
);
5938 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
5941 DestroyWindow(hwnd
);
5944 static void test_LVM_REDRAWITEMS(void)
5949 list
= create_listview_control(LVS_ICON
);
5950 ok(list
!= NULL
, "failed to create listview window\n");
5952 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 0);
5955 insert_item(list
, 0);
5957 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, -1, 0);
5960 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, -1);
5963 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 0);
5966 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 1);
5969 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 2);
5972 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 1, 0);
5975 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 2, 3);
5978 DestroyWindow(list
);
5981 static void test_imagelists(void)
5984 HIMAGELIST himl1
, himl2
, himl3
;
5987 himl1
= pImageList_Create(40, 40, 0, 4, 4);
5988 himl2
= pImageList_Create(40, 40, 0, 4, 4);
5989 himl3
= pImageList_Create(40, 40, 0, 4, 4);
5990 ok(himl1
!= NULL
, "Failed to create imagelist\n");
5991 ok(himl2
!= NULL
, "Failed to create imagelist\n");
5992 ok(himl3
!= NULL
, "Failed to create imagelist\n");
5994 hwnd
= create_listview_control(LVS_REPORT
| LVS_SHAREIMAGELISTS
);
5995 header
= subclass_header(hwnd
);
5997 ok(header
!= NULL
, "Expected header\n");
5998 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
5999 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6001 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6003 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl1
);
6004 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6005 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6006 "set normal image list", FALSE
);
6008 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6010 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl2
);
6011 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6012 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6013 "set state image list", TRUE
);
6015 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
6016 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6018 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6020 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl3
);
6021 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6022 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_header_set_imagelist
,
6023 "set small image list", FALSE
);
6025 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
6026 ok((HIMAGELIST
)ret
== himl3
, "Expected imagelist %p, got %p\n", himl3
, (HIMAGELIST
)ret
);
6027 DestroyWindow(hwnd
);
6029 hwnd
= create_listview_control(WS_VISIBLE
| LVS_ICON
);
6031 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6033 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl1
);
6034 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6035 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6036 "set normal image list", FALSE
);
6038 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6040 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl2
);
6041 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6042 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6043 "set state image list", FALSE
);
6045 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6047 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl3
);
6048 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6049 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6050 "set small image list", FALSE
);
6052 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
6053 ok(header
== NULL
, "Expected no header, got %p\n", header
);
6055 SetWindowLongPtrA(hwnd
, GWL_STYLE
, GetWindowLongPtrA(hwnd
, GWL_STYLE
) | LVS_REPORT
);
6057 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
6058 ok(header
!= NULL
, "Expected header, got NULL\n");
6060 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
6061 ok((HIMAGELIST
)ret
== himl3
, "Expected imagelist %p, got %p\n", himl3
, (HIMAGELIST
)ret
);
6063 DestroyWindow(hwnd
);
6066 static void test_deleteitem(void)
6073 hwnd
= create_listview_control(LVS_REPORT
);
6075 insert_item(hwnd
, 0);
6076 insert_item(hwnd
, 0);
6077 insert_item(hwnd
, 0);
6078 insert_item(hwnd
, 0);
6079 insert_item(hwnd
, 0);
6081 g_focus_test_LVN_DELETEITEM
= TRUE
;
6083 /* delete focused item (not the last index) */
6084 item
.stateMask
= LVIS_FOCUSED
;
6085 item
.state
= LVIS_FOCUSED
;
6086 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 2, (LPARAM
)&item
);
6087 ok(ret
== TRUE
, "got %d\n", ret
);
6088 ret
= SendMessageA(hwnd
, LVM_DELETEITEM
, 2, 0);
6089 ok(ret
== TRUE
, "got %d\n", ret
);
6090 /* next item gets focus */
6091 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_FOCUSED
);
6092 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6094 /* focus last item and delete it */
6095 item
.stateMask
= LVIS_FOCUSED
;
6096 item
.state
= LVIS_FOCUSED
;
6097 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 3, (LPARAM
)&item
);
6098 ok(ret
== TRUE
, "got %d\n", ret
);
6099 ret
= SendMessageA(hwnd
, LVM_DELETEITEM
, 3, 0);
6100 ok(ret
== TRUE
, "got %d\n", ret
);
6101 /* new last item gets focus */
6102 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_FOCUSED
);
6103 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6105 /* focus first item and delete it */
6106 item
.stateMask
= LVIS_FOCUSED
;
6107 item
.state
= LVIS_FOCUSED
;
6108 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6109 ok(ret
== TRUE
, "got %d\n", ret
);
6110 ret
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
6111 ok(ret
== TRUE
, "got %d\n", ret
);
6112 /* new first item gets focus */
6113 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_FOCUSED
);
6114 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6116 g_focus_test_LVN_DELETEITEM
= FALSE
;
6118 DestroyWindow(hwnd
);
6121 static const struct message parent_insert_focused0_seq
[] = {
6122 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 0, LVIF_STATE
, LVN_ITEMCHANGING
},
6123 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 0, LVIF_STATE
, LVN_ITEMCHANGED
},
6124 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_INSERTITEM
},
6128 static const struct message parent_insert_focused1_seq
[] = {
6129 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 1, LVIF_STATE
, LVN_ITEMCHANGING
},
6130 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 0, LVIF_STATE
, LVN_ITEMCHANGING
},
6131 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 0, LVIF_STATE
, LVN_ITEMCHANGED
},
6132 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 1, LVIF_STATE
, LVN_ITEMCHANGED
},
6133 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_INSERTITEM
},
6137 static const struct message parent_insert_item_seq
[] = {
6138 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_INSERTITEM
},
6142 static const struct message parent_insert_selected_seq
[] = {
6143 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 3, LVIF_STATE
, LVN_ITEMCHANGING
},
6144 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 3, LVIF_STATE
, LVN_ITEMCHANGED
},
6145 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_INSERTITEM
},
6149 #define LVIS_ALL (LVIS_FOCUSED | LVIS_SELECTED | LVIS_CUT | LVIS_DROPHILITED | LVIS_ACTIVATING)
6151 static void test_LVM_INSERTITEM(void)
6155 UINT mask
, state
, stateMask
;
6158 { LVIF_STATE
, LVIS_FOCUSED
, LVIS_FOCUSED
},
6159 { LVIF_STATE
, LVIS_FOCUSED
, 0 },
6160 { LVIF_STATE
, 0, LVIS_FOCUSED
},
6162 { LVIF_STATE
, LVIS_SELECTED
, LVIS_SELECTED
},
6163 { LVIF_STATE
, LVIS_SELECTED
, 0 },
6164 { LVIF_STATE
, 0, LVIS_SELECTED
},
6166 { LVIF_STATE
, LVIS_FOCUSED
| LVIS_SELECTED
, LVIS_FOCUSED
| LVIS_SELECTED
},
6167 { LVIF_STATE
, LVIS_FOCUSED
| LVIS_SELECTED
, 0 },
6168 { LVIF_STATE
, 0, LVIS_FOCUSED
| LVIS_SELECTED
},
6170 { LVIF_STATE
, LVIS_FOCUSED
, LVIS_ALL
},
6171 { LVIF_STATE
, LVIS_SELECTED
, LVIS_ALL
},
6172 { LVIF_STATE
, LVIS_CUT
, LVIS_ALL
},
6173 { LVIF_STATE
, LVIS_DROPHILITED
, LVIS_ALL
},
6174 { LVIF_STATE
, LVIS_ACTIVATING
, LVIS_ALL
},
6176 { LVIF_STATE
, LVIS_ALL
, LVIS_ALL
},
6177 { LVIF_STATE
, LVIS_ALL
, 0 },
6178 { LVIF_STATE
, 0, LVIS_ALL
},
6180 { LVIF_STATE
| LVIF_PARAM
, 0, 0 },
6181 { LVIF_STATE
| LVIF_PARAM
, LVIS_FOCUSED
, LVIS_FOCUSED
},
6182 { LVIF_STATE
| LVIF_PARAM
, LVIS_FOCUSED
, 0 },
6183 { LVIF_STATE
| LVIF_PARAM
, 0, LVIS_FOCUSED
},
6185 { LVIF_STATE
| LVIF_PARAM
, LVIS_SELECTED
, LVIS_SELECTED
},
6186 { LVIF_STATE
| LVIF_PARAM
, LVIS_SELECTED
, 0 },
6187 { LVIF_STATE
| LVIF_PARAM
, 0, LVIS_SELECTED
},
6189 { LVIF_STATE
, 0, 0 },
6190 { LVIF_PARAM
, 0, 0 },
6192 { LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, 0 },
6193 { LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_FOCUSED
, LVIS_FOCUSED
},
6194 { LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_FOCUSED
, 0 },
6195 { LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, LVIS_FOCUSED
},
6197 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, 0 },
6198 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_FOCUSED
, LVIS_FOCUSED
},
6199 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_FOCUSED
, 0 },
6200 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, LVIS_FOCUSED
},
6202 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, 0 },
6203 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_ALL
, LVIS_ALL
},
6204 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_ALL
, 0 },
6205 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, LVIS_ALL
},
6213 for (i
= 0; i
< ARRAYSIZE(insert_item
); i
++)
6215 hwnd
= create_listview_control(LVS_REPORT
);
6217 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6219 item
.mask
= insert_item
[i
].mask
;
6220 item
.state
= insert_item
[i
].state
;
6221 item
.stateMask
= insert_item
[i
].stateMask
;
6222 item
.pszText
= (LPSTR
)"Hello World!";
6223 item
.iImage
= I_IMAGECALLBACK
;
6226 item
.lParam
= 0xdeadbeef;
6227 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6228 ok(ret
== 0, "%d: got %d\n", i
, ret
);
6230 if ((insert_item
[i
].mask
& LVIF_STATE
) && (insert_item
[i
].state
& (LVIS_FOCUSED
| LVIS_SELECTED
)))
6232 sprintf(buf
, "%d: insert focused", i
);
6233 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_focused0_seq
, buf
, FALSE
);
6237 sprintf(buf
, "%d: insert item", i
);
6238 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_item_seq
, buf
, FALSE
);
6241 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_ALL
);
6242 if ((insert_item
[i
].mask
& LVIF_STATE
) && insert_item
[i
].state
)
6243 ok(state
== insert_item
[i
].state
, "%d: expected %#x, got %#x\n", i
, insert_item
[i
].state
, state
);
6245 ok(state
== 0, "%d: expected 0, got %#x\n", i
, state
);
6247 DestroyWindow(hwnd
);
6251 static void test_insertitem(void)
6258 hwnd
= create_listview_control(LVS_REPORT
);
6260 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6262 /* insert item 0 focused */
6263 item
.mask
= LVIF_STATE
;
6264 item
.state
= LVIS_FOCUSED
;
6265 item
.stateMask
= LVIS_FOCUSED
;
6268 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6269 ok(ret
== 0, "got %d\n", ret
);
6270 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_focused0_seq
, "insert focused 0", FALSE
);
6272 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_FOCUSED
);
6273 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6275 /* insert item 1, focus shift */
6276 item
.mask
= LVIF_STATE
;
6277 item
.state
= LVIS_FOCUSED
;
6278 item
.stateMask
= LVIS_FOCUSED
;
6281 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6282 ok(ret
== 1, "got %d\n", ret
);
6283 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_focused1_seq
, "insert focused 1", FALSE
);
6285 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_FOCUSED
);
6286 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6288 /* insert item 2, no focus shift */
6289 item
.mask
= LVIF_STATE
;
6291 item
.stateMask
= LVIS_FOCUSED
;
6294 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6295 ok(ret
== 2, "got %d\n", ret
);
6296 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_item_seq
, "insert focused 2", FALSE
);
6298 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_FOCUSED
);
6299 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6302 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
6303 item
.state
= LVIS_SELECTED
;
6304 item
.stateMask
= LVIS_SELECTED
;
6307 item
.lParam
= 0xdeadbeef;
6308 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6309 ok(ret
== 3, "got %d\n", ret
);
6310 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_selected_seq
, "insert selected", FALSE
);
6313 item
.mask
= LVIF_PARAM
;
6318 item
.lParam
= 0xdeadbeef;
6319 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6320 ok(ret
== 4, "got %d\n", ret
);
6321 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_item_seq
, "insert param", FALSE
);
6324 item
.mask
= LVIF_STATE
;
6329 item
.lParam
= 0xdeadbeef;
6330 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6331 ok(ret
== 5, "got %d\n", ret
);
6332 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_item_seq
, "insert state", FALSE
);
6334 DestroyWindow(hwnd
);
6337 static void test_header_proc(void)
6339 HWND hwnd
, header
, hdr
;
6340 WNDPROC proc1
, proc2
;
6342 hwnd
= create_listview_control(LVS_REPORT
);
6344 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
6345 ok(header
!= NULL
, "got %p\n", header
);
6347 hdr
= CreateWindowExA(0, WC_HEADERA
, NULL
,
6348 WS_BORDER
|WS_VISIBLE
|HDS_BUTTONS
|HDS_HORZ
,
6350 NULL
, NULL
, NULL
, NULL
);
6351 ok(hdr
!= NULL
, "got %p\n", hdr
);
6353 proc1
= (WNDPROC
)GetWindowLongPtrW(header
, GWLP_WNDPROC
);
6354 proc2
= (WNDPROC
)GetWindowLongPtrW(hdr
, GWLP_WNDPROC
);
6355 ok(proc1
== proc2
, "got %p, expected %p\n", proc1
, proc2
);
6358 DestroyWindow(hwnd
);
6361 static void flush_events(void)
6365 int min_timeout
= 100;
6366 DWORD time
= GetTickCount() + diff
;
6370 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
6371 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6372 diff
= time
- GetTickCount();
6376 static void test_oneclickactivate(void)
6378 TRACKMOUSEEVENT track
;
6379 char item1
[] = "item1";
6386 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", WS_VISIBLE
|WS_CHILD
|LVS_LIST
,
6387 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
6388 ok(hwnd
!= NULL
, "failed to create listview window\n");
6389 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_ONECLICKACTIVATE
);
6390 ok(r
== 0, "should return zero\n");
6392 SetForegroundWindow(hwndparent
);
6394 fg
= GetForegroundWindow();
6395 if (fg
!= hwndparent
)
6397 skip("Window is not in the foreground. Skipping oneclickactivate tests.\n");
6398 DestroyWindow(hwnd
);
6402 item
.mask
= LVIF_TEXT
;
6406 item
.pszText
= item1
;
6407 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
6408 ok(r
== 0, "should not fail\n");
6410 GetWindowRect(hwnd
, &rect
);
6411 GetCursorPos(&orig_pos
);
6412 SetCursorPos(rect
.left
+5, rect
.top
+5);
6414 r
= SendMessageA(hwnd
, WM_MOUSEMOVE
, MAKELONG(1, 1), 0);
6417 track
.cbSize
= sizeof(track
);
6418 track
.dwFlags
= TME_QUERY
;
6419 p_TrackMouseEvent(&track
);
6420 ok(track
.hwndTrack
== hwnd
, "hwndTrack != hwnd\n");
6421 ok(track
.dwFlags
== TME_LEAVE
, "dwFlags = %lx\n", track
.dwFlags
);
6423 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
6425 r
= SendMessageA(hwnd
, WM_MOUSEHOVER
, MAKELONG(1, 1), 0);
6427 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
6430 DestroyWindow(hwnd
);
6431 SetCursorPos(orig_pos
.x
, orig_pos
.y
);
6434 static void test_callback_mask(void)
6441 hwnd
= create_listview_control(LVS_REPORT
);
6443 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, ~0u, 0);
6444 ok(ret
, "got %d\n", ret
);
6446 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, ~0u, 1);
6447 ok(ret
, "got %d\n", ret
);
6449 mask
= SendMessageA(hwnd
, LVM_GETCALLBACKMASK
, 0, 0);
6450 ok(mask
== ~0u, "got 0x%08lx\n", mask
);
6452 /* Ask for state, invalid subitem. */
6453 insert_item(hwnd
, 0);
6455 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_FOCUSED
, 0);
6456 ok(ret
, "Failed to set callback mask.\n");
6458 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6460 memset(&item
, 0, sizeof(item
));
6462 item
.mask
= LVIF_STATE
;
6463 item
.stateMask
= LVIS_SELECTED
;
6464 ret
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6465 ok(ret
, "Failed to get item data.\n");
6467 memset(&item
, 0, sizeof(item
));
6468 item
.mask
= LVIF_STATE
;
6469 item
.stateMask
= LVIS_SELECTED
;
6470 ret
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6471 ok(ret
, "Failed to get item data.\n");
6473 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "parent seq, callback mask/invalid subitem 1", TRUE
);
6475 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6477 memset(&item
, 0, sizeof(item
));
6478 memset(&g_itema
, 0, sizeof(g_itema
));
6480 item
.mask
= LVIF_STATE
;
6481 item
.stateMask
= LVIS_FOCUSED
| LVIS_SELECTED
;
6482 ret
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6483 ok(ret
, "Failed to get item data.\n");
6484 ok(g_itema
.iSubItem
== 1, "Unexpected LVN_DISPINFO subitem %d.\n", g_itema
.iSubItem
);
6485 ok(g_itema
.stateMask
== LVIS_FOCUSED
, "Unexpected state mask %#x.\n", g_itema
.stateMask
);
6487 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
6488 "parent seq, callback mask/invalid subitem 2", FALSE
);
6490 DestroyWindow(hwnd
);
6492 /* LVS_OWNERDATA, mask LVIS_FOCUSED */
6493 hwnd
= create_listview_control(LVS_REPORT
| LVS_OWNERDATA
);
6495 mask
= SendMessageA(hwnd
, LVM_GETCALLBACKMASK
, 0, 0);
6496 ok(mask
== 0, "Unexpected callback mask %#lx.\n", mask
);
6498 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_FOCUSED
, 0);
6499 ok(ret
, "Failed to set callback mask, %d\n", ret
);
6501 mask
= SendMessageA(hwnd
, LVM_GETCALLBACKMASK
, 0, 0);
6502 ok(mask
== LVIS_FOCUSED
, "Unexpected callback mask %#lx.\n", mask
);
6504 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6505 ok(ret
, "Failed to set item count.\n");
6507 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6508 ok(ret
== -1, "Unexpected selection mark, %d\n", ret
);
6510 item
.stateMask
= LVIS_FOCUSED
;
6511 item
.state
= LVIS_FOCUSED
;
6512 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6513 ok(ret
, "Failed to set item state.\n");
6515 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6517 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6519 ok(ret
== 0, "Unexpected focused item, ret %d\n", ret
);
6521 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6523 ok(ret
== 0, "Unexpected selection mark, %d\n", ret
);
6525 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 0, 0);
6526 ok(ret
, "Failed to set item count.\n");
6528 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6529 ok(ret
== -1, "Unexpected focused item, ret %d\n", ret
);
6531 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6532 ok(ret
== -1, "Unexpected selection mark, %d\n", ret
);
6534 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6535 ok(ret
, "Failed to set item count.\n");
6537 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6538 ok(ret
== -1, "Unexpected focused item, ret %d\n", ret
);
6540 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "parent seq, owner data/focus 1", FALSE
);
6542 /* LVS_OWNDERDATA, empty mask */
6543 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, 0, 0);
6544 ok(ret
, "Failed to set callback mask, %d\n", ret
);
6546 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6547 ok(ret
, "Failed to set item count.\n");
6549 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6550 ok(ret
== -1, "Unexpected selection mark, %d\n", ret
);
6552 item
.stateMask
= LVIS_FOCUSED
;
6553 item
.state
= LVIS_FOCUSED
;
6554 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6555 ok(ret
, "Failed to set item state.\n");
6557 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6558 ok(ret
== 0, "Unexpected selection mark, %d\n", ret
);
6560 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6562 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6563 ok(ret
== 0, "Unexpected focused item, ret %d\n", ret
);
6565 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 0, 0);
6566 ok(ret
, "Failed to set item count.\n");
6568 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6569 ok(ret
== -1, "Unexpected focused item, ret %d\n", ret
);
6571 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6573 ok(ret
== -1, "Unexpected selection mark, %d\n", ret
);
6575 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6576 ok(ret
, "Failed to set item count.\n");
6578 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6579 ok(ret
== -1, "Unexpected focused item, ret %d\n", ret
);
6581 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "parent seq, owner data/focus 2", FALSE
);
6583 /* 2 items, focus on index 0, reduce to 1 item. */
6584 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6586 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 2, 0);
6587 ok(ret
, "Failed to set item count.\n");
6589 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6590 ok(ret
, "Failed to set item state.\n");
6592 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6593 ok(ret
== 0, "Unexpected focused item, ret %d\n", ret
);
6595 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6596 ok(ret
, "Failed to set item count.\n");
6598 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6599 ok(ret
== 0, "Unexpected focused item, ret %d\n", ret
);
6601 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_focus_change_ownerdata_seq
,
6602 "parent seq, owner data/focus 3", TRUE
);
6604 DestroyWindow(hwnd
);
6607 static void test_state_image(void)
6609 static const DWORD styles
[] =
6618 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
6620 static char text
[] = "Item";
6621 static char subtext
[] = "Subitem";
6627 hwnd
= create_listview_control(styles
[i
]);
6629 insert_column(hwnd
, 0);
6630 insert_column(hwnd
, 1);
6632 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
6635 item
.pszText
= text
;
6636 item
.lParam
= 123456;
6637 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6638 ok(r
== 0, "Failed to insert an item.\n");
6640 item
.mask
= LVIF_STATE
;
6641 item
.state
= INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED
| LVIS_FOCUSED
;
6642 item
.stateMask
= LVIS_STATEIMAGEMASK
| LVIS_SELECTED
| LVIS_FOCUSED
;
6645 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
6646 ok(r
, "Failed to set item state.\n");
6648 item
.mask
= LVIF_TEXT
;
6651 item
.pszText
= subtext
;
6652 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
6653 ok(r
, "Failed to set subitem text.\n");
6655 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
6656 item
.stateMask
= ~0u;
6661 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6662 ok(r
, "Failed to get item state.\n");
6663 ok(item
.state
== (INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED
| LVIS_FOCUSED
),
6664 "Unexpected item state %#x.\n", item
.state
);
6665 ok(item
.lParam
== 123456, "Unexpected lParam %Id.\n", item
.lParam
);
6668 item
.stateMask
= ~0u;
6669 item
.state
= INDEXTOSTATEIMAGEMASK(2);
6672 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6673 ok(r
, "Failed to get subitem state.\n");
6674 ok(item
.state
== INDEXTOSTATEIMAGEMASK(2), "Unexpected state %#x.\n", item
.state
);
6676 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
6677 item
.stateMask
= ~0u;
6678 item
.state
= INDEXTOSTATEIMAGEMASK(2);
6682 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6683 ok(r
, "Failed to get subitem state.\n");
6684 ok(item
.state
== 0, "Unexpected state %#x.\n", item
.state
);
6685 ok(item
.lParam
== 123456, "Unexpected lParam %Id.\n", item
.lParam
);
6687 item
.mask
= LVIF_STATE
;
6688 item
.stateMask
= LVIS_FOCUSED
;
6692 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6693 ok(r
, "Failed to get subitem state.\n");
6694 ok(item
.state
== 0, "Unexpected state %#x.\n", item
.state
);
6696 item
.mask
= LVIF_STATE
;
6697 item
.stateMask
= ~0u;
6698 item
.state
= INDEXTOSTATEIMAGEMASK(2);
6701 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6702 ok(r
, "Failed to get subitem state.\n");
6703 ok(item
.state
== 0, "Unexpected state %#x.\n", item
.state
);
6705 item
.mask
= LVIF_TEXT
;
6708 item
.pszText
= buff
;
6709 item
.cchTextMax
= sizeof(buff
);
6710 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6711 ok(r
, "Failed to get subitem text %d.\n", r
);
6712 ok(!strcmp(buff
, subtext
), "Unexpected subitem text %s.\n", buff
);
6714 DestroyWindow(hwnd
);
6718 static void test_LVSCW_AUTOSIZE(void)
6724 hwnd
= create_listview_control(LVS_REPORT
);
6725 ok(hwnd
!= NULL
, "failed to create a listview window\n");
6727 insert_column(hwnd
, 0);
6728 insert_column(hwnd
, 1);
6729 insert_item(hwnd
, 0);
6731 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
6732 ok(ret
, "Failed to set column width.\n");
6734 width
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
6735 ok(width
> 0, "Unexpected column width %d.\n", width
);
6737 /* Turn on checkboxes. */
6738 ret
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
6739 ok(ret
== 0, "Unexpected previous extended style.\n");
6741 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
6742 ok(ret
, "Failed to set column width.\n");
6744 width2
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
6745 ok(width2
> 0, "Unexpected column width %d.\n", width2
);
6746 ok(width2
> width
, "Expected increased column width.\n");
6748 /* Turn off checkboxes. */
6749 ret
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
6750 ok(ret
== LVS_EX_CHECKBOXES
, "Unexpected previous extended style.\n");
6752 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
6753 ok(ret
, "Failed to set column width.\n");
6755 width
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
6756 ok(width
> 0, "Unexpected column width %d.\n", width2
);
6757 ok(width2
> width
, "Expected reduced column width.\n");
6759 DestroyWindow(hwnd
);
6762 static void test_LVN_ENDLABELEDIT(void)
6764 WCHAR text
[] = {'l','a','l','a',0};
6765 HWND hwnd
, hwndedit
;
6769 hwnd
= create_listview_control(LVS_REPORT
| LVS_EDITLABELS
);
6771 insert_column(hwnd
, 0);
6773 item
.mask
= LVIF_TEXT
;
6774 item
.pszText
= text
;
6775 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6777 /* Test normal editing */
6779 hwndedit
= (HWND
)SendMessageW(hwnd
, LVM_EDITLABELW
, 0, 0);
6780 ok(hwndedit
!= NULL
, "Failed to get edit control.\n");
6782 ret
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)"test");
6783 ok(ret
, "Failed to set edit text.\n");
6785 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6787 ret
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_RETURN
, 0);
6788 ok_sequence(sequences
, PARENT_SEQ_INDEX
, listview_end_label_edit
, "Label edit", FALSE
);
6790 /* Test editing with kill focus */
6792 hwndedit
= (HWND
)SendMessageW(hwnd
, LVM_EDITLABELW
, 0, 0);
6793 ok(hwndedit
!= NULL
, "Failed to get edit control.\n");
6795 ret
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)"test2");
6796 ok(ret
, "Failed to set edit text.\n");
6798 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6800 g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT
= TRUE
;
6801 ret
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_RETURN
, 0);
6802 g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT
= FALSE
;
6804 ok_sequence(sequences
, PARENT_SEQ_INDEX
, listview_end_label_edit_kill_focus
,
6805 "Label edit, kill focus", FALSE
);
6806 ok(GetFocus() == hwnd
, "Unexpected focused window.\n");
6808 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6810 DestroyWindow(hwnd
);
6813 static LRESULT CALLBACK
create_item_height_wndproc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
6815 if (msg
== WM_CREATE
)
6818 return CallWindowProcA(listviewWndProc
, hwnd
, msg
, wParam
, lParam
);
6821 static void test_LVM_GETCOUNTPERPAGE(void)
6823 static const DWORD styles
[] = { LVS_ICON
, LVS_LIST
, LVS_REPORT
, LVS_SMALLICON
};
6830 cls
.cbSize
= sizeof(WNDCLASSEXA
);
6831 ret
= GetClassInfoExA(GetModuleHandleA(NULL
), WC_LISTVIEWA
, &cls
);
6832 ok(ret
, "Failed to get class info.\n");
6833 listviewWndProc
= cls
.lpfnWndProc
;
6834 cls
.lpfnWndProc
= create_item_height_wndproc
;
6835 cls
.lpszClassName
= "CountPerPageClass";
6836 class = RegisterClassExA(&cls
);
6837 ok(class, "Failed to register class.\n");
6839 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
6841 static char text
[] = "item text";
6842 LVITEMA item
= { 0 };
6845 hwnd
= create_listview_control(styles
[i
]);
6846 ok(hwnd
!= NULL
, "Failed to create listview window.\n");
6848 count
= SendMessageA(hwnd
, LVM_GETCOUNTPERPAGE
, 0, 0);
6849 if (styles
[i
] == LVS_LIST
|| styles
[i
] == LVS_REPORT
)
6850 ok(count
> 0 || broken(styles
[i
] == LVS_LIST
&& count
== 0), "%u: unexpected count %u.\n", i
, count
);
6852 ok(count
== 0, "%u: unexpected count %u.\n", i
, count
);
6854 for (j
= 0; j
< 10; j
++)
6856 item
.mask
= LVIF_TEXT
;
6857 item
.pszText
= text
;
6858 SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6861 count2
= SendMessageA(hwnd
, LVM_GETCOUNTPERPAGE
, 0, 0);
6862 if (styles
[i
] == LVS_LIST
|| styles
[i
] == LVS_REPORT
)
6863 ok(count
== count2
, "%u: unexpected count %u.\n", i
, count2
);
6865 ok(count2
== 10, "%u: unexpected count %u.\n", i
, count2
);
6867 DestroyWindow(hwnd
);
6869 hwnd
= CreateWindowA("CountPerPageClass", "Test", WS_VISIBLE
| styles
[i
], 0, 0, 100, 100, NULL
, NULL
,
6870 GetModuleHandleA(NULL
), 0);
6871 ok(hwnd
!= NULL
, "Failed to create a window.\n");
6873 count
= SendMessageA(hwnd
, LVM_GETCOUNTPERPAGE
, 0, 0);
6874 ok(count
== 0, "%u: unexpected count %u.\n", i
, count
);
6876 DestroyWindow(hwnd
);
6879 ret
= UnregisterClassA("CountPerPageClass", NULL
);
6880 ok(ret
, "Failed to unregister test class.\n");
6883 static void test_item_state_change(void)
6885 static const DWORD styles
[] = { LVS_ICON
, LVS_LIST
, LVS_REPORT
, LVS_SMALLICON
};
6891 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
6893 hwnd
= create_listview_control(styles
[i
]);
6895 insert_item(hwnd
, 0);
6897 /* LVM_SETITEMSTATE with mask */
6898 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
6899 memset(&item
, 0, sizeof(item
));
6900 item
.mask
= LVIF_STATE
;
6901 item
.stateMask
= LVIS_SELECTED
;
6902 item
.state
= LVIS_SELECTED
;
6903 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6904 ok(res
, "Failed to set item state.\n");
6906 ok(g_nmlistview
.iItem
== item
.iItem
, "Unexpected item %d.\n", g_nmlistview
.iItem
);
6907 ok(g_nmlistview
.iSubItem
== item
.iSubItem
, "Unexpected subitem %d.\n", g_nmlistview
.iSubItem
);
6908 ok(g_nmlistview
.lParam
== item
.lParam
, "Unexpected lParam.\n");
6909 ok(g_nmlistview
.uNewState
== LVIS_SELECTED
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
6910 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
6911 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
6913 /* LVM_SETITEMSTATE 0 mask */
6914 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
6915 memset(&item
, 0, sizeof(item
));
6916 item
.stateMask
= LVIS_SELECTED
;
6918 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6919 ok(res
, "Failed to set item state.\n");
6921 ok(g_nmlistview
.iItem
== item
.iItem
, "Unexpected item %d.\n", g_nmlistview
.iItem
);
6922 ok(g_nmlistview
.iSubItem
== item
.iSubItem
, "Unexpected subitem %d.\n", g_nmlistview
.iSubItem
);
6923 ok(g_nmlistview
.lParam
== item
.lParam
, "Unexpected lParam.\n");
6924 ok(g_nmlistview
.uNewState
== 0, "Unexpected new state %#x.\n", g_nmlistview
.uNewState
);
6925 ok(g_nmlistview
.uOldState
== LVIS_SELECTED
, "Unexpected old state %#x.\n", g_nmlistview
.uOldState
);
6926 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "Unexpected change mask %#x.\n", g_nmlistview
.uChanged
);
6928 /* LVM_SETITEM changes state */
6929 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
6930 memset(&item
, 0, sizeof(item
));
6931 item
.stateMask
= LVIS_SELECTED
;
6932 item
.state
= LVIS_SELECTED
;
6933 item
.mask
= LVIF_STATE
;
6934 res
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
6935 ok(res
, "Failed to set item.\n");
6937 ok(g_nmlistview
.iItem
== item
.iItem
, "Unexpected item %d.\n", g_nmlistview
.iItem
);
6938 ok(g_nmlistview
.iSubItem
== item
.iSubItem
, "Unexpected subitem %d.\n", g_nmlistview
.iSubItem
);
6939 ok(g_nmlistview
.lParam
== item
.lParam
, "Unexpected lParam.\n");
6940 ok(g_nmlistview
.uNewState
== LVIS_SELECTED
, "Unexpected new state %#x.\n", g_nmlistview
.uNewState
);
6941 ok(g_nmlistview
.uOldState
== 0, "Unexpected old state %#x.\n", g_nmlistview
.uOldState
);
6942 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "Unexpected change mask %#x.\n", g_nmlistview
.uChanged
);
6944 /* LVM_SETITEM no state changes */
6945 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
6946 memset(&item
, 0, sizeof(item
));
6948 item
.mask
= LVIF_PARAM
;
6949 res
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
6950 ok(res
, "Failed to set item.\n");
6952 ok(g_nmlistview
.iItem
== item
.iItem
, "Unexpected item %d.\n", g_nmlistview
.iItem
);
6953 ok(g_nmlistview
.iSubItem
== item
.iSubItem
, "Unexpected subitem %d.\n", g_nmlistview
.iSubItem
);
6954 ok(g_nmlistview
.lParam
== item
.lParam
, "Unexpected lParam.\n");
6955 ok(g_nmlistview
.uNewState
== 0, "Unexpected new state %#x.\n", g_nmlistview
.uNewState
);
6956 ok(g_nmlistview
.uOldState
== 0, "Unexpected old state %#x.\n", g_nmlistview
.uOldState
);
6957 ok(g_nmlistview
.uChanged
== LVIF_PARAM
, "Unexpected change mask %#x.\n", g_nmlistview
.uChanged
);
6959 DestroyWindow(hwnd
);
6963 static void test_selected_column(void)
6965 static const DWORD styles
[] = { LVS_ICON
, LVS_LIST
, LVS_REPORT
, LVS_SMALLICON
};
6969 for (i
= 0; i
< ARRAY_SIZE(styles
); ++i
)
6971 hwnd
= create_listview_control(styles
[i
]);
6974 ret
= SendMessageA(hwnd
, LVM_GETSELECTEDCOLUMN
, 0, 0);
6975 ok(ret
== -1, "Unexpected column %d.\n", ret
);
6977 ret
= SendMessageA(hwnd
, LVM_SETSELECTEDCOLUMN
, -100, 0);
6978 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
6980 ret
= SendMessageA(hwnd
, LVM_GETSELECTEDCOLUMN
, 0, 0);
6981 ok(ret
== -100, "Unexpected column %d.\n", ret
);
6983 ret
= SendMessageA(hwnd
, LVM_SETSELECTEDCOLUMN
, 100, 0);
6984 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
6986 ret
= SendMessageA(hwnd
, LVM_GETSELECTEDCOLUMN
, 0, 0);
6987 ok(ret
== 100, "Unexpected column %d.\n", ret
);
6989 ret
= SendMessageA(hwnd
, LVM_SETSELECTEDCOLUMN
, -1, 0);
6990 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
6992 ret
= SendMessageA(hwnd
, LVM_GETSELECTEDCOLUMN
, 0, 0);
6993 ok(ret
== -1, "Unexpected column %d.\n", ret
);
6995 DestroyWindow(hwnd
);
6999 static void test_LVM_GETNEXTITEMINDEX(void)
7005 hwnd
= create_listview_control(LVS_REPORT
);
7007 insert_item(hwnd
, 0);
7008 insert_item(hwnd
, 1);
7010 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEMINDEX
, 0, LVNI_ALL
);
7011 ok(!ret
, "Unexpected return value %d.\n", ret
);
7015 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEMINDEX
, (WPARAM
)&index
, LVNI_ALL
);
7016 ok(ret
, "Unexpected return value %d.\n", ret
);
7017 ok(index
.iItem
== 0, "Unexpected item index %d.\n", index
.iItem
);
7019 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEMINDEX
, (WPARAM
)&index
, LVNI_ALL
);
7020 ok(ret
, "Unexpected return value %d.\n", ret
);
7021 ok(index
.iItem
== 1, "Unexpected item index %d.\n", index
.iItem
);
7023 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEMINDEX
, (WPARAM
)&index
, LVNI_ALL
);
7024 ok(!ret
, "Unexpected return value %d.\n", ret
);
7025 ok(index
.iItem
== -1, "Unexpected item index %d.\n", index
.iItem
);
7027 DestroyWindow(hwnd
);
7030 static void test_LVM_SETBKIMAGE(BOOL is_v6
)
7040 hbmp
= CreateBitmap(32, 32, 1, 1, NULL
);
7041 hwnd
= create_listview_control(LVS_REPORT
);
7043 image
.ulFlags
= LVBKIF_SOURCE_NONE
;
7045 image
.pszImage
= NULL
;
7046 image
.cchImageMax
= 0;
7047 image
.xOffsetPercent
= 0;
7048 image
.yOffsetPercent
= 0;
7049 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7050 ok(!ret
, "got %d\n", ret
);
7052 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7053 ok(ret
== sizeof(bm
), "got %d\n", ret
);
7055 image
.ulFlags
= LVBKIF_SOURCE_HBITMAP
;
7057 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7059 ok(ret
, "got %d\n", ret
);
7061 todo_wine
ok(!ret
, "got %d\n", ret
);
7063 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7064 ok(ret
== sizeof(bm
), "got %d\n", ret
);
7066 image
.ulFlags
= LVBKIF_SOURCE_NONE
;
7068 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7069 ok(!ret
, "got %d\n", ret
);
7071 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7072 ok(!ret
, "got %d\n", ret
);
7074 hbmp
= CreateBitmap(32, 32, 1, 1, NULL
);
7076 image
.ulFlags
= LVBKIF_SOURCE_HBITMAP
;
7078 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7080 ok(ret
, "got %d\n", ret
);
7082 todo_wine
ok(!ret
, "got %d\n", ret
);
7084 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7085 ok(ret
== sizeof(bm
), "got %d\n", ret
);
7087 image
.ulFlags
= LVBKIF_SOURCE_HBITMAP
;
7089 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7090 ok(!ret
, "got %d\n", ret
);
7092 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7093 ok(!ret
, "got %d\n", ret
);
7095 image
.ulFlags
= LVBKIF_SOURCE_NONE
;
7097 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7098 ok(!ret
, "got %d\n", ret
);
7100 DestroyWindow(hwnd
);
7105 START_TEST(listview
)
7107 ULONG_PTR ctx_cookie
;
7112 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
7114 hwndparent
= create_parent_window(FALSE
);
7115 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
7117 test_header_notification();
7118 test_header_notification2();
7125 test_icon_spacing();
7128 test_item_position();
7133 test_subitem_rect();
7136 test_ownerdata_multiselect();
7138 test_nosortheader();
7142 test_getitemposition();
7144 test_notifyformat();
7146 test_getitemspacing();
7147 test_getcolumnwidth();
7148 test_approximate_viewrect();
7151 test_destroynotify();
7152 test_createdragimage();
7154 test_LVM_SETITEMTEXT();
7155 test_LVM_REDRAWITEMS();
7159 test_LVM_INSERTITEM();
7161 test_oneclickactivate();
7162 test_callback_mask();
7164 test_LVSCW_AUTOSIZE();
7165 test_LVN_ENDLABELEDIT();
7166 test_LVM_GETCOUNTPERPAGE();
7167 test_item_state_change();
7168 test_LVM_SETBKIMAGE(FALSE
);
7170 if (!load_v6_module(&ctx_cookie
, &hCtx
))
7172 DestroyWindow(hwndparent
);
7178 /* comctl32 version 6 tests start here */
7179 test_get_set_view();
7180 test_canceleditlabel();
7182 test_scrollnotify();
7183 test_LVS_EX_TRANSPARENTBKGND();
7184 test_LVS_EX_HEADERINALLVIEWS();
7197 test_ownerdata_multiselect();
7199 test_nosortheader();
7203 test_destroynotify();
7204 test_createdragimage();
7206 test_LVM_SETITEMTEXT();
7207 test_LVM_REDRAWITEMS();
7208 test_oneclickactivate();
7210 test_LVSCW_AUTOSIZE();
7211 test_LVN_ENDLABELEDIT();
7212 test_LVM_GETCOUNTPERPAGE();
7213 test_item_state_change();
7214 test_selected_column();
7215 test_LVM_GETNEXTITEMINDEX();
7216 test_LVM_SETBKIMAGE(TRUE
);
7218 unload_v6_module(ctx_cookie
, hCtx
);
7220 DestroyWindow(hwndparent
);