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_ERASEBKGND
, sent
|id
|defwinproc
|optional
, 0, 0, LISTVIEW_ID
},
122 static const struct message listview_icon_spacing_seq
[] = {
123 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(20, 30) },
124 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(25, 35) },
125 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(-1, -1) },
129 static const struct message listview_color_seq
[] = {
130 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
131 { LVM_GETBKCOLOR
, sent
},
132 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
133 { LVM_GETTEXTCOLOR
, sent
},
134 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
135 { LVM_GETTEXTBKCOLOR
, sent
},
137 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
138 { LVM_GETBKCOLOR
, sent
},
139 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
140 { LVM_GETTEXTCOLOR
, sent
},
141 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
142 { LVM_GETTEXTBKCOLOR
, sent
},
144 { LVM_SETBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
145 { LVM_GETBKCOLOR
, sent
},
146 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, CLR_NONE
},
147 { LVM_GETTEXTCOLOR
, sent
},
148 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
149 { LVM_GETTEXTBKCOLOR
, sent
},
151 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
152 { LVM_GETBKCOLOR
, sent
},
153 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
154 { LVM_GETTEXTCOLOR
, sent
},
155 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
156 { LVM_GETTEXTBKCOLOR
, sent
},
160 static const struct message listview_item_count_seq
[] = {
161 { LVM_GETITEMCOUNT
, sent
},
162 { LVM_INSERTITEMA
, sent
},
163 { LVM_INSERTITEMA
, sent
},
164 { LVM_INSERTITEMA
, sent
},
165 { LVM_GETITEMCOUNT
, sent
},
166 { LVM_DELETEITEM
, sent
|wparam
, 2 },
167 { WM_NCPAINT
, sent
|optional
},
168 { WM_ERASEBKGND
, sent
|optional
},
169 { LVM_GETITEMCOUNT
, sent
},
170 { LVM_DELETEALLITEMS
, sent
},
171 { LVM_GETITEMCOUNT
, sent
},
172 { LVM_INSERTITEMA
, sent
},
173 { LVM_INSERTITEMA
, sent
},
174 { LVM_GETITEMCOUNT
, sent
},
175 { LVM_INSERTITEMA
, sent
},
176 { LVM_GETITEMCOUNT
, sent
},
180 static const struct message listview_itempos_seq
[] = {
181 { LVM_INSERTITEMA
, sent
},
182 { LVM_INSERTITEMA
, sent
},
183 { LVM_INSERTITEMA
, sent
},
184 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 1, MAKELPARAM(10,5) },
185 { WM_NCPAINT
, sent
|optional
},
186 { WM_ERASEBKGND
, sent
|optional
},
187 { LVM_GETITEMPOSITION
, sent
|wparam
, 1 },
188 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 2, MAKELPARAM(0,0) },
189 { LVM_GETITEMPOSITION
, sent
|wparam
, 2 },
190 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 0, MAKELPARAM(20,20) },
191 { LVM_GETITEMPOSITION
, sent
|wparam
, 0 },
195 static const struct message listview_ownerdata_switchto_seq
[] = {
196 { WM_STYLECHANGING
, sent
},
197 { WM_STYLECHANGED
, sent
},
201 static const struct message listview_getorderarray_seq
[] = {
202 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
203 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
204 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 0, 0, LISTVIEW_ID
},
205 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 0, 0, HEADER_ID
},
209 static const struct message listview_setorderarray_seq
[] = {
210 { LVM_SETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
211 { HDM_SETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
212 { LVM_SETCOLUMNORDERARRAY
, sent
|id
|wparam
, 0, 0, LISTVIEW_ID
},
213 { HDM_SETORDERARRAY
, sent
|id
|wparam
, 0, 0, HEADER_ID
},
217 static const struct message empty_seq
[] = {
221 static const struct message parent_focus_change_ownerdata_seq
[] = {
222 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
223 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
227 static const struct message forward_erasebkgnd_parent_seq
[] = {
228 { WM_ERASEBKGND
, sent
},
232 static const struct message ownerdata_select_focus_parent_seq
[] = {
233 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
234 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
235 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, LVN_GETDISPINFOA
}, /* version 4.7x */
239 static const struct message ownerdata_setstate_all_parent_seq
[] = {
240 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
244 static const struct message ownerdata_defocus_all_parent_seq
[] = {
245 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
246 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
247 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, LVN_GETDISPINFOA
},
248 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
252 static const struct message ownerdata_deselect_all_parent_seq
[] = {
253 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODCACHEHINT
},
254 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
258 static const struct message ownerdata_multiselect_select_0_to_1_odstatechanged_seq
[] = {
259 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
260 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODSTATECHANGED
},
261 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
262 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
266 static const struct message ownerdata_multiselect_select_0_odstatechanged_seq
[] = {
267 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
268 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
269 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
273 static const struct message ownerdata_multiselect_select_0_modkey_odstatechanged_seq
[] = {
274 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
275 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
276 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
277 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
281 static const struct message ownerdata_multiselect_move_0_to_1_odstatechanged_seq
[] = {
282 { WM_NOTIFY
, sent
|id
|wparam
, 0, 0, LVN_ITEMCHANGED
},
283 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
287 static const struct message ownerdata_multiselect_select_0_to_2_odstatechanged_seq
[] = {
288 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
289 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODSTATECHANGED
},
290 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
291 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
295 static const struct message ownerdata_multiselect_select_3_odstatechanged_seq
[] = {
296 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
297 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
298 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
302 static const struct message ownerdata_multiselect_select_3_modkey_odstatechanged_seq
[] = {
303 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
304 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
305 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
306 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
310 static const struct message ownerdata_multiselect_select_3_to_2_odstatechanged_seq
[] = {
311 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
312 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODSTATECHANGED
},
313 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
314 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
318 static const struct message ownerdata_multiselect_move_3_to_2_odstatechanged_seq
[] = {
319 { WM_NOTIFY
, sent
|id
|wparam
, 3, 0, LVN_ITEMCHANGED
},
320 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
324 static const struct message ownerdata_multiselect_select_3_to_1_odstatechanged_seq
[] = {
325 { WM_NOTIFY
, sent
|id
|wparam
, -1, 0, LVN_ITEMCHANGED
},
326 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODSTATECHANGED
},
327 { WM_NOTIFY
, sent
|id
|wparam
, 2, 0, LVN_ITEMCHANGED
},
328 { WM_NOTIFY
, sent
|id
|wparam
, 1, 0, LVN_ITEMCHANGED
},
332 static const struct message change_all_parent_seq
[] = {
333 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
334 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
336 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
337 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
339 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
340 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
342 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
343 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
345 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
346 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
350 static const struct message changing_all_parent_seq
[] = {
351 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
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
},
359 static const struct message textcallback_set_again_parent_seq
[] = {
360 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
361 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
365 static const struct message single_getdispinfo_parent_seq
[] = {
366 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
370 static const struct message getitemposition_seq1
[] = {
371 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
375 static const struct message getitemposition_seq2
[] = {
376 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
377 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
381 static const struct message getsubitemrect_seq
[] = {
382 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, -1, 0, LISTVIEW_ID
},
383 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
384 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, 0, 0, LISTVIEW_ID
},
385 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
386 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, -10, 0, LISTVIEW_ID
},
387 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
388 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, 20, 0, LISTVIEW_ID
},
389 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
393 static const struct message editbox_create_pos
[] = {
394 /* sequence sent after LVN_BEGINLABELEDIT */
395 /* next two are 4.7x specific */
396 { WM_WINDOWPOSCHANGING
, sent
},
397 { WM_WINDOWPOSCHANGED
, sent
|optional
},
399 { WM_WINDOWPOSCHANGING
, sent
|optional
},
400 { WM_NCCALCSIZE
, sent
},
401 { WM_WINDOWPOSCHANGED
, sent
},
402 { WM_MOVE
, sent
|defwinproc
},
403 { WM_SIZE
, sent
|defwinproc
},
404 /* the rest is todo, skipped in 4.7x */
405 { WM_WINDOWPOSCHANGING
, sent
|optional
},
406 { WM_WINDOWPOSCHANGED
, sent
|optional
},
410 static const struct message scroll_parent_seq
[] = {
411 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_BEGINSCROLL
},
412 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDSCROLL
},
416 static const struct message setredraw_seq
[] = {
417 { WM_SETREDRAW
, sent
|id
|wparam
, FALSE
, 0, LISTVIEW_ID
},
421 static const struct message lvs_ex_transparentbkgnd_seq
[] = {
422 { WM_PRINTCLIENT
, sent
|lparam
, 0, PRF_ERASEBKGND
},
426 static const struct message edit_end_nochange
[] = {
427 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDLABELEDITA
},
428 { WM_NOTIFY
, sent
|id
, 0, 0, NM_CUSTOMDRAW
}, /* todo */
429 { WM_NOTIFY
, sent
|id
, 0, 0, NM_SETFOCUS
},
433 static const struct message hover_parent
[] = {
434 { WM_GETDLGCODE
, sent
}, /* todo_wine */
435 { WM_NOTIFY
, sent
|id
, 0, 0, NM_HOVER
},
439 static const struct message listview_destroy
[] = {
440 { 0x0090, sent
|optional
}, /* Vista */
441 { WM_PARENTNOTIFY
, sent
},
442 { WM_SHOWWINDOW
, sent
},
443 { WM_WINDOWPOSCHANGING
, sent
},
444 { WM_WINDOWPOSCHANGED
, sent
|optional
},
445 { WM_DESTROY
, sent
},
446 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_DELETEALLITEMS
},
447 { WM_NCDESTROY
, sent
},
451 static const struct message listview_ownerdata_destroy
[] = {
452 { 0x0090, sent
|optional
}, /* Vista */
453 { WM_PARENTNOTIFY
, sent
},
454 { WM_SHOWWINDOW
, sent
},
455 { WM_WINDOWPOSCHANGING
, sent
},
456 { WM_WINDOWPOSCHANGED
, sent
|optional
},
457 { WM_DESTROY
, sent
},
458 { WM_NCDESTROY
, sent
},
462 static const struct message listview_ownerdata_deleteall
[] = {
463 { LVM_DELETEALLITEMS
, sent
},
464 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_DELETEALLITEMS
},
468 static const struct message listview_header_changed_seq
[] = {
469 { LVM_SETCOLUMNA
, sent
},
470 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
471 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
475 static const struct message parent_header_click_seq
[] = {
476 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_COLUMNCLICK
},
477 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_ITEMCLICKA
},
481 static const struct message parent_header_divider_dclick_seq
[] = {
482 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_ITEMCHANGINGA
},
483 { WM_NOTIFY
, sent
|id
, 0, 0, NM_CUSTOMDRAW
},
484 { WM_NOTIFY
, sent
|id
, 0, 0, NM_CUSTOMDRAW
},
485 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_ITEMCHANGEDA
},
486 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_DIVIDERDBLCLICKA
},
490 static const struct message listview_set_imagelist
[] = {
491 { LVM_SETIMAGELIST
, sent
|id
, 0, 0, LISTVIEW_ID
},
495 static const struct message listview_header_set_imagelist
[] = {
496 { LVM_SETIMAGELIST
, sent
|id
, 0, 0, LISTVIEW_ID
},
497 { HDM_SETIMAGELIST
, sent
|id
, 0, 0, HEADER_ID
},
501 static const struct message parent_report_cd_seq
[] = {
502 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_PREPAINT
},
503 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
},
504 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
|CDDS_SUBITEM
},
505 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
|CDDS_SUBITEM
},
506 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
|CDDS_SUBITEM
},
507 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
|CDDS_SUBITEM
},
508 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
},
509 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_POSTPAINT
},
513 static const struct message parent_list_cd_seq
[] = {
514 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_PREPAINT
},
515 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
},
516 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
},
517 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_POSTPAINT
},
521 static const struct message listview_end_label_edit
[] = {
522 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDLABELEDITA
},
523 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
524 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
525 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, NM_CUSTOMDRAW
}, /* XP */
526 { WM_NOTIFY
, sent
|id
, 0, 0, NM_SETFOCUS
},
530 static const struct message listview_end_label_edit_kill_focus
[] = {
531 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDLABELEDITA
},
532 { WM_COMMAND
, sent
|id
|optional
, 0, 0, EN_KILLFOCUS
}, /* todo: not sent by wine yet */
533 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
534 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
535 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, NM_CUSTOMDRAW
}, /* XP */
536 { WM_NOTIFY
, sent
|id
, 0, 0, NM_SETFOCUS
},
540 static void hold_key(int vk
)
545 res
= GetKeyboardState(kstate
);
546 ok(res
, "GetKeyboardState failed.\n");
548 res
= SetKeyboardState(kstate
);
549 ok(res
, "SetKeyboardState failed.\n");
552 static void release_key(int vk
)
557 res
= GetKeyboardState(kstate
);
558 ok(res
, "GetKeyboardState failed.\n");
560 res
= SetKeyboardState(kstate
);
561 ok(res
, "SetKeyboardState failed.\n");
564 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
566 static LONG defwndproc_counter
= 0;
570 msg
.message
= message
;
571 msg
.flags
= sent
|wparam
|lparam
;
572 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
575 if (message
== WM_NOTIFY
&& lParam
)
577 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
579 msg
.id
= nmlv
->hdr
.code
;
580 if (msg
.id
== LVN_ITEMCHANGING
|| msg
.id
== LVN_ITEMCHANGED
)
582 msg
.wParam
= nmlv
->iItem
;
583 msg
.lParam
= nmlv
->uChanged
;
586 if (message
== WM_COMMAND
) msg
.id
= HIWORD(wParam
);
588 /* log system messages, except for painting */
589 if (message
< WM_USER
&&
590 message
!= WM_PAINT
&&
591 message
!= WM_ERASEBKGND
&&
592 message
!= WM_NCPAINT
&&
593 message
!= WM_NCHITTEST
&&
594 message
!= WM_GETTEXT
&&
595 message
!= WM_GETICON
&&
596 message
!= WM_DEVICECHANGE
)
598 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
599 add_message(sequences
, COMBINED_SEQ_INDEX
, &msg
);
601 /* log change messages for single and multiple items changing in ownerdata listviews */
602 if (message
== WM_NOTIFY
&& (msg
.id
== LVN_ITEMCHANGED
|| msg
.id
== LVN_ODSTATECHANGED
))
603 add_message(sequences
, PARENT_ODSTATECHANGED_SEQ_INDEX
, &msg
);
605 add_message(sequences
, PARENT_FULL_SEQ_INDEX
, &msg
);
611 switch (((NMHDR
*)lParam
)->code
)
613 case LVN_BEGINLABELEDITA
:
617 /* subclass edit box */
619 edit
= subclass_editbox(((NMHDR
*)lParam
)->hwndFrom
);
623 INT len
= SendMessageA(edit
, EM_GETLIMITTEXT
, 0, 0);
624 ok(len
== 259 || broken(len
== 260) /* includes NULL in NT4 */,
625 "text limit %d, expected 259\n", len
);
630 case LVN_ENDLABELEDITA
:
634 /* always accept new item text */
635 NMLVDISPINFOA
*di
= (NMLVDISPINFOA
*)lParam
;
636 g_editbox_disp_info
= *di
;
638 /* edit control still available from this notification */
639 edit
= (HWND
)SendMessageA(((NMHDR
*)lParam
)->hwndFrom
, LVM_GETEDITCONTROL
, 0, 0);
640 ok(IsWindow(edit
), "expected valid edit control handle\n");
641 ok((GetWindowLongA(edit
, GWL_STYLE
) & ES_MULTILINE
) == 0, "edit is multiline\n");
643 if (g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT
)
644 SendMessageA(edit
, WM_KILLFOCUS
, 0, 0);
648 case LVN_ITEMCHANGING
:
650 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
651 g_nmlistview_changing
= *nmlv
;
654 case LVN_ITEMCHANGED
:
656 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
657 g_nmlistview
= *nmlv
;
660 case LVN_GETDISPINFOA
:
662 NMLVDISPINFOA
*dispinfo
= (NMLVDISPINFOA
*)lParam
;
663 g_itema
= dispinfo
->item
;
665 if (g_disp_A_to_W
&& (dispinfo
->item
.mask
& LVIF_TEXT
))
667 dispinfo
->hdr
.code
= LVN_GETDISPINFOW
;
668 lstrcpyW((WCHAR
*)dispinfo
->item
.pszText
, L
"TEST");
671 /* test control buffer size for text, 10 used to mask cases when control
672 is using caller buffer to process LVM_GETITEM for example */
673 if (dispinfo
->item
.mask
& LVIF_TEXT
&& dispinfo
->item
.cchTextMax
> 10)
674 ok(dispinfo
->item
.cchTextMax
== 260 ||
675 broken(dispinfo
->item
.cchTextMax
== 264) /* NT4 reports aligned size */,
676 "buffer size %d\n", dispinfo
->item
.cchTextMax
);
680 if (g_focus_test_LVN_DELETEITEM
)
682 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
685 state
= SendMessageA(((NMHDR
*)lParam
)->hwndFrom
, LVM_GETITEMSTATE
, nmlv
->iItem
, LVIS_FOCUSED
);
686 ok(state
== 0, "got state %x\n", state
);
690 if (g_block_hover
) return 1;
695 case WM_NOTIFYFORMAT
:
697 /* force to return format */
698 if (lParam
== NF_QUERY
&& notifyFormat
!= -1) return notifyFormat
;
703 defwndproc_counter
++;
704 if (IsWindowUnicode(hwnd
))
705 ret
= DefWindowProcW(hwnd
, message
, wParam
, lParam
);
707 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
708 defwndproc_counter
--;
713 static BOOL
register_parent_wnd_class(BOOL Unicode
)
721 clsW
.lpfnWndProc
= parent_wnd_proc
;
724 clsW
.hInstance
= GetModuleHandleW(NULL
);
726 clsW
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
727 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
728 clsW
.lpszMenuName
= NULL
;
729 clsW
.lpszClassName
= L
"Listview test parentW";
734 clsA
.lpfnWndProc
= parent_wnd_proc
;
737 clsA
.hInstance
= GetModuleHandleA(NULL
);
739 clsA
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
740 clsA
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
741 clsA
.lpszMenuName
= NULL
;
742 clsA
.lpszClassName
= "Listview test parent class";
745 return Unicode
? RegisterClassW(&clsW
) : RegisterClassA(&clsA
);
748 static HWND
create_parent_window(BOOL Unicode
)
752 if (!register_parent_wnd_class(Unicode
))
759 hwnd
= CreateWindowExW(0, L
"Listview test parentW", L
"testparentnameW",
760 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
761 WS_MAXIMIZEBOX
| WS_VISIBLE
,
763 GetDesktopWindow(), NULL
, GetModuleHandleW(NULL
), NULL
);
765 hwnd
= CreateWindowExA(0, "Listview test parent class",
766 "Listview test parent window",
767 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
768 WS_MAXIMIZEBOX
| WS_VISIBLE
,
770 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
771 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
775 static LRESULT WINAPI
listview_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
777 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
778 static LONG defwndproc_counter
= 0;
782 msg
.message
= message
;
783 msg
.flags
= sent
|wparam
|lparam
;
784 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
787 msg
.id
= LISTVIEW_ID
;
788 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
789 add_message(sequences
, COMBINED_SEQ_INDEX
, &msg
);
791 defwndproc_counter
++;
792 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
793 defwndproc_counter
--;
797 static HWND
create_listview_control(DWORD style
)
803 GetClientRect(hwndparent
, &rect
);
804 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo",
805 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
806 0, 0, rect
.right
, rect
.bottom
,
807 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
808 ok(hwnd
!= NULL
, "gle=%ld\n", GetLastError());
810 if (!hwnd
) return NULL
;
814 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
815 (LONG_PTR
)listview_subclass_proc
);
816 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
821 /* unicode listview window with specified parent */
822 static HWND
create_listview_controlW(DWORD style
, HWND parent
)
828 GetClientRect(parent
, &rect
);
829 hwnd
= CreateWindowExW(0, WC_LISTVIEWW
, L
"foo",
830 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
831 0, 0, rect
.right
, rect
.bottom
,
832 parent
, NULL
, GetModuleHandleW(NULL
), NULL
);
833 ok(hwnd
!= NULL
, "gle=%ld\n", GetLastError());
835 if (!hwnd
) return NULL
;
839 oldproc
= (WNDPROC
)SetWindowLongPtrW(hwnd
, GWLP_WNDPROC
,
840 (LONG_PTR
)listview_subclass_proc
);
841 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
847 static LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
849 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
850 static LONG defwndproc_counter
= 0;
851 struct message msg
= { 0 };
854 msg
.message
= message
;
855 msg
.flags
= sent
|wparam
|lparam
;
856 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
860 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
862 defwndproc_counter
++;
863 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
864 defwndproc_counter
--;
868 static HWND
subclass_header(HWND hwndListview
)
873 hwnd
= (HWND
)SendMessageA(hwndListview
, LVM_GETHEADER
, 0, 0);
874 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
875 (LONG_PTR
)header_subclass_proc
);
876 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
881 static LRESULT WINAPI
editbox_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
883 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
884 static LONG defwndproc_counter
= 0;
885 struct message msg
= { 0 };
888 msg
.message
= message
;
889 msg
.flags
= sent
|wparam
|lparam
;
890 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
894 /* all we need is sizing */
895 if (message
== WM_WINDOWPOSCHANGING
||
896 message
== WM_NCCALCSIZE
||
897 message
== WM_WINDOWPOSCHANGED
||
898 message
== WM_MOVE
||
901 add_message(sequences
, EDITBOX_SEQ_INDEX
, &msg
);
904 defwndproc_counter
++;
905 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
906 defwndproc_counter
--;
910 static HWND
subclass_editbox(HWND hwndListview
)
915 hwnd
= (HWND
)SendMessageA(hwndListview
, LVM_GETEDITCONTROL
, 0, 0);
916 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
917 (LONG_PTR
)editbox_subclass_proc
);
918 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
923 /* Performs a single LVM_HITTEST test */
924 static void test_lvm_hittest_(HWND hwnd
, INT x
, INT y
, INT item
, UINT flags
, UINT broken_flags
,
925 BOOL todo_item
, BOOL todo_flags
, int line
)
934 ret
= SendMessageA(hwnd
, LVM_HITTEST
, 0, (LPARAM
)&lpht
);
936 todo_wine_if(todo_item
)
938 ok_(__FILE__
, line
)(ret
== item
, "Expected %d retval, got %d\n", item
, ret
);
939 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
940 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
946 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags 0x%x, got 0x%x\n", flags
, lpht
.flags
);
948 else if (broken_flags
)
949 ok_(__FILE__
, line
)(lpht
.flags
== flags
|| broken(lpht
.flags
== broken_flags
),
950 "Expected flags %x, got %x\n", flags
, lpht
.flags
);
952 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags 0x%x, got 0x%x\n", flags
, lpht
.flags
);
955 #define test_lvm_hittest(a,b,c,d,e,f,g,h) test_lvm_hittest_(a,b,c,d,e,f,g,h,__LINE__)
957 /* Performs a single LVM_SUBITEMHITTEST test */
958 static void test_lvm_subitemhittest_(HWND hwnd
, INT x
, INT y
, INT item
, INT subitem
, UINT flags
,
959 BOOL todo_item
, BOOL todo_subitem
, BOOL todo_flags
, int line
)
967 ret
= SendMessageA(hwnd
, LVM_SUBITEMHITTEST
, 0, (LPARAM
)&lpht
);
969 todo_wine_if(todo_item
)
971 ok_(__FILE__
, line
)(ret
== item
, "Expected %d retval, got %d\n", item
, ret
);
972 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
975 todo_wine_if(todo_subitem
)
976 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
978 todo_wine_if(todo_flags
)
979 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags 0x%x, got 0x%x\n", flags
, lpht
.flags
);
982 #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__)
984 static void test_images(void)
992 static CHAR hello
[] = "hello";
994 himl
= pImageList_Create(40, 40, 0, 4, 4);
995 ok(himl
!= NULL
, "failed to create imagelist\n");
997 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
998 ok(hbmp
!= NULL
, "failed to create bitmap\n");
1000 r
= pImageList_Add(himl
, hbmp
, 0);
1001 ok(r
== 0, "should be zero\n");
1003 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_OWNERDRAWFIXED
,
1004 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1005 ok(hwnd
!= NULL
, "failed to create listview window\n");
1007 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0,
1008 LVS_EX_UNDERLINEHOT
| LVS_EX_FLATSB
| LVS_EX_ONECLICKACTIVATE
);
1010 ok(r
== 0, "should return zero\n");
1012 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
1013 ok(r
== 0, "should return zero\n");
1015 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELONG(100,50));
1016 ok(r
!= 0, "got 0\n");
1018 /* returns dimensions */
1020 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1021 ok(r
== 0, "should be zero items\n");
1023 item
.mask
= LVIF_IMAGE
| LVIF_TEXT
;
1028 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1029 ok(r
== -1, "should fail\n");
1032 item
.pszText
= hello
;
1033 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1034 ok(r
== 0, "should not fail\n");
1036 SetRect(&r1
, LVIR_ICON
, 0, 0, 0);
1037 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r1
);
1040 r
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1041 ok(r
== TRUE
, "should not fail\n");
1044 item
.pszText
= hello
;
1045 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1046 ok(r
== 0, "should not fail\n");
1048 SetRect(&r2
, LVIR_ICON
, 0, 0, 0);
1049 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r2
);
1052 ok(EqualRect(&r1
, &r2
), "rectangle should be the same\n");
1054 DestroyWindow(hwnd
);
1056 /* I_IMAGECALLBACK set for item, try to get image with invalid subitem. */
1057 hwnd
= create_listview_control(LVS_REPORT
);
1058 ok(hwnd
!= NULL
, "Failed to create listview.\n");
1060 memset(&item
, 0, sizeof(item
));
1061 item
.mask
= LVIF_IMAGE
;
1062 item
.iImage
= I_IMAGECALLBACK
;
1063 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
1064 ok(!r
, "Failed to insert item.\n");
1066 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1068 memset(&item
, 0, sizeof(item
));
1069 item
.mask
= LVIF_IMAGE
;
1070 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
1071 ok(r
, "Failed to get item.\n");
1073 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
, "get image dispinfo 1", FALSE
);
1075 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1077 memset(&item
, 0, sizeof(item
));
1078 item
.mask
= LVIF_IMAGE
;
1080 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
1081 ok(r
, "Failed to get item.\n");
1083 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "get image dispinfo 2", FALSE
);
1085 DestroyWindow(hwnd
);
1088 static void test_checkboxes(void)
1093 static CHAR text
[] = "Text",
1097 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_REPORT
,
1098 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1099 ok(hwnd
!= NULL
, "failed to create listview window\n");
1101 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
1102 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
1103 item
.stateMask
= 0xffff;
1104 item
.state
= 0xfccc;
1107 item
.pszText
= text
;
1108 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1112 item
.mask
= LVIF_STATE
;
1113 item
.stateMask
= 0xffff;
1114 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1116 ok(item
.state
== 0xfccc, "state %x\n", item
.state
);
1118 /* Don't set LVIF_STATE */
1119 item
.mask
= LVIF_TEXT
;
1120 item
.stateMask
= 0xffff;
1121 item
.state
= 0xfccc;
1124 item
.pszText
= text
;
1125 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1129 item
.mask
= LVIF_STATE
;
1130 item
.stateMask
= 0xffff;
1131 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1133 ok(item
.state
== 0, "state %x\n", item
.state
);
1135 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
1138 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
1140 item
.mask
= LVIF_STATE
;
1141 item
.stateMask
= 0xffff;
1142 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1145 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
1147 item
.mask
= LVIF_TEXT
;
1149 item
.pszText
= text2
;
1150 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1154 item
.mask
= LVIF_STATE
;
1155 item
.stateMask
= 0xffff;
1156 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1158 ok(item
.state
== 0x1000, "state %x\n", item
.state
);
1160 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
1162 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
1163 item
.stateMask
= 0xffff;
1164 item
.state
= 0x2aaa;
1165 item
.pszText
= text3
;
1166 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1170 item
.mask
= LVIF_STATE
;
1171 item
.stateMask
= 0xffff;
1172 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1174 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
1176 /* Set an item's state to checked */
1178 item
.mask
= LVIF_STATE
;
1179 item
.stateMask
= 0xf000;
1180 item
.state
= 0x2000;
1181 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1185 item
.mask
= LVIF_STATE
;
1186 item
.stateMask
= 0xffff;
1187 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1189 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
1191 /* Check that only the bits we asked for are returned,
1192 * and that all the others are set to zero
1195 item
.mask
= LVIF_STATE
;
1196 item
.stateMask
= 0xf000;
1197 item
.state
= 0xffff;
1198 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1200 ok(item
.state
== 0x2000, "state %x\n", item
.state
);
1202 /* Set the style again and check that doesn't change an item's state */
1203 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
1204 ok(r
== LVS_EX_CHECKBOXES
, "ret %lx\n", r
);
1207 item
.mask
= LVIF_STATE
;
1208 item
.stateMask
= 0xffff;
1209 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1211 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
1213 /* Unsetting the checkbox extended style doesn't change an item's state */
1214 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
1215 ok(r
== LVS_EX_CHECKBOXES
, "ret %lx\n", r
);
1218 item
.mask
= LVIF_STATE
;
1219 item
.stateMask
= 0xffff;
1220 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1222 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
1224 /* Now setting the style again will change an item's state */
1225 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
1229 item
.mask
= LVIF_STATE
;
1230 item
.stateMask
= 0xffff;
1231 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1233 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
1235 /* Toggle checkbox tests (bug 9934) */
1236 memset (&item
, 0xcc, sizeof(item
));
1237 item
.mask
= LVIF_STATE
;
1240 item
.state
= LVIS_FOCUSED
;
1241 item
.stateMask
= LVIS_FOCUSED
;
1242 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1246 item
.mask
= LVIF_STATE
;
1247 item
.stateMask
= 0xffff;
1248 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1250 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
1252 r
= SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
1254 r
= SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
1258 item
.mask
= LVIF_STATE
;
1259 item
.stateMask
= 0xffff;
1260 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1262 ok(item
.state
== 0x2aab, "state %x\n", item
.state
);
1264 r
= SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
1266 r
= SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
1270 item
.mask
= LVIF_STATE
;
1271 item
.stateMask
= 0xffff;
1272 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1274 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
1276 DestroyWindow(hwnd
);
1279 static void insert_column(HWND hwnd
, int idx
)
1284 memset(&column
, 0xcc, sizeof(column
));
1285 column
.mask
= LVCF_SUBITEM
;
1286 column
.iSubItem
= idx
;
1288 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, idx
, (LPARAM
)&column
);
1292 static void insert_item(HWND hwnd
, int idx
)
1294 static CHAR text
[] = "foo";
1299 memset(&item
, 0xcc, sizeof (item
));
1300 item
.mask
= LVIF_TEXT
;
1303 item
.pszText
= text
;
1305 rc
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
1309 static void test_items(void)
1311 const LPARAM lparamTest
= 0x42;
1312 static CHAR text
[] = "Text";
1318 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_REPORT
,
1319 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1320 ok(hwnd
!= NULL
, "failed to create listview window\n");
1323 * Test setting/getting item params
1326 /* Set up two columns */
1327 insert_column(hwnd
, 0);
1328 insert_column(hwnd
, 1);
1330 /* LVIS_SELECTED with zero stateMask */
1332 memset (&item
, 0, sizeof (item
));
1333 item
.mask
= LVIF_STATE
;
1334 item
.state
= LVIS_SELECTED
;
1338 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1341 memset (&item
, 0xcc, sizeof (item
));
1342 item
.mask
= LVIF_STATE
;
1343 item
.stateMask
= LVIS_SELECTED
;
1347 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1349 ok(item
.state
& LVIS_SELECTED
, "Expected LVIS_SELECTED\n");
1350 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
1351 ok(r
, "got %ld\n", r
);
1353 /* LVIS_SELECTED with zero stateMask */
1355 memset (&item
, 0, sizeof (item
));
1356 item
.mask
= LVIF_STATE
;
1357 item
.state
= LVIS_FOCUSED
;
1361 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1364 memset (&item
, 0xcc, sizeof (item
));
1365 item
.mask
= LVIF_STATE
;
1366 item
.stateMask
= LVIS_FOCUSED
;
1370 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1372 ok(item
.state
& LVIS_FOCUSED
, "Expected LVIS_FOCUSED\n");
1373 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
1374 ok(r
, "got %ld\n", r
);
1376 /* LVIS_CUT with LVIS_FOCUSED stateMask */
1378 memset (&item
, 0, sizeof (item
));
1379 item
.mask
= LVIF_STATE
;
1380 item
.state
= LVIS_CUT
;
1381 item
.stateMask
= LVIS_FOCUSED
;
1384 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1387 memset (&item
, 0xcc, sizeof (item
));
1388 item
.mask
= LVIF_STATE
;
1389 item
.stateMask
= LVIS_CUT
;
1393 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1395 ok(item
.state
& LVIS_CUT
, "Expected LVIS_CUT\n");
1396 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
1397 ok(r
, "got %ld\n", r
);
1399 /* Insert an item with just a param */
1400 memset (&item
, 0xcc, sizeof (item
));
1401 item
.mask
= LVIF_PARAM
;
1404 item
.lParam
= lparamTest
;
1405 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1408 /* Test getting of the param */
1409 memset (&item
, 0xcc, sizeof (item
));
1410 item
.mask
= LVIF_PARAM
;
1413 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1415 ok(item
.lParam
== lparamTest
, "got lParam %Ix, expected %Ix\n", item
.lParam
, lparamTest
);
1417 /* Set up a subitem */
1418 memset (&item
, 0xcc, sizeof (item
));
1419 item
.mask
= LVIF_TEXT
;
1422 item
.pszText
= text
;
1423 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1426 item
.mask
= LVIF_TEXT
;
1429 item
.pszText
= buffA
;
1430 item
.cchTextMax
= sizeof(buffA
);
1431 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1433 ok(!memcmp(item
.pszText
, text
, sizeof(text
)), "got text %s, expected %s\n", item
.pszText
, text
);
1435 /* set up with extra flag */
1436 /* 1. reset subitem text */
1437 item
.mask
= LVIF_TEXT
;
1440 item
.pszText
= NULL
;
1441 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1444 item
.mask
= LVIF_TEXT
;
1447 item
.pszText
= buffA
;
1449 item
.cchTextMax
= sizeof(buffA
);
1450 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1452 ok(item
.pszText
[0] == 0, "got %p\n", item
.pszText
);
1454 /* 2. set new text with extra flag specified */
1455 item
.mask
= LVIF_TEXT
| LVIF_DI_SETITEM
;
1458 item
.pszText
= text
;
1459 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1460 ok(r
== 1 || broken(r
== 0) /* NT4 */, "ret %ld\n", r
);
1464 item
.mask
= LVIF_TEXT
;
1467 item
.pszText
= buffA
;
1469 item
.cchTextMax
= sizeof(buffA
);
1470 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1472 ok(!memcmp(item
.pszText
, text
, sizeof(text
)), "got %s, expected %s\n", item
.pszText
, text
);
1475 /* Query param from subitem: returns main item param */
1476 memset (&item
, 0xcc, sizeof (item
));
1477 item
.mask
= LVIF_PARAM
;
1480 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1482 ok(item
.lParam
== lparamTest
, "got lParam %Ix, expected %Ix\n", item
.lParam
, lparamTest
);
1484 /* Set up param on first subitem: no effect */
1485 memset (&item
, 0xcc, sizeof (item
));
1486 item
.mask
= LVIF_PARAM
;
1489 item
.lParam
= lparamTest
+1;
1490 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1493 /* Query param from subitem again: should still return main item param */
1494 memset (&item
, 0xcc, sizeof (item
));
1495 item
.mask
= LVIF_PARAM
;
1498 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1500 ok(item
.lParam
== lparamTest
, "got lParam %Ix, expected %Ix\n", item
.lParam
, lparamTest
);
1502 /**** Some tests of state highlighting ****/
1503 memset (&item
, 0xcc, sizeof (item
));
1504 item
.mask
= LVIF_STATE
;
1507 item
.state
= LVIS_SELECTED
;
1508 item
.stateMask
= LVIS_SELECTED
| LVIS_DROPHILITED
;
1509 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1512 item
.state
= LVIS_DROPHILITED
;
1513 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1516 memset (&item
, 0xcc, sizeof (item
));
1517 item
.mask
= LVIF_STATE
;
1520 item
.stateMask
= -1;
1521 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1523 ok(item
.state
== LVIS_SELECTED
, "got state %x, expected %x\n", item
.state
, LVIS_SELECTED
);
1525 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1527 todo_wine
ok(item
.state
== LVIS_DROPHILITED
, "got state %x, expected %x\n", item
.state
, LVIS_DROPHILITED
);
1529 /* some notnull but meaningless masks */
1530 memset (&item
, 0, sizeof(item
));
1531 item
.mask
= LVIF_NORECOMPUTE
;
1534 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1536 memset (&item
, 0, sizeof(item
));
1537 item
.mask
= LVIF_DI_SETITEM
;
1540 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1543 /* set text to callback value already having it */
1544 r
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1546 memset (&item
, 0, sizeof (item
));
1547 item
.mask
= LVIF_TEXT
;
1548 item
.pszText
= LPSTR_TEXTCALLBACKA
;
1550 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1552 memset (&item
, 0, sizeof (item
));
1554 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1556 item
.pszText
= LPSTR_TEXTCALLBACKA
;
1557 r
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0 , (LPARAM
) &item
);
1560 ok_sequence(sequences
, PARENT_SEQ_INDEX
, textcallback_set_again_parent_seq
,
1561 "check callback text comparison rule", FALSE
);
1563 DestroyWindow(hwnd
);
1566 static void test_columns(void)
1575 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_LIST
,
1576 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1577 ok(hwnd
!= NULL
, "failed to create listview window\n");
1579 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1580 ok(header
== NULL
, "got %p\n", header
);
1582 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1583 ok(rc
== 0, "got %ld\n", rc
);
1585 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1586 ok(header
== NULL
, "got %p\n", header
);
1588 DestroyWindow(hwnd
);
1590 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", LVS_REPORT
,
1591 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1592 ok(hwnd
!= NULL
, "failed to create listview window\n");
1594 rc
= SendMessageA(hwnd
, LVM_DELETECOLUMN
, -1, 0);
1595 ok(!rc
, "got %ld\n", rc
);
1597 rc
= SendMessageA(hwnd
, LVM_DELETECOLUMN
, 0, 0);
1598 ok(!rc
, "got %ld\n", rc
);
1600 /* Add a column with no mask */
1601 memset(&column
, 0xcc, sizeof(column
));
1603 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&column
);
1604 ok(rc
== 0, "Inserting column with no mask failed with %ld\n", rc
);
1606 /* Check its width */
1607 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
1608 ok(rc
== 10, "Inserting column with no mask failed to set width to 10 with %ld\n", rc
);
1610 DestroyWindow(hwnd
);
1612 /* LVM_GETCOLUMNORDERARRAY */
1613 hwnd
= create_listview_control(LVS_REPORT
);
1614 subclass_header(hwnd
);
1616 memset(&column
, 0, sizeof(column
));
1617 column
.mask
= LVCF_WIDTH
;
1619 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&column
);
1623 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 1, (LPARAM
)&column
);
1626 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1628 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1630 ok(order
[0] == 0, "Expected order 0, got %d\n", order
[0]);
1631 ok(order
[1] == 1, "Expected order 1, got %d\n", order
[1]);
1633 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNORDERARRAY
, 0, 0);
1636 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_getorderarray_seq
, "get order array", FALSE
);
1638 /* LVM_SETCOLUMNORDERARRAY */
1639 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1643 rc
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1646 rc
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 0, 0);
1649 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_setorderarray_seq
, "set order array", FALSE
);
1651 /* after column added subitem is considered as present */
1652 insert_item(hwnd
, 0);
1654 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1656 item
.pszText
= buff
;
1657 item
.cchTextMax
= sizeof(buff
);
1660 item
.mask
= LVIF_TEXT
;
1661 memset(&g_itema
, 0, sizeof(g_itema
));
1662 rc
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
1664 ok(g_itema
.iSubItem
== 1, "got %d\n", g_itema
.iSubItem
);
1666 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
1667 "get subitem text after column added", FALSE
);
1669 DestroyWindow(hwnd
);
1671 /* Columns are not created right away. */
1672 hwnd
= create_listview_control(LVS_REPORT
);
1673 ok(hwnd
!= NULL
, "Failed to create a listview window.\n");
1675 insert_item(hwnd
, 0);
1677 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1678 ok(IsWindow(header
), "Expected header handle.\n");
1679 rc
= SendMessageA(header
, HDM_GETITEMCOUNT
, 0, 0);
1680 ok(!rc
, "Unexpected column count.\n");
1682 DestroyWindow(hwnd
);
1685 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1686 static WNDPROC listviewWndProc
;
1687 static HIMAGELIST test_create_imagelist
;
1689 static LRESULT CALLBACK
create_test_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1693 if (uMsg
== WM_CREATE
)
1695 CREATESTRUCTA
*lpcs
= (CREATESTRUCTA
*)lParam
;
1696 lpcs
->style
|= LVS_REPORT
;
1698 ret
= CallWindowProcA(listviewWndProc
, hwnd
, uMsg
, wParam
, lParam
);
1699 if (uMsg
== WM_CREATE
) SendMessageA(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)test_create_imagelist
);
1703 /* Header creation is delayed in classic implementation. */
1704 #define TEST_NO_HEADER(a) test_header_presence_(a, FALSE, __LINE__)
1705 #define TEST_HEADER_EXPECTED(a) test_header_presence_(a, TRUE, __LINE__)
1706 #define TEST_NO_HEADER2(a, b) test_header_presence_(a, b, __LINE__)
1707 static void test_header_presence_(HWND hwnd
, BOOL present
, int line
)
1709 HWND header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1713 ok_(__FILE__
, line
)(IsWindow(header
), "Header should have been created.\n");
1714 if (header
) /* FIXME: remove when todo's are fixed */
1715 ok_(__FILE__
, line
)(header
== GetDlgItem(hwnd
, 0), "Dialog item expected.\n");
1719 ok_(__FILE__
, line
)(!IsWindow(header
), "Header shouldn't be created.\n");
1720 ok_(__FILE__
, line
)(NULL
== GetDlgItem(hwnd
, 0), "NULL dialog item expected.\n");
1724 static void test_create(BOOL is_version_6
)
1737 cls
.cbSize
= sizeof(WNDCLASSEXA
);
1738 r
= GetClassInfoExA(GetModuleHandleA(NULL
), WC_LISTVIEWA
, &cls
);
1739 ok(r
, "Failed to get class info.\n");
1740 listviewWndProc
= cls
.lpfnWndProc
;
1741 cls
.lpfnWndProc
= create_test_wndproc
;
1742 cls
.lpszClassName
= "MyListView32";
1743 class = RegisterClassExA(&cls
);
1744 ok(class, "Failed to register class.\n");
1746 test_create_imagelist
= pImageList_Create(16, 16, 0, 5, 10);
1747 hList
= CreateWindowA("MyListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1748 ok((HIMAGELIST
)SendMessageA(hList
, LVM_GETIMAGELIST
, 0, 0) == test_create_imagelist
, "Image list not obtained\n");
1749 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1750 ok(IsWindow(hHeader
) && IsWindowVisible(hHeader
), "Listview not in report mode\n");
1751 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1752 DestroyWindow(hList
);
1754 /* header isn't created on LVS_ICON and LVS_LIST styles */
1755 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1756 TEST_NO_HEADER(hList
);
1759 memset(&col
, 0, sizeof(LVCOLUMNA
));
1760 col
.mask
= LVCF_WIDTH
;
1762 r
= SendMessageA(hList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
1764 TEST_HEADER_EXPECTED(hList
);
1765 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1766 style
= GetWindowLongA(hHeader
, GWL_STYLE
);
1767 ok(!(style
& HDS_HIDDEN
), "Not expected HDS_HIDDEN\n");
1768 DestroyWindow(hList
);
1770 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1771 GetModuleHandleA(NULL
), 0);
1772 TEST_NO_HEADER(hList
);
1774 memset(&col
, 0, sizeof(LVCOLUMNA
));
1775 col
.mask
= LVCF_WIDTH
;
1777 r
= SendMessageA(hList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
1779 TEST_HEADER_EXPECTED(hList
);
1780 DestroyWindow(hList
);
1782 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1783 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1784 GetModuleHandleA(NULL
), 0);
1785 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
, GetWindowLongPtrA(hList
, GWL_STYLE
) | LVS_REPORT
);
1786 ok(ret
& WS_VISIBLE
, "Style wrong, should have WS_VISIBLE\n");
1787 TEST_HEADER_EXPECTED(hList
);
1788 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
, GetWindowLongA(hList
, GWL_STYLE
) & ~LVS_REPORT
);
1789 ok((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1790 TEST_HEADER_EXPECTED(hList
);
1791 DestroyWindow(hList
);
1793 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1794 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1795 GetModuleHandleA(NULL
), 0);
1796 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
,
1797 (GetWindowLongPtrA(hList
, GWL_STYLE
) & ~LVS_LIST
) | LVS_REPORT
);
1798 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_LIST
)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1799 TEST_HEADER_EXPECTED(hList
);
1800 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
, (GetWindowLongPtrA(hList
, GWL_STYLE
) & ~LVS_REPORT
) | LVS_LIST
);
1801 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1802 TEST_HEADER_EXPECTED(hList
);
1803 DestroyWindow(hList
);
1805 /* LVS_REPORT without WS_VISIBLE */
1806 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1807 GetModuleHandleA(NULL
), 0);
1808 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1809 todo_wine_if(is_version_6
)
1810 TEST_NO_HEADER2(hList
, is_version_6
);
1813 memset(&col
, 0, sizeof(LVCOLUMNA
));
1814 col
.mask
= LVCF_WIDTH
;
1816 r
= SendMessageA(hList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
1818 TEST_HEADER_EXPECTED(hList
);
1819 DestroyWindow(hList
);
1821 /* LVS_REPORT without WS_VISIBLE, try to show it */
1822 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1823 GetModuleHandleA(NULL
), 0);
1824 todo_wine_if(is_version_6
)
1825 TEST_NO_HEADER2(hList
, is_version_6
);
1827 ShowWindow(hList
, SW_SHOW
);
1828 TEST_HEADER_EXPECTED(hList
);
1829 DestroyWindow(hList
);
1831 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1832 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
|LVS_NOCOLUMNHEADER
|WS_VISIBLE
,
1833 0, 0, 100, 100, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1834 TEST_HEADER_EXPECTED(hList
);
1835 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1836 /* HDS_DRAGDROP set by default */
1837 ok(GetWindowLongPtrA(hHeader
, GWL_STYLE
) & HDS_DRAGDROP
, "Expected header to have HDS_DRAGDROP\n");
1838 DestroyWindow(hList
);
1840 /* setting LVS_EX_HEADERDRAGDROP creates header */
1841 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1842 GetModuleHandleA(NULL
), 0);
1843 todo_wine_if(is_version_6
)
1844 TEST_NO_HEADER2(hList
, is_version_6
);
1846 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1847 TEST_HEADER_EXPECTED(hList
);
1848 DestroyWindow(hList
);
1850 /* setting LVS_EX_GRIDLINES creates header */
1851 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1852 GetModuleHandleA(NULL
), 0);
1853 todo_wine_if(is_version_6
)
1854 TEST_NO_HEADER2(hList
, is_version_6
);
1856 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_GRIDLINES
);
1857 TEST_HEADER_EXPECTED(hList
);
1858 DestroyWindow(hList
);
1860 /* setting LVS_EX_FULLROWSELECT creates header */
1861 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1862 GetModuleHandleA(NULL
), 0);
1863 todo_wine_if(is_version_6
)
1864 TEST_NO_HEADER2(hList
, is_version_6
);
1865 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
1866 TEST_HEADER_EXPECTED(hList
);
1867 DestroyWindow(hList
);
1869 /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1870 hList
= create_listview_control(LVS_ICON
);
1871 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1872 r
= SendMessageA(hList
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1873 ok(r
& LVS_EX_HEADERDRAGDROP
, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1874 DestroyWindow(hList
);
1876 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1877 hList
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1878 GetModuleHandleA(NULL
), 0);
1879 todo_wine_if(is_version_6
)
1880 TEST_NO_HEADER2(hList
, is_version_6
);
1882 SetRect(&rect
, LVIR_BOUNDS
, 1, -10, -10);
1883 r
= SendMessageA(hList
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1884 ok(r
== 1, "Unexpected ret value %ld.\n", r
);
1885 /* right value contains garbage, probably because header columns are not set up */
1886 ok(rect
.bottom
>= 0, "Unexpected rectangle.\n");
1888 todo_wine_if(is_version_6
)
1889 TEST_NO_HEADER2(hList
, is_version_6
);
1890 DestroyWindow(hList
);
1892 /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1893 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1894 hList
= CreateWindowExA(0, WC_LISTVIEWA
, NULL
,
1895 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_OWNERDRAWFIXED
| LVS_REPORT
,
1896 0, 0, 100, 100, hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
1897 ok(hList
!= NULL
, "Failed to create ListView window.\n");
1898 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_ownerdrawfixed_parent_seq
,
1899 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE
);
1900 DestroyWindow(hList
);
1902 /* Test that window text is preserved. */
1903 hList
= CreateWindowExA(0, WC_LISTVIEWA
, "test text", WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
1904 0, 0, 100, 100, hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
1905 ok(hList
!= NULL
, "Failed to create ListView window.\n");
1907 GetWindowTextA(hList
, buff
, sizeof(buff
));
1908 ok(!strcmp(buff
, "test text"), "Unexpected window text %s.\n", buff
);
1909 DestroyWindow(hList
);
1911 hList
= CreateWindowExW(0, WC_LISTVIEWW
, L
"test text", WS_CHILD
| WS_BORDER
| WS_VISIBLE
,
1912 0, 0, 100, 100, hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
1913 ok(hList
!= NULL
, "Failed to create ListView window.\n");
1915 GetWindowTextA(hList
, buff
, sizeof(buff
));
1916 ok(!strcmp(buff
, "test text"), "Unexpected window text %s.\n", buff
);
1917 DestroyWindow(hList
);
1919 r
= UnregisterClassA("MyListView32", NULL
);
1920 ok(r
, "Failed to unregister test class.\n");
1923 static void test_redraw(void)
1931 hwnd
= create_listview_control(LVS_REPORT
);
1932 subclass_header(hwnd
);
1934 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1936 InvalidateRect(hwnd
, NULL
, TRUE
);
1938 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, redraw_listview_seq
, "redraw listview", FALSE
);
1940 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1942 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1943 /* 1. Without backbuffer */
1944 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
1947 hdc
= GetWindowDC(hwndparent
);
1949 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1950 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1951 ok(r
== 1, "Expected not zero result\n");
1952 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1953 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1955 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_DEFAULT
);
1958 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1959 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1961 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1962 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1964 /* 2. With backbuffer */
1965 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_DOUBLEBUFFER
,
1966 LVS_EX_DOUBLEBUFFER
);
1967 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
1970 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1971 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1973 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1974 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1976 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_DEFAULT
);
1979 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1980 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1981 todo_wine
expect(1, r
);
1982 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1983 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1985 ReleaseDC(hwndparent
, hdc
);
1987 /* test setting the window style to what it already was */
1989 SetWindowLongA(hwnd
, GWL_STYLE
, GetWindowLongA(hwnd
, GWL_STYLE
));
1990 GetUpdateRect(hwnd
, &rect
, FALSE
);
1991 ok(rect
.left
== 0 && rect
.top
== 0 && rect
.right
== 0 && rect
.bottom
== 0,
1992 "Expected empty update rect, got %s\n", wine_dbgstr_rect(&rect
));
1994 DestroyWindow(hwnd
);
1997 static LRESULT WINAPI
cd_wndproc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1999 COLORREF clr
, c0ffee
= RGB(0xc0, 0xff, 0xee);
2001 if(message
== WM_NOTIFY
) {
2002 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
2003 if(nmhdr
->code
== NM_CUSTOMDRAW
) {
2004 NMLVCUSTOMDRAW
*nmlvcd
= (NMLVCUSTOMDRAW
*)nmhdr
;
2005 BOOL showsel_always
= !!(GetWindowLongA(nmlvcd
->nmcd
.hdr
.hwndFrom
, GWL_STYLE
) & LVS_SHOWSELALWAYS
);
2006 BOOL is_selected
= !!(nmlvcd
->nmcd
.uItemState
& CDIS_SELECTED
);
2009 msg
.message
= message
;
2010 msg
.flags
= sent
|wparam
|lparam
|custdraw
;
2011 msg
.wParam
= wParam
;
2012 msg
.lParam
= lParam
;
2013 msg
.id
= nmhdr
->code
;
2014 msg
.stage
= nmlvcd
->nmcd
.dwDrawStage
;
2015 add_message(sequences
, PARENT_CD_SEQ_INDEX
, &msg
);
2017 switch(nmlvcd
->nmcd
.dwDrawStage
) {
2019 SetBkColor(nmlvcd
->nmcd
.hdc
, c0ffee
);
2020 return CDRF_NOTIFYITEMDRAW
|CDRF_NOTIFYPOSTPAINT
;
2021 case CDDS_ITEMPREPAINT
:
2022 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
2023 todo_wine_if(nmlvcd
->iSubItem
)
2024 ok(clr
== c0ffee
, "Unexpected background color %#lx.\n", clr
);
2025 nmlvcd
->clrTextBk
= CLR_DEFAULT
;
2026 nmlvcd
->clrText
= RGB(0, 255, 0);
2027 return CDRF_NOTIFYSUBITEMDRAW
|CDRF_NOTIFYPOSTPAINT
;
2028 case CDDS_ITEMPREPAINT
| CDDS_SUBITEM
:
2029 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
2030 ok(nmlvcd
->clrTextBk
== CLR_DEFAULT
, "Unexpected text background %#lx.\n", nmlvcd
->clrTextBk
);
2031 ok(nmlvcd
->clrText
== RGB(0, 255, 0), "Unexpected text color %#lx.\n", nmlvcd
->clrText
);
2032 if (showsel_always
&& is_selected
&& nmlvcd
->iSubItem
)
2033 ok(clr
== GetSysColor(COLOR_3DFACE
), "Unexpected background color %#lx.\n", clr
);
2035 todo_wine_if(nmlvcd
->iSubItem
)
2036 ok(clr
== c0ffee
, "clr=%.8lx\n", clr
);
2037 return CDRF_NOTIFYPOSTPAINT
;
2038 case CDDS_ITEMPOSTPAINT
| CDDS_SUBITEM
:
2039 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
2040 if (showsel_always
&& is_selected
)
2041 ok(clr
== GetSysColor(COLOR_3DFACE
), "Unexpected background color %#lx.\n", clr
);
2045 ok(clr
== c0ffee
, "Unexpected background color %#lx.\n", clr
);
2048 ok(nmlvcd
->clrTextBk
== CLR_DEFAULT
, "Unexpected text background color %#lx.\n", nmlvcd
->clrTextBk
);
2049 ok(nmlvcd
->clrText
== RGB(0, 255, 0), "got 0x%lx\n", nmlvcd
->clrText
);
2050 return CDRF_DODEFAULT
;
2052 return CDRF_DODEFAULT
;
2056 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2059 static void test_customdraw(void)
2065 hwnd
= create_listview_control(LVS_REPORT
);
2067 insert_column(hwnd
, 0);
2068 insert_column(hwnd
, 1);
2069 insert_item(hwnd
, 0);
2071 oldwndproc
= (WNDPROC
)SetWindowLongPtrA(hwndparent
, GWLP_WNDPROC
,
2072 (LONG_PTR
)cd_wndproc
);
2074 InvalidateRect(hwnd
, NULL
, TRUE
);
2078 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2079 InvalidateRect(hwnd
, NULL
, TRUE
);
2081 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_report_cd_seq
, "parent customdraw, LVS_REPORT", FALSE
);
2083 /* Check colors when item is selected. */
2084 item
.mask
= LVIF_STATE
;
2085 item
.stateMask
= LVIS_SELECTED
;
2086 item
.state
= LVIS_SELECTED
;
2087 SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2089 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2090 InvalidateRect(hwnd
, NULL
, TRUE
);
2092 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_report_cd_seq
,
2093 "parent customdraw, item selected, LVS_REPORT, selection", FALSE
);
2095 SetWindowLongW(hwnd
, GWL_STYLE
, GetWindowLongW(hwnd
, GWL_STYLE
) | LVS_SHOWSELALWAYS
);
2096 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2097 InvalidateRect(hwnd
, NULL
, TRUE
);
2099 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_report_cd_seq
,
2100 "parent customdraw, item selected, LVS_SHOWSELALWAYS, LVS_REPORT", FALSE
);
2102 DestroyWindow(hwnd
);
2104 hwnd
= create_listview_control(LVS_LIST
);
2106 insert_column(hwnd
, 0);
2107 insert_column(hwnd
, 1);
2108 insert_item(hwnd
, 0);
2110 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2111 InvalidateRect(hwnd
, NULL
, TRUE
);
2113 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_list_cd_seq
, "parent customdraw, LVS_LIST", FALSE
);
2115 SetWindowLongPtrA(hwndparent
, GWLP_WNDPROC
, (LONG_PTR
)oldwndproc
);
2116 DestroyWindow(hwnd
);
2119 static void test_icon_spacing(void)
2121 /* LVM_SETICONSPACING */
2122 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
2128 hwnd
= create_listview_control(LVS_ICON
);
2129 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2131 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, (WPARAM
)hwndparent
, NF_REQUERY
);
2132 expect(NFR_ANSI
, r
);
2134 /* reset the icon spacing to defaults */
2135 SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
2137 /* now we can request what the defaults are */
2138 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
2142 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2144 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(20, 30));
2145 ok(r
== MAKELONG(w
, h
) ||
2146 broken(r
== MAKELONG(w
, w
)), /* win98 */
2147 "Expected %ld, got %d\n", MAKELONG(w
, h
), r
);
2149 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(25, 35));
2150 expect(MAKELONG(20,30), r
);
2152 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1,-1));
2153 expect(MAKELONG(25,35), r
);
2155 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_icon_spacing_seq
, "test icon spacing seq", FALSE
);
2157 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2158 DestroyWindow(hwnd
);
2161 static void test_color(void)
2169 COLORREF colors
[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE
, RGB(255,255,255)};
2171 hwnd
= create_listview_control(LVS_REPORT
);
2172 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2174 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2176 for (i
= 0; i
< 4; i
++)
2180 r
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, color
);
2182 r
= SendMessageA(hwnd
, LVM_GETBKCOLOR
, 0, 0);
2185 r
= SendMessageA(hwnd
, LVM_SETTEXTCOLOR
, 0, color
);
2187 r
= SendMessageA(hwnd
, LVM_GETTEXTCOLOR
, 0, 0);
2190 r
= SendMessageA(hwnd
, LVM_SETTEXTBKCOLOR
, 0, color
);
2192 r
= SendMessageA(hwnd
, LVM_GETTEXTBKCOLOR
, 0, 0);
2196 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_color_seq
, "test color seq", FALSE
);
2197 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2199 /* invalidation test done separately to avoid a message chain mess */
2200 r
= ValidateRect(hwnd
, NULL
);
2202 r
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, colors
[0]);
2205 rect
.right
= rect
.bottom
= 1;
2206 r
= GetUpdateRect(hwnd
, &rect
, TRUE
);
2208 ok(rect
.right
== 0 && rect
.bottom
== 0, "got update rectangle %s\n", wine_dbgstr_rect(&rect
));
2210 r
= ValidateRect(hwnd
, NULL
);
2212 r
= SendMessageA(hwnd
, LVM_SETTEXTCOLOR
, 0, colors
[0]);
2215 rect
.right
= rect
.bottom
= 1;
2216 r
= GetUpdateRect(hwnd
, &rect
, TRUE
);
2218 ok(rect
.right
== 0 && rect
.bottom
== 0, "got update rectangle %s\n", wine_dbgstr_rect(&rect
));
2220 r
= ValidateRect(hwnd
, NULL
);
2222 r
= SendMessageA(hwnd
, LVM_SETTEXTBKCOLOR
, 0, colors
[0]);
2225 rect
.right
= rect
.bottom
= 1;
2226 r
= GetUpdateRect(hwnd
, &rect
, TRUE
);
2228 ok(rect
.right
== 0 && rect
.bottom
== 0, "got update rectangle %s\n", wine_dbgstr_rect(&rect
));
2230 DestroyWindow(hwnd
);
2233 static void test_item_count(void)
2235 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
2248 static CHAR item0text
[] = "item0";
2249 static CHAR item1text
[] = "item1";
2250 static CHAR item2text
[] = "item2";
2252 hwnd
= create_listview_control(LVS_REPORT
);
2253 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2255 /* resize in dpiaware manner to fit all 3 items added */
2257 hOldFont
= SelectObject(hdc
, GetStockObject(SYSTEM_FONT
));
2258 GetTextMetricsA(hdc
, &tm
);
2259 /* 2 extra pixels for bounds and header border */
2260 height
= tm
.tmHeight
+ 2;
2261 SelectObject(hdc
, hOldFont
);
2264 GetWindowRect(hwnd
, &rect
);
2265 /* 3 items + 1 header + 1 to be sure */
2266 MoveWindow(hwnd
, 0, 0, rect
.right
- rect
.left
, 5 * height
, FALSE
);
2268 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2270 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2274 item0
.mask
= LVIF_TEXT
;
2277 item0
.pszText
= item0text
;
2278 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item0
);
2281 /* [item0, item1] */
2282 item1
.mask
= LVIF_TEXT
;
2285 item1
.pszText
= item1text
;
2286 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2289 /* [item0, item1, item2] */
2290 item2
.mask
= LVIF_TEXT
;
2293 item2
.pszText
= item2text
;
2294 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item2
);
2297 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2300 /* [item0, item1] */
2301 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 2, 0);
2304 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2308 r
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
2311 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2315 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2318 /* [item0, item1] */
2319 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2322 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2325 /* [item0, item1, item2] */
2326 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item2
);
2329 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2332 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_item_count_seq
, "test item count seq", FALSE
);
2334 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2335 DestroyWindow(hwnd
);
2338 static void test_item_position(void)
2340 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
2349 static CHAR item0text
[] = "item0";
2350 static CHAR item1text
[] = "item1";
2351 static CHAR item2text
[] = "item2";
2353 hwnd
= create_listview_control(LVS_ICON
);
2354 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2356 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2359 item0
.mask
= LVIF_TEXT
;
2362 item0
.pszText
= item0text
;
2363 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item0
);
2366 /* [item0, item1] */
2367 item1
.mask
= LVIF_TEXT
;
2370 item1
.pszText
= item1text
;
2371 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2374 /* [item0, item1, item2] */
2375 item2
.mask
= LVIF_TEXT
;
2378 item2
.pszText
= item2text
;
2379 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item2
);
2382 r
= SendMessageA(hwnd
, LVM_SETITEMPOSITION
, 1, MAKELPARAM(10,5));
2384 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 1, (LPARAM
) &position
);
2386 expect2(10, 5, position
.x
, position
.y
);
2388 r
= SendMessageA(hwnd
, LVM_SETITEMPOSITION
, 2, MAKELPARAM(0,0));
2390 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 2, (LPARAM
) &position
);
2392 expect2(0, 0, position
.x
, position
.y
);
2394 r
= SendMessageA(hwnd
, LVM_SETITEMPOSITION
, 0, MAKELPARAM(20,20));
2396 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
) &position
);
2398 expect2(20, 20, position
.x
, position
.y
);
2400 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_itempos_seq
, "test item position seq", TRUE
);
2402 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2403 DestroyWindow(hwnd
);
2406 static void test_getorigin(void)
2414 position
.x
= position
.y
= 0;
2416 hwnd
= create_listview_control(LVS_ICON
);
2417 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2418 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2420 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2422 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2423 DestroyWindow(hwnd
);
2425 hwnd
= create_listview_control(LVS_SMALLICON
);
2426 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2427 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2429 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2431 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2432 DestroyWindow(hwnd
);
2434 hwnd
= create_listview_control(LVS_LIST
);
2435 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2436 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2438 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2440 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2441 DestroyWindow(hwnd
);
2443 hwnd
= create_listview_control(LVS_REPORT
);
2444 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2445 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2447 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2449 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2450 DestroyWindow(hwnd
);
2453 static void test_multiselect(void)
2455 typedef struct t_select_task
2467 static const int items
=5;
2473 static struct t_select_task task_list
[] = {
2474 { "using VK_DOWN", 0, VK_DOWN
, -1, -1 },
2475 { "using VK_UP", -1, VK_UP
, -1, -1 },
2476 { "using VK_END", 0, VK_END
, 1, -1 },
2477 { "using VK_HOME", -1, VK_HOME
, 1, -1 }
2480 hwnd
= create_listview_control(LVS_REPORT
);
2482 for (i
= 0; i
< items
; i
++)
2483 insert_item(hwnd
, 0);
2485 item_count
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2486 expect(items
, item_count
);
2488 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2489 ok(r
== -1, "got %d\n", r
);
2491 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, 0);
2492 ok(r
== -1, "got %d\n", r
);
2494 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, 0);
2495 ok(r
== 0, "got %d\n", r
);
2497 /* out of range index */
2498 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, items
);
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 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -2);
2505 ok(r
== 0, "got %d\n", r
);
2507 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2508 ok(r
== 0, "got %d\n", r
);
2510 for (i
= 0; i
< ARRAY_SIZE(task_list
); i
++) {
2511 DWORD selected_count
;
2514 task
= task_list
[i
];
2516 /* deselect all items */
2518 item
.stateMask
= LVIS_SELECTED
;
2519 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2520 ok(r
, "got %d\n", r
);
2521 SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2523 /* set initial position */
2524 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, (task
.initPos
== -1 ? item_count
-1 : task
.initPos
));
2525 ok(r
, "got %d\n", r
);
2527 item
.state
= LVIS_SELECTED
;
2528 item
.stateMask
= LVIS_SELECTED
;
2529 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, task
.initPos
== -1 ? item_count
-1 : task
.initPos
, (LPARAM
)&item
);
2530 ok(r
, "got %d\n", r
);
2532 selected_count
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2533 ok(selected_count
== 1, "expected 1, got %ld\n", selected_count
);
2537 for (j
=1;j
<=(task
.count
== -1 ? item_count
: task
.count
);j
++) {
2538 r
= SendMessageA(hwnd
, WM_KEYDOWN
, task
.loopVK
, 0);
2540 r
= SendMessageA(hwnd
, WM_KEYUP
, task
.loopVK
, 0);
2544 selected_count
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2546 ok((task
.result
== -1 ? item_count
: task
.result
) == selected_count
,
2547 "Failed multiple selection %s. There should be %ld selected items (is %ld)\n",
2548 task
.descr
, item_count
, selected_count
);
2550 release_key(VK_SHIFT
);
2552 DestroyWindow(hwnd
);
2554 /* make multiple selection, then switch to LVS_SINGLESEL */
2555 hwnd
= create_listview_control(LVS_REPORT
);
2556 for (i
=0;i
<items
;i
++) {
2557 insert_item(hwnd
, 0);
2559 item_count
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2560 expect(items
,item_count
);
2562 /* try with NULL pointer */
2563 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, 0);
2566 /* select all, check notifications */
2568 item
.stateMask
= LVIS_SELECTED
;
2569 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2570 ok(r
, "got %d\n", r
);
2572 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2574 item
.stateMask
= LVIS_SELECTED
;
2575 item
.state
= LVIS_SELECTED
;
2576 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2579 ok_sequence(sequences
, PARENT_SEQ_INDEX
, change_all_parent_seq
,
2580 "select all notification", FALSE
);
2582 /* select all again (all selected already) */
2583 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2585 memset(&g_nmlistview_changing
, 0xcc, sizeof(g_nmlistview_changing
));
2587 item
.stateMask
= LVIS_SELECTED
;
2588 item
.state
= LVIS_SELECTED
;
2589 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2592 ok(g_nmlistview_changing
.uNewState
== LVIS_SELECTED
, "got 0x%x\n", g_nmlistview_changing
.uNewState
);
2593 ok(g_nmlistview_changing
.uOldState
== LVIS_SELECTED
, "got 0x%x\n", g_nmlistview_changing
.uOldState
);
2594 ok(g_nmlistview_changing
.uChanged
== LVIF_STATE
, "got 0x%x\n", g_nmlistview_changing
.uChanged
);
2596 ok_sequence(sequences
, PARENT_SEQ_INDEX
, changing_all_parent_seq
,
2597 "select all notification 2", FALSE
);
2599 /* deselect all items */
2600 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2603 item
.stateMask
= LVIS_SELECTED
;
2604 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2605 ok(r
, "got %d\n", r
);
2607 ok_sequence(sequences
, PARENT_SEQ_INDEX
, change_all_parent_seq
,
2608 "deselect all notification", FALSE
);
2610 /* deselect all items again */
2611 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2613 item
.stateMask
= LVIS_SELECTED
;
2614 SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2615 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "deselect all notification 2", FALSE
);
2617 /* any non-zero state value does the same */
2618 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2620 memset(&g_nmlistview_changing
, 0xcc, sizeof(g_nmlistview_changing
));
2622 item
.stateMask
= LVIS_SELECTED
;
2623 item
.state
= LVIS_CUT
;
2624 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2627 ok(g_nmlistview_changing
.uNewState
== 0, "got 0x%x\n", g_nmlistview_changing
.uNewState
);
2628 ok(g_nmlistview_changing
.uOldState
== 0, "got 0x%x\n", g_nmlistview_changing
.uOldState
);
2629 ok(g_nmlistview_changing
.uChanged
== LVIF_STATE
, "got 0x%x\n", g_nmlistview_changing
.uChanged
);
2631 ok_sequence(sequences
, PARENT_SEQ_INDEX
, changing_all_parent_seq
,
2632 "set state all notification 3", FALSE
);
2634 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2635 ok(r
, "got %d\n", r
);
2636 for (i
= 0; i
< 3; i
++) {
2637 item
.state
= LVIS_SELECTED
;
2638 item
.stateMask
= LVIS_SELECTED
;
2639 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
2640 ok(r
, "got %d\n", r
);
2643 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2645 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2648 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2649 ok(!(style
& LVS_SINGLESEL
), "LVS_SINGLESEL isn't expected\n");
2650 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SINGLESEL
);
2651 /* check that style is accepted */
2652 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2653 ok(style
& LVS_SINGLESEL
, "LVS_SINGLESEL expected\n");
2656 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, i
, LVIS_SELECTED
);
2657 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
2659 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2661 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2662 ok(r
== -1, "got %d\n", r
);
2664 /* select one more */
2665 item
.state
= LVIS_SELECTED
;
2666 item
.stateMask
= LVIS_SELECTED
;
2667 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 3, (LPARAM
)&item
);
2668 ok(r
, "got %d\n", r
);
2671 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, i
, LVIS_SELECTED
);
2672 ok(!(r
& LVIS_SELECTED
), "Expected item %d to be unselected\n", i
);
2675 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 3, LVIS_SELECTED
);
2676 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
2678 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2680 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2683 /* try to select all on LVS_SINGLESEL */
2684 memset(&item
, 0, sizeof(item
));
2685 item
.stateMask
= LVIS_SELECTED
;
2686 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2688 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2689 ok(r
== -1, "got %d\n", r
);
2691 item
.stateMask
= LVIS_SELECTED
;
2692 item
.state
= LVIS_SELECTED
;
2693 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2696 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2698 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2701 /* try to deselect all on LVS_SINGLESEL */
2702 item
.stateMask
= LVIS_SELECTED
;
2703 item
.state
= LVIS_SELECTED
;
2704 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2707 item
.stateMask
= LVIS_SELECTED
;
2709 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2711 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2714 /* 1. selection mark is update when new focused item is set */
2715 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2716 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SINGLESEL
);
2718 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2721 item
.stateMask
= LVIS_FOCUSED
;
2722 item
.state
= LVIS_FOCUSED
;
2723 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2726 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2729 /* it's not updated if already set */
2730 item
.stateMask
= LVIS_FOCUSED
;
2731 item
.state
= LVIS_FOCUSED
;
2732 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 1, (LPARAM
)&item
);
2735 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2738 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2741 item
.stateMask
= LVIS_FOCUSED
;
2742 item
.state
= LVIS_FOCUSED
;
2743 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 1, (LPARAM
)&item
);
2746 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2749 /* need to reset focused item first */
2750 item
.stateMask
= LVIS_FOCUSED
;
2752 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2755 item
.stateMask
= LVIS_FOCUSED
;
2756 item
.state
= LVIS_FOCUSED
;
2757 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 2, (LPARAM
)&item
);
2760 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2763 item
.stateMask
= LVIS_FOCUSED
;
2765 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2768 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2771 /* 2. same tests, with LVM_SETITEM */
2772 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2773 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SINGLESEL
);
2775 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2778 item
.stateMask
= LVIS_FOCUSED
;
2779 item
.state
= LVIS_FOCUSED
;
2780 item
.mask
= LVIF_STATE
;
2781 item
.iItem
= item
.iSubItem
= 0;
2782 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2785 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2788 /* it's not updated if already set */
2789 item
.stateMask
= LVIS_FOCUSED
;
2790 item
.state
= LVIS_FOCUSED
;
2791 item
.mask
= LVIF_STATE
;
2794 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2797 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2800 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2803 item
.stateMask
= LVIS_FOCUSED
;
2804 item
.state
= LVIS_FOCUSED
;
2805 item
.mask
= LVIF_STATE
;
2808 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2811 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2814 /* need to reset focused item first */
2815 item
.stateMask
= LVIS_FOCUSED
;
2817 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2820 item
.stateMask
= LVIS_FOCUSED
;
2821 item
.state
= LVIS_FOCUSED
;
2822 item
.mask
= LVIF_STATE
;
2825 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2828 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2831 item
.stateMask
= LVIS_FOCUSED
;
2833 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2836 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2839 DestroyWindow(hwnd
);
2842 static void test_subitem_rect(void)
2850 /* test LVM_GETSUBITEMRECT for header */
2851 hwnd
= create_listview_control(LVS_REPORT
);
2852 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2853 /* add some columns */
2854 memset(&col
, 0, sizeof(LVCOLUMNA
));
2855 col
.mask
= LVCF_WIDTH
;
2857 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
2860 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 1, (LPARAM
)&col
);
2863 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 2, (LPARAM
)&col
);
2865 /* item = -1 means header, subitem index is 1 based */
2866 SetRect(&rect
, LVIR_BOUNDS
, 0, 0, 0);
2867 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2870 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2871 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2874 expect(100, rect
.left
);
2875 expect(250, rect
.right
);
2876 expect(3, rect
.top
);
2878 SetRect(&rect
, LVIR_BOUNDS
, 2, 0, 0);
2879 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2882 expect(250, rect
.left
);
2883 expect(450, rect
.right
);
2884 expect(3, rect
.top
);
2886 /* item LVS_REPORT padding isn't applied to subitems */
2887 insert_item(hwnd
, 0);
2889 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2890 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2892 expect(100, rect
.left
);
2893 expect(250, rect
.right
);
2895 SetRect(&rect
, LVIR_ICON
, 1, 0, 0);
2896 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2898 /* no icon attached - zero width rectangle, with no left padding */
2899 expect(100, rect
.left
);
2900 expect(100, rect
.right
);
2902 SetRect(&rect
, LVIR_LABEL
, 1, 0, 0);
2903 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2905 /* same as full LVIR_BOUNDS */
2906 expect(100, rect
.left
);
2907 expect(250, rect
.right
);
2909 r
= SendMessageA(hwnd
, LVM_SCROLL
, 10, 0);
2910 ok(r
, "got %ld\n", r
);
2912 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2913 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2915 expect(90, rect
.left
);
2916 expect(240, rect
.right
);
2918 SendMessageA(hwnd
, LVM_SCROLL
, -10, 0);
2920 /* test header interaction */
2921 subclass_header(hwnd
);
2922 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2924 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2925 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2928 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2929 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2932 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2933 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -10, (LPARAM
)&rect
);
2936 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2937 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 20, (LPARAM
)&rect
);
2940 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getsubitemrect_seq
, "LVM_GETSUBITEMRECT negative index", FALSE
);
2942 DestroyWindow(hwnd
);
2944 /* test subitem rects after re-arranging columns */
2945 hwnd
= create_listview_control(LVS_REPORT
);
2946 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2947 memset(&col
, 0, sizeof(LVCOLUMNA
));
2948 col
.mask
= LVCF_WIDTH
;
2951 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
2955 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 1, (LPARAM
)&col
);
2959 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 2, (LPARAM
)&col
);
2962 insert_item(hwnd
, 0);
2963 insert_item(hwnd
, 1);
2965 /* wrong item is refused for main item */
2966 SetRect(&rect
, LVIR_BOUNDS
, 0, -1, -1);
2967 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 2, (LPARAM
)&rect
);
2970 /* for subitems rectangle is calculated even if there's no item added */
2971 SetRect(&rect
, LVIR_BOUNDS
, 1, -1, -1);
2972 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 1, (LPARAM
)&rect
);
2975 SetRect(&rect2
, LVIR_BOUNDS
, 1, -1, -1);
2976 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 2, (LPARAM
)&rect2
);
2978 expect(rect
.right
, rect2
.right
);
2979 expect(rect
.left
, rect2
.left
);
2980 expect(rect
.bottom
, rect2
.top
);
2981 ok(rect2
.bottom
> rect2
.top
, "expected not zero height\n");
2983 arr
[0] = 1; arr
[1] = 0; arr
[2] = 2;
2984 r
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 3, (LPARAM
)arr
);
2987 SetRect(&rect
, LVIR_BOUNDS
, 0, -1, -1);
2988 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2990 expect(0, rect
.left
);
2991 expect(600, rect
.right
);
2993 SetRect(&rect
, LVIR_BOUNDS
, 1, -1, -1);
2994 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2996 expect(0, rect
.left
);
2997 expect(200, rect
.right
);
2999 SetRect(&rect2
, LVIR_BOUNDS
, 1, -1, -1);
3000 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 1, (LPARAM
)&rect2
);
3002 expect(0, rect2
.left
);
3003 expect(200, rect2
.right
);
3004 /* items are of the same height */
3005 ok(rect2
.top
> 0, "expected positive item height\n");
3006 expect(rect
.bottom
, rect2
.top
);
3007 expect(rect
.bottom
* 2 - rect
.top
, rect2
.bottom
);
3009 SetRect(&rect
, LVIR_BOUNDS
, 2, -1, -1);
3010 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
3012 expect(300, rect
.left
);
3013 expect(600, rect
.right
);
3015 DestroyWindow(hwnd
);
3017 /* try it for non LVS_REPORT style */
3018 hwnd
= CreateWindowA(WC_LISTVIEWA
, "Test", LVS_ICON
, 0, 0, 100, 100, NULL
, NULL
,
3019 GetModuleHandleA(NULL
), 0);
3020 SetRect(&rect
, LVIR_BOUNDS
, 1, -10, -10);
3021 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
3023 /* rect is unchanged */
3024 expect(0, rect
.left
);
3025 expect(-10, rect
.right
);
3026 expect(1, rect
.top
);
3027 expect(-10, rect
.bottom
);
3028 DestroyWindow(hwnd
);
3031 /* comparison callback for test_sorting */
3032 static INT WINAPI
test_CallBackCompare(LPARAM first
, LPARAM second
, LPARAM lParam
)
3034 if (first
== second
) return 0;
3035 return (first
> second
? 1 : -1);
3038 static void test_sorting(void)
3044 static CHAR names
[][5] = {"A", "B", "C", "D", "0"};
3047 hwnd
= create_listview_control(LVS_REPORT
);
3048 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3050 /* insert some items */
3051 item
.mask
= LVIF_PARAM
| LVIF_STATE
;
3052 item
.state
= LVIS_SELECTED
;
3056 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3059 item
.mask
= LVIF_PARAM
;
3063 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3066 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
3067 item
.state
= LVIS_SELECTED
;
3071 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3074 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
3077 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3080 r
= SendMessageA(hwnd
, LVM_SORTITEMS
, 0, (LPARAM
)test_CallBackCompare
);
3083 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3085 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
3087 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_SELECTED
);
3089 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_SELECTED
);
3090 expect(LVIS_SELECTED
, r
);
3091 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_SELECTED
);
3092 expect(LVIS_SELECTED
, r
);
3094 DestroyWindow(hwnd
);
3096 /* switch to LVS_SORTASCENDING when some items added */
3097 hwnd
= create_listview_control(LVS_REPORT
);
3098 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3100 item
.mask
= LVIF_TEXT
;
3103 item
.pszText
= names
[1];
3104 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3107 item
.mask
= LVIF_TEXT
;
3110 item
.pszText
= names
[2];
3111 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3114 item
.mask
= LVIF_TEXT
;
3117 item
.pszText
= names
[0];
3118 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3121 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3122 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
3123 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3124 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
3126 /* no sorting performed when switched to LVS_SORTASCENDING */
3127 item
.mask
= LVIF_TEXT
;
3129 item
.pszText
= buff
;
3130 item
.cchTextMax
= sizeof(buff
);
3131 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3133 ok(lstrcmpA(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
3136 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3138 ok(lstrcmpA(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
3141 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3143 ok(lstrcmpA(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
3145 /* adding new item doesn't resort list */
3146 item
.mask
= LVIF_TEXT
;
3149 item
.pszText
= names
[3];
3150 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3153 item
.mask
= LVIF_TEXT
;
3155 item
.pszText
= buff
;
3156 item
.cchTextMax
= sizeof(buff
);
3157 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3159 ok(lstrcmpA(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
3162 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3164 ok(lstrcmpA(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
3167 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3169 ok(lstrcmpA(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
3172 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3174 ok(lstrcmpA(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
3176 /* corner case - item should be placed at first position */
3177 item
.mask
= LVIF_TEXT
;
3180 item
.pszText
= names
[4];
3181 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
3185 item
.pszText
= buff
;
3186 item
.cchTextMax
= sizeof(buff
);
3187 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3189 ok(lstrcmpA(buff
, names
[4]) == 0, "Expected '%s', got '%s'\n", names
[4], buff
);
3192 item
.pszText
= buff
;
3193 item
.cchTextMax
= sizeof(buff
);
3194 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3196 ok(lstrcmpA(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
3199 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3201 ok(lstrcmpA(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
3204 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3206 ok(lstrcmpA(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
3209 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
3211 ok(lstrcmpA(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
3213 DestroyWindow(hwnd
);
3216 static void test_ownerdata(void)
3218 static char test_str
[] = "test";
3221 LONG_PTR style
, ret
;
3225 /* Setting LVS_OWNERDATA after creation leads to crash on older versions < 5.80 */
3226 hwnd
= create_listview_control(LVS_REPORT
);
3227 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3228 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3229 ok(!(style
& LVS_OWNERDATA
) && style
, "LVS_OWNERDATA isn't expected\n");
3231 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3233 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
3234 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
3235 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
3236 "try to switch to LVS_OWNERDATA seq", FALSE
);
3238 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3239 ok(!(style
& LVS_OWNERDATA
), "LVS_OWNERDATA isn't expected\n");
3240 DestroyWindow(hwnd
);
3242 /* try to set LVS_OWNERDATA after creation just having it */
3243 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3244 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3245 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3246 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
3248 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3250 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
3251 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
3252 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
3253 "try to switch to LVS_OWNERDATA seq", FALSE
);
3254 DestroyWindow(hwnd
);
3256 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3257 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3258 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3259 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
3261 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3263 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_OWNERDATA
);
3264 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
3265 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
3266 "try to switch to LVS_OWNERDATA seq", FALSE
);
3267 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3268 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
3269 DestroyWindow(hwnd
);
3271 /* try select an item */
3272 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3273 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3274 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3276 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3278 memset(&item
, 0, sizeof(item
));
3279 item
.stateMask
= LVIS_SELECTED
;
3280 item
.state
= LVIS_SELECTED
;
3281 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3283 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3285 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
3287 DestroyWindow(hwnd
);
3289 /* LVM_SETITEM and LVM_SETITEMTEXT is unsupported on LVS_OWNERDATA */
3290 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3291 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3292 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3294 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
3296 memset(&item
, 0, sizeof(item
));
3297 item
.mask
= LVIF_STATE
;
3299 item
.stateMask
= LVIS_SELECTED
;
3300 item
.state
= LVIS_SELECTED
;
3301 res
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
3303 memset(&item
, 0, sizeof(item
));
3304 item
.pszText
= test_str
;
3305 res
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
3307 DestroyWindow(hwnd
);
3309 /* check notifications after focused/selected changed */
3310 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3311 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3312 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 20, 0);
3315 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3317 memset(&item
, 0, sizeof(item
));
3318 item
.stateMask
= LVIS_SELECTED
;
3319 item
.state
= LVIS_SELECTED
;
3320 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3323 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_select_focus_parent_seq
,
3324 "ownerdata select notification", TRUE
);
3326 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3328 memset(&item
, 0, sizeof(item
));
3329 item
.stateMask
= LVIS_FOCUSED
;
3330 item
.state
= LVIS_FOCUSED
;
3331 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3334 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_select_focus_parent_seq
,
3335 "ownerdata focus notification", TRUE
);
3337 /* select all, check notifications */
3338 item
.stateMask
= LVIS_SELECTED
;
3340 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3343 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3345 item
.stateMask
= LVIS_SELECTED
;
3346 item
.state
= LVIS_SELECTED
;
3348 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3349 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3351 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3352 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3353 ok(g_nmlistview
.uNewState
== LVIS_SELECTED
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3354 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3355 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3356 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3357 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3359 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3360 "ownerdata select all notification", FALSE
);
3362 /* select all again, note that all items are selected already */
3363 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3364 item
.stateMask
= LVIS_SELECTED
;
3365 item
.state
= LVIS_SELECTED
;
3367 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3368 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3370 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3371 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3372 ok(g_nmlistview
.uNewState
== LVIS_SELECTED
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3373 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3374 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3375 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3376 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3378 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3379 "ownerdata select all notification", FALSE
);
3382 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3383 item
.stateMask
= LVIS_SELECTED
;
3386 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3387 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3389 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3390 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3391 ok(g_nmlistview
.uNewState
== 0, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3392 ok(g_nmlistview
.uOldState
== LVIS_SELECTED
, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3393 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3394 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3395 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3397 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_deselect_all_parent_seq
,
3398 "ownerdata deselect all notification", TRUE
);
3400 /* nothing selected, deselect all again */
3401 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3402 item
.stateMask
= LVIS_SELECTED
;
3405 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3408 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "ownerdata deselect all notification", FALSE
);
3410 /* select one, then deselect all */
3411 item
.stateMask
= LVIS_SELECTED
;
3412 item
.state
= LVIS_SELECTED
;
3413 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3415 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3416 item
.stateMask
= LVIS_SELECTED
;
3419 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3420 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3422 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3423 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3424 ok(g_nmlistview
.uNewState
== 0, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3425 ok(g_nmlistview
.uOldState
== LVIS_SELECTED
, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3426 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3427 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3428 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3430 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_deselect_all_parent_seq
,
3431 "ownerdata select all notification", TRUE
);
3433 /* remove focused, try to focus all */
3434 item
.stateMask
= LVIS_FOCUSED
;
3435 item
.state
= LVIS_FOCUSED
;
3436 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3438 item
.stateMask
= LVIS_FOCUSED
;
3440 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3442 item
.stateMask
= LVIS_FOCUSED
;
3443 res
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_FOCUSED
);
3446 /* setting all to focused returns failure value */
3447 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3448 item
.stateMask
= LVIS_FOCUSED
;
3449 item
.state
= LVIS_FOCUSED
;
3451 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3454 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3455 "ownerdata focus all notification", FALSE
);
3457 /* focus single item, remove all */
3458 item
.stateMask
= LVIS_FOCUSED
;
3459 item
.state
= LVIS_FOCUSED
;
3460 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3462 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3463 item
.stateMask
= LVIS_FOCUSED
;
3466 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3467 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3469 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3470 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3471 ok(g_nmlistview
.uNewState
== 0, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3472 ok(g_nmlistview
.uOldState
== LVIS_FOCUSED
, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3473 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3474 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3475 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3477 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_defocus_all_parent_seq
,
3478 "ownerdata remove focus all notification", TRUE
);
3481 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3482 item
.stateMask
= LVIS_CUT
;
3483 item
.state
= LVIS_CUT
;
3485 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3486 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3488 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3489 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3490 ok(g_nmlistview
.uNewState
== LVIS_CUT
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3491 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3492 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3493 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3494 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3496 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3497 "ownerdata cut all notification", FALSE
);
3499 /* all marked cut, try again */
3500 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3501 item
.stateMask
= LVIS_CUT
;
3502 item
.state
= LVIS_CUT
;
3504 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3505 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3507 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3508 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3509 ok(g_nmlistview
.uNewState
== LVIS_CUT
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3510 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3511 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3512 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3513 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3515 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3516 "ownerdata cut all notification #2", FALSE
);
3518 DestroyWindow(hwnd
);
3520 /* check notifications on LVM_GETITEM */
3521 /* zero callback mask */
3522 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3523 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3524 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3527 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3529 memset(&item
, 0, sizeof(item
));
3530 item
.stateMask
= LVIS_SELECTED
;
3531 item
.mask
= LVIF_STATE
;
3532 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3535 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3536 "ownerdata getitem selected state 1", FALSE
);
3538 /* non zero callback mask but not we asking for */
3539 res
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_OVERLAYMASK
, 0);
3542 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3544 memset(&item
, 0, sizeof(item
));
3545 item
.stateMask
= LVIS_SELECTED
;
3546 item
.mask
= LVIF_STATE
;
3547 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3550 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3551 "ownerdata getitem selected state 2", FALSE
);
3553 /* LVIS_OVERLAYMASK callback mask, asking for index */
3554 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3556 memset(&item
, 0, sizeof(item
));
3557 item
.stateMask
= LVIS_OVERLAYMASK
;
3558 item
.mask
= LVIF_STATE
;
3559 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3562 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
3563 "ownerdata getitem selected state 2", FALSE
);
3565 DestroyWindow(hwnd
);
3567 /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
3568 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_SORTASCENDING
| LVS_REPORT
);
3569 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3570 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3571 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
3572 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
3573 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SORTASCENDING
);
3574 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3575 ok(!(style
& LVS_SORTASCENDING
), "Expected LVS_SORTASCENDING not set\n");
3576 DestroyWindow(hwnd
);
3577 /* apparently it's allowed to switch these style on after creation */
3578 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3579 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3580 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3581 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
3582 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
3583 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3584 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
3585 DestroyWindow(hwnd
);
3587 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3588 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3589 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3590 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
3591 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTDESCENDING
);
3592 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3593 ok(style
& LVS_SORTDESCENDING
, "Expected LVS_SORTDESCENDING to be set\n");
3594 DestroyWindow(hwnd
);
3596 /* The focused item is updated after the invalidation */
3597 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3598 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3599 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 3, 0);
3602 memset(&item
, 0, sizeof(item
));
3603 item
.stateMask
= LVIS_FOCUSED
;
3604 item
.state
= LVIS_FOCUSED
;
3605 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3608 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3609 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 0, 0);
3611 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3612 "ownerdata setitemcount", FALSE
);
3614 res
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
3616 DestroyWindow(hwnd
);
3619 static void test_ownerdata_multiselect(void)
3632 UINT selected_count
;
3633 const char *context
;
3634 const struct message
*expected
;
3639 /* First down then up */
3640 { TRUE
, FALSE
, VK_DOWN
, 2, "select multiple via SHIFT+DOWN",
3641 ownerdata_multiselect_select_0_to_1_odstatechanged_seq
, FALSE
},
3642 { TRUE
, FALSE
, VK_UP
, 1, "select one item via SHIFT+UP",
3643 ownerdata_multiselect_select_0_modkey_odstatechanged_seq
, TRUE
},
3644 { TRUE
, TRUE
, VK_DOWN
, 2, "select multiple via SHIFT+CONTROL+DOWN",
3645 ownerdata_multiselect_select_0_to_1_odstatechanged_seq
, FALSE
},
3646 { TRUE
, TRUE
, VK_UP
, 1, "select one item via SHIFT+CONTROL+UP",
3647 ownerdata_multiselect_select_0_modkey_odstatechanged_seq
, TRUE
},
3648 { FALSE
, TRUE
, VK_DOWN
, 1, "keep selection but move cursor via CONTROL+DOWN",
3649 ownerdata_multiselect_move_0_to_1_odstatechanged_seq
, FALSE
},
3650 { TRUE
, TRUE
, VK_DOWN
, 3, "select multiple after skip via SHIFT+CONTROL+DOWN",
3651 ownerdata_multiselect_select_0_to_2_odstatechanged_seq
, FALSE
},
3652 { FALSE
, FALSE
, VK_DOWN
, 1, "deselect all, select item 3 via DOWN",
3653 ownerdata_multiselect_select_3_odstatechanged_seq
, FALSE
},
3654 /* First up then down */
3655 { TRUE
, FALSE
, VK_UP
, 2, "select multiple via SHIFT+UP",
3656 ownerdata_multiselect_select_3_to_2_odstatechanged_seq
, FALSE
},
3657 { TRUE
, FALSE
, VK_DOWN
, 1, "select one item via SHIFT+DOWN",
3658 ownerdata_multiselect_select_3_modkey_odstatechanged_seq
, TRUE
},
3659 { TRUE
, TRUE
, VK_UP
, 2, "select multiple via SHIFT+CONTROL+UP",
3660 ownerdata_multiselect_select_3_to_2_odstatechanged_seq
, FALSE
},
3661 { TRUE
, TRUE
, VK_DOWN
, 1, "select one item via SHIFT+CONTROL+DOWN",
3662 ownerdata_multiselect_select_3_modkey_odstatechanged_seq
, TRUE
},
3663 { FALSE
, TRUE
, VK_UP
, 1, "keep selection but move cursor via CONTROL+UP",
3664 ownerdata_multiselect_move_3_to_2_odstatechanged_seq
, FALSE
},
3665 { TRUE
, TRUE
, VK_UP
, 3, "select multiple after skip via SHIFT+CONTROL+UP",
3666 ownerdata_multiselect_select_3_to_1_odstatechanged_seq
, FALSE
},
3667 { FALSE
, FALSE
, VK_UP
, 1, "deselect all, select item 0 via UP",
3668 ownerdata_multiselect_select_0_odstatechanged_seq
, FALSE
},
3671 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3672 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3673 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 20, 0);
3675 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3678 /* Select and focus the first row */
3679 memset(&item
, 0, sizeof(item
));
3680 item
.state
= LVIS_SELECTED
| LVIS_FOCUSED
;
3681 item
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
3682 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3684 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3686 res
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, 0);
3689 /* Select/deselect rows using UP/DOWN and SHIFT/CONTROL keys */
3690 for (i
= 0; i
< ARRAY_SIZE(key_tests
); i
++)
3692 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3694 if (key_tests
[i
].hold_shift
)
3696 if (key_tests
[i
].hold_control
)
3697 hold_key(VK_CONTROL
);
3699 res
= SendMessageA(hwnd
, WM_KEYDOWN
, key_tests
[i
].press_key
, 0);
3701 sprintf(buf
, "ownerdata multiselect: %s", key_tests
[i
].context
);
3702 ok_sequence(sequences
, PARENT_ODSTATECHANGED_SEQ_INDEX
, key_tests
[i
].expected
,
3703 buf
, key_tests
[i
].todo
);
3704 res
= SendMessageA(hwnd
, WM_KEYUP
, key_tests
[i
].press_key
, 0);
3707 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3708 expect(key_tests
[i
].selected_count
, res
);
3710 if (key_tests
[i
].hold_shift
)
3711 release_key(VK_SHIFT
);
3712 if (key_tests
[i
].hold_control
)
3713 release_key(VK_CONTROL
);
3716 DestroyWindow(hwnd
);
3719 static void test_norecompute(void)
3721 static CHAR testA
[] = "test";
3727 /* self containing control */
3728 hwnd
= create_listview_control(LVS_REPORT
);
3729 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3730 memset(&item
, 0, sizeof(item
));
3731 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
3733 item
.stateMask
= LVIS_SELECTED
;
3734 item
.state
= LVIS_SELECTED
;
3735 item
.pszText
= testA
;
3736 res
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3738 /* retrieve with LVIF_NORECOMPUTE */
3739 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
3741 item
.pszText
= buff
;
3742 item
.cchTextMax
= ARRAY_SIZE(buff
);
3743 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3745 ok(lstrcmpA(buff
, testA
) == 0, "Expected (%s), got (%s)\n", testA
, buff
);
3747 item
.mask
= LVIF_TEXT
;
3749 item
.pszText
= LPSTR_TEXTCALLBACKA
;
3750 res
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3753 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
3755 item
.pszText
= buff
;
3756 item
.cchTextMax
= ARRAY_SIZE(buff
);
3758 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3759 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3761 ok(item
.pszText
== LPSTR_TEXTCALLBACKA
, "Expected (%p), got (%p)\n",
3762 LPSTR_TEXTCALLBACKA
, (VOID
*)item
.pszText
);
3763 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq", FALSE
);
3765 DestroyWindow(hwnd
);
3768 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3769 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3771 item
.mask
= LVIF_STATE
;
3772 item
.stateMask
= LVIS_SELECTED
;
3773 item
.state
= LVIS_SELECTED
;
3775 res
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3778 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
3780 item
.pszText
= buff
;
3781 item
.cchTextMax
= ARRAY_SIZE(buff
);
3782 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3783 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3785 ok(item
.pszText
== LPSTR_TEXTCALLBACKA
, "Expected (%p), got (%p)\n",
3786 LPSTR_TEXTCALLBACKA
, (VOID
*)item
.pszText
);
3787 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE
);
3789 DestroyWindow(hwnd
);
3792 static void test_nosortheader(void)
3797 hwnd
= create_listview_control(LVS_REPORT
);
3798 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3800 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
3801 ok(IsWindow(header
), "header expected\n");
3803 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3804 ok(style
& HDS_BUTTONS
, "expected header to have HDS_BUTTONS\n");
3806 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3807 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_NOSORTHEADER
);
3808 /* HDS_BUTTONS retained */
3809 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3810 ok(style
& HDS_BUTTONS
, "expected header to retain HDS_BUTTONS\n");
3812 DestroyWindow(hwnd
);
3814 /* create with LVS_NOSORTHEADER */
3815 hwnd
= create_listview_control(LVS_NOSORTHEADER
| LVS_REPORT
);
3816 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3818 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
3819 ok(IsWindow(header
), "header expected\n");
3821 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3822 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
3824 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3825 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_NOSORTHEADER
);
3826 /* not changed here */
3827 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3828 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
3830 DestroyWindow(hwnd
);
3833 static void test_setredraw(void)
3841 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3842 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3844 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
3845 ListView seems to handle it internally without DefWinProc */
3847 /* default value first */
3848 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3851 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3852 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
3853 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3855 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3856 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
3857 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3860 /* check update rect after redrawing */
3861 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3863 InvalidateRect(hwnd
, NULL
, FALSE
);
3864 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
3865 rect
.right
= rect
.bottom
= 1;
3866 GetUpdateRect(hwnd
, &rect
, FALSE
);
3867 expect(0, rect
.right
);
3868 expect(0, rect
.bottom
);
3871 hdc
= GetWindowDC(hwndparent
);
3872 ret
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
3874 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3876 ret
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
3878 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3880 ReleaseDC(hwndparent
, hdc
);
3882 /* check notification messages to show that repainting is disabled */
3883 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3885 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3887 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3889 InvalidateRect(hwnd
, NULL
, TRUE
);
3891 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3892 "redraw after WM_SETREDRAW (FALSE)", FALSE
);
3894 ret
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
3896 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3897 InvalidateRect(hwnd
, NULL
, TRUE
);
3899 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3900 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE
);
3902 /* message isn't forwarded to header */
3903 subclass_header(hwnd
);
3904 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3905 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3907 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, setredraw_seq
,
3908 "WM_SETREDRAW: not forwarded to header", FALSE
);
3910 DestroyWindow(hwnd
);
3913 static void test_hittest(void)
3919 static CHAR text
[] = "1234567890ABCDEFGHIJKLMNOPQRST";
3923 HIMAGELIST himl
, himl2
;
3926 hwnd
= create_listview_control(LVS_REPORT
);
3927 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3929 /* LVS_REPORT with a single subitem (2 columns) */
3930 insert_column(hwnd
, 0);
3931 insert_column(hwnd
, 1);
3932 insert_item(hwnd
, 0);
3935 /* the only purpose of that line is to be as long as a half item rect */
3936 item
.pszText
= text
;
3937 r
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
3940 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
3942 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
3945 SetRect(&bounds
, LVIR_BOUNDS
, 0, 0, 0);
3946 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&bounds
);
3948 ok(bounds
.bottom
- bounds
.top
> 0, "Expected non zero item height\n");
3949 ok(bounds
.right
- bounds
.left
> 0, "Expected non zero item width\n");
3950 r
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, TRUE
, 0);
3952 ok(bounds
.bottom
- bounds
.top
== vert
,
3953 "Vertical spacing inconsistent (%ld != %d)\n", bounds
.bottom
- bounds
.top
, vert
);
3954 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pos
);
3957 /* LVS_EX_FULLROWSELECT not set, no icons attached */
3959 /* outside columns by x position - valid is [0, 199] */
3961 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3962 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TOLEFT
, 0, FALSE
, FALSE
);
3963 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3965 x
= pos
.x
+ 50; /* column half width */
3966 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3967 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMLABEL
, 0, FALSE
, FALSE
);
3968 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3969 x
= pos
.x
+ 150; /* outside column */
3970 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3971 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
3972 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3973 y
= (bounds
.bottom
- bounds
.top
) / 2;
3974 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
3975 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3976 /* outside possible client rectangle (to right) */
3978 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3979 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
3980 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3981 y
= (bounds
.bottom
- bounds
.top
) / 2;
3982 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
3983 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3984 /* subitem returned with -1 item too */
3986 y
= bounds
.top
- vert
;
3987 test_lvm_subitemhittest(hwnd
, x
, y
, -1, 1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3988 test_lvm_subitemhittest(hwnd
, x
, y
- vert
+ 1, -1, 1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3989 /* return values appear to underflow with negative indices */
3993 test_lvm_subitemhittest(hwnd
, x
, y
, i
, 1, LVHT_ONITEMLABEL
, TRUE
, FALSE
, TRUE
);
3994 test_lvm_subitemhittest(hwnd
, x
, y
- vert
+ 1, i
, 1, LVHT_ONITEMLABEL
, TRUE
, FALSE
, TRUE
);
3998 /* parent client area is 100x100 by default */
3999 MoveWindow(hwnd
, 0, 0, 300, 100, FALSE
);
4000 x
= pos
.x
+ 150; /* outside column */
4001 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4002 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, 0, FALSE
, FALSE
);
4003 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4004 y
= (bounds
.bottom
- bounds
.top
) / 2;
4005 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, 0, FALSE
, TRUE
);
4006 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4007 /* the same with LVS_EX_FULLROWSELECT */
4008 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
4009 x
= pos
.x
+ 150; /* outside column */
4010 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4011 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEM
, LVHT_ONITEMLABEL
, FALSE
, FALSE
);
4012 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4013 y
= (bounds
.bottom
- bounds
.top
) / 2;
4014 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4015 MoveWindow(hwnd
, 0, 0, 100, 100, FALSE
);
4016 x
= pos
.x
+ 150; /* outside column */
4017 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4018 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
4019 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4020 y
= (bounds
.bottom
- bounds
.top
) / 2;
4021 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
4022 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
4023 /* outside possible client rectangle (to right) */
4025 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4026 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
4027 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
4028 y
= (bounds
.bottom
- bounds
.top
) / 2;
4029 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
4030 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
4031 /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
4032 himl
= pImageList_Create(16, 16, 0, 4, 4);
4033 ok(himl
!= NULL
, "failed to create imagelist\n");
4034 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
4035 ok(hbmp
!= NULL
, "failed to create bitmap\n");
4036 r
= pImageList_Add(himl
, hbmp
, 0);
4037 ok(r
== 0, "should be zero\n");
4038 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
4039 ok(hbmp
!= NULL
, "failed to create bitmap\n");
4040 r
= pImageList_Add(himl
, hbmp
, 0);
4041 ok(r
== 1, "should be one\n");
4043 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
4046 item
.mask
= LVIF_IMAGE
;
4050 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4054 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4055 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, 0, FALSE
, FALSE
);
4056 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
4057 y
= (bounds
.bottom
- bounds
.top
) / 2;
4058 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
4060 /* state icons indices are 1 based, check with valid index */
4061 item
.mask
= LVIF_STATE
;
4062 item
.state
= INDEXTOSTATEIMAGEMASK(1);
4063 item
.stateMask
= LVIS_STATEIMAGEMASK
;
4066 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4070 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4071 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, 0, FALSE
, FALSE
);
4072 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
4073 y
= (bounds
.bottom
- bounds
.top
) / 2;
4074 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
4076 himl2
= (HIMAGELIST
)SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, 0);
4077 ok(himl2
== himl
, "should return handle\n");
4079 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
4083 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
4084 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMICON
, 0, FALSE
, FALSE
);
4085 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
);
4086 y
= (bounds
.bottom
- bounds
.top
) / 2;
4087 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
);
4089 DestroyWindow(hwnd
);
4092 static void test_getviewrect(void)
4099 hwnd
= create_listview_control(LVS_REPORT
);
4100 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4103 r
= SendMessageA(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
4106 insert_column(hwnd
, 0);
4107 insert_column(hwnd
, 1);
4109 memset(&item
, 0, sizeof(item
));
4112 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4113 ok(!r
, "got %ld\n", r
);
4115 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
4117 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(120, 0));
4120 SetRect(&rect
, -1, -1, -1, -1);
4121 r
= SendMessageA(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
4123 /* left is set to (2e31-1) - XP SP2 */
4124 expect(0, rect
.right
);
4125 expect(0, rect
.top
);
4126 expect(0, rect
.bottom
);
4128 /* switch to LVS_ICON */
4129 SetWindowLongA(hwnd
, GWL_STYLE
, GetWindowLongA(hwnd
, GWL_STYLE
) & ~LVS_REPORT
);
4131 SetRect(&rect
, -1, -1, -1, -1);
4132 r
= SendMessageA(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
4134 expect(0, rect
.left
);
4135 expect(0, rect
.top
);
4136 /* precise value differs for 2k, XP and Vista */
4137 ok(rect
.bottom
> 0, "Expected positive bottom value, got %ld\n", rect
.bottom
);
4138 ok(rect
.right
> 0, "Expected positive right value, got %ld\n", rect
.right
);
4140 DestroyWindow(hwnd
);
4143 static void test_getitemposition(void)
4150 hwnd
= create_listview_control(LVS_REPORT
);
4151 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4152 header
= subclass_header(hwnd
);
4154 /* LVS_REPORT, single item, no columns added */
4155 insert_item(hwnd
, 0);
4157 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4160 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
4162 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq1
, "get item position 1", FALSE
);
4164 /* LVS_REPORT, single item, single column */
4165 insert_column(hwnd
, 0);
4167 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4170 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
4172 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq2
, "get item position 2", TRUE
);
4174 SetRectEmpty(&rect
);
4175 r
= SendMessageA(header
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4176 ok(r
, "got %ld\n", r
);
4179 /* offset by header height */
4180 expect(rect
.bottom
- rect
.top
, pt
.y
);
4182 DestroyWindow(hwnd
);
4185 static void test_getitemrect(void)
4188 HIMAGELIST himl
, himl_ret
;
4197 /* rectangle isn't empty for empty text items */
4198 hwnd
= create_listview_control(LVS_LIST
);
4199 memset(&item
, 0, sizeof(item
));
4202 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4204 rect
.left
= LVIR_LABEL
;
4205 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4207 expect(0, rect
.left
);
4208 expect(0, rect
.top
);
4209 /* estimate it as width / height ratio */
4211 ok((rect
.right
/ rect
.bottom
) >= 5, "got right %ld, bottom %ld\n", rect
.right
, rect
.bottom
);
4212 DestroyWindow(hwnd
);
4214 hwnd
= create_listview_control(LVS_REPORT
);
4215 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4218 memset(&item
, 0, sizeof(item
));
4221 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4224 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4225 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4228 /* zero width rectangle with no padding */
4229 expect(0, rect
.left
);
4230 expect(0, rect
.right
);
4232 insert_column(hwnd
, 0);
4233 insert_column(hwnd
, 1);
4235 col
.mask
= LVCF_WIDTH
;
4237 r
= SendMessageA(hwnd
, LVM_SETCOLUMNA
, 0, (LPARAM
)&col
);
4240 col
.mask
= LVCF_WIDTH
;
4242 r
= SendMessageA(hwnd
, LVM_SETCOLUMNA
, 1, (LPARAM
)&col
);
4245 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4246 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4249 /* still no left padding */
4250 expect(0, rect
.left
);
4251 expect(150, rect
.right
);
4253 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4254 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4257 expect(2, rect
.left
);
4259 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4260 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4262 /* padding, column width */
4263 expect(2, rect
.left
);
4264 expect(50, rect
.right
);
4266 /* no icons attached */
4267 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4268 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4271 expect(2, rect
.left
);
4272 expect(2, rect
.right
);
4275 order
[0] = 1; order
[1] = 0;
4276 r
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
4279 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
4281 /* 1 indexed column width + padding */
4283 /* rect is at zero too */
4284 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4285 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4287 expect(0, rect
.left
);
4288 /* just width sum */
4289 expect(150, rect
.right
);
4291 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4292 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4294 /* column width + padding */
4295 expect(102, rect
.left
);
4297 /* back to initial order */
4298 order
[0] = 0; order
[1] = 1;
4299 r
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
4303 himl
= pImageList_Create(16, 16, 0, 2, 2);
4304 ok(himl
!= NULL
, "failed to create imagelist\n");
4305 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
4306 ok(hbm
!= NULL
, "failed to create bitmap\n");
4307 r
= pImageList_Add(himl
, hbm
, 0);
4309 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
4310 ok(hbm
!= NULL
, "failed to create bitmap\n");
4311 r
= pImageList_Add(himl
, hbm
, 0);
4314 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
4317 item
.mask
= LVIF_STATE
;
4318 item
.state
= INDEXTOSTATEIMAGEMASK(1);
4319 item
.stateMask
= LVIS_STATEIMAGEMASK
;
4322 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4326 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4327 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4329 /* padding + stateicon width */
4330 expect(18, rect
.left
);
4331 expect(18, rect
.right
);
4333 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4334 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4336 /* padding + stateicon width -> column width */
4337 expect(18, rect
.left
);
4338 expect(50, rect
.right
);
4340 himl_ret
= (HIMAGELIST
)SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, 0);
4341 ok(himl_ret
== himl
, "got %p, expected %p\n", himl_ret
, himl
);
4343 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
4346 item
.mask
= LVIF_STATE
| LVIF_IMAGE
;
4349 item
.stateMask
= ~0;
4352 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4356 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4357 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4359 /* padding, icon width */
4360 expect(2, rect
.left
);
4361 expect(18, rect
.right
);
4363 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4364 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4366 /* padding + icon width -> column width */
4367 expect(18, rect
.left
);
4368 expect(50, rect
.right
);
4371 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4372 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4374 /* padding, column width */
4375 expect(2, rect
.left
);
4376 expect(50, rect
.right
);
4378 /* try with indentation */
4379 item
.mask
= LVIF_INDENT
;
4383 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4387 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4388 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4390 /* padding + 1 icon width, column width */
4391 expect(0, rect
.left
);
4392 expect(150, rect
.right
);
4395 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4396 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4398 /* padding + 1 icon width, column width */
4399 expect(2 + 16, rect
.left
);
4400 expect(50, rect
.right
);
4403 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4404 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4406 /* padding + 2 icon widths, column width */
4407 expect(2 + 16*2, rect
.left
);
4408 expect(50, rect
.right
);
4411 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4412 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4414 /* padding + 1 icon width indentation, icon width */
4415 expect(2 + 16, rect
.left
);
4416 expect(34, rect
.right
);
4418 DestroyWindow(hwnd
);
4421 static void test_editbox(void)
4423 static CHAR testitemA
[] = "testitem";
4424 static CHAR testitem1A
[] = "testitem_quitelongname";
4425 static CHAR testitem2A
[] = "testITEM_quitelongname";
4426 static CHAR buffer
[25];
4427 HWND hwnd
, hwndedit
, hwndedit2
, header
;
4431 hwnd
= create_listview_control(LVS_EDITLABELS
| LVS_REPORT
);
4432 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4434 insert_column(hwnd
, 0);
4436 memset(&item
, 0, sizeof(item
));
4437 item
.mask
= LVIF_TEXT
;
4438 item
.pszText
= testitemA
;
4441 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4444 /* test notifications without edit created */
4445 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4446 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_SETFOCUS
), (LPARAM
)0xdeadbeef);
4448 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
4449 "edit box WM_COMMAND (EN_SETFOCUS), no edit created", FALSE
);
4450 /* same thing but with valid window */
4451 hwndedit
= CreateWindowA(WC_EDITA
, "Test edit", WS_VISIBLE
| WS_CHILD
, 0, 0, 20,
4452 10, hwnd
, (HMENU
)1, (HINSTANCE
)GetWindowLongPtrA(hwnd
, GWLP_HINSTANCE
), 0);
4453 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4454 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_SETFOCUS
), (LPARAM
)hwndedit
);
4456 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
4457 "edit box WM_COMMAND (EN_SETFOCUS), no edit created #2", FALSE
);
4458 DestroyWindow(hwndedit
);
4460 /* setting focus is necessary */
4462 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4463 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4465 /* test children Z-order after Edit box created */
4466 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4467 ok(IsWindow(header
), "Expected header to be created\n");
4468 ok(GetTopWindow(hwnd
) == header
, "Expected header to be on top\n");
4469 ok(GetNextWindow(header
, GW_HWNDNEXT
) == hwndedit
, "got %p\n", GetNextWindow(header
, GW_HWNDNEXT
));
4471 /* modify initial string */
4472 r
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
4475 /* edit window is resized and repositioned,
4476 check again for Z-order - it should be preserved */
4477 ok(GetTopWindow(hwnd
) == header
, "Expected header to be on top\n");
4478 ok(GetNextWindow(header
, GW_HWNDNEXT
) == hwndedit
, "got %p\n", GetNextWindow(header
, GW_HWNDNEXT
));
4480 /* return focus to listview */
4483 memset(&item
, 0, sizeof(item
));
4484 item
.mask
= LVIF_TEXT
;
4485 item
.pszText
= buffer
;
4486 item
.cchTextMax
= sizeof(buffer
);
4489 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
4492 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
4494 /* send LVM_EDITLABEL on already created edit */
4496 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4497 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4498 /* focus will be set to edit */
4499 ok(GetFocus() == hwndedit
, "Expected Edit window to be focused\n");
4500 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4501 ok(IsWindow(hwndedit2
), "Expected Edit window to be created\n");
4503 /* creating label disabled when control isn't focused */
4505 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4506 todo_wine
ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
4508 /* check EN_KILLFOCUS handling */
4509 memset(&item
, 0, sizeof(item
));
4510 item
.pszText
= testitemA
;
4513 r
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
4517 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4518 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4519 /* modify edit and notify control that it lost focus */
4520 r
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
4522 g_editbox_disp_info
.item
.pszText
= NULL
;
4523 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
4525 ok(g_editbox_disp_info
.item
.pszText
!= NULL
, "expected notification with not null text\n");
4527 memset(&item
, 0, sizeof(item
));
4528 item
.pszText
= buffer
;
4529 item
.cchTextMax
= sizeof(buffer
);
4532 r
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
4533 expect(lstrlenA(item
.pszText
), r
);
4534 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
4535 ok(!IsWindow(hwndedit
), "Expected Edit window to be freed\n");
4537 /* change item name to differ in casing only */
4539 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4540 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4541 /* modify edit and notify control that it lost focus */
4542 r
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem2A
);
4544 g_editbox_disp_info
.item
.pszText
= NULL
;
4545 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
4547 ok(g_editbox_disp_info
.item
.pszText
!= NULL
, "got %p\n", g_editbox_disp_info
.item
.pszText
);
4549 memset(&item
, 0, sizeof(item
));
4550 item
.pszText
= buffer
;
4551 item
.cchTextMax
= sizeof(buffer
);
4554 r
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
4555 expect(lstrlenA(item
.pszText
), r
);
4556 ok(strcmp(buffer
, testitem2A
) == 0, "got %s, expected %s\n", buffer
, testitem2A
);
4557 ok(!IsWindow(hwndedit
), "Expected Edit window to be freed\n");
4559 /* end edit without saving */
4561 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4562 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4563 r
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_ESCAPE
, 0);
4565 ok_sequence(sequences
, PARENT_SEQ_INDEX
, edit_end_nochange
,
4566 "edit box - end edit, no change, escape", TRUE
);
4567 /* end edit with saving */
4569 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4570 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4571 r
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_RETURN
, 0);
4573 ok_sequence(sequences
, PARENT_SEQ_INDEX
, edit_end_nochange
,
4574 "edit box - end edit, no change, return", TRUE
);
4576 memset(&item
, 0, sizeof(item
));
4577 item
.pszText
= buffer
;
4578 item
.cchTextMax
= sizeof(buffer
);
4581 r
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
4582 expect(lstrlenA(item
.pszText
), r
);
4583 ok(strcmp(buffer
, testitem2A
) == 0, "Expected item text to change\n");
4585 /* LVM_EDITLABEL with -1 destroys current edit */
4586 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_GETEDITCONTROL
, 0, 0);
4587 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
4588 /* no edit present */
4589 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, -1, 0);
4590 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
4591 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4592 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4594 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
4595 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, -1, 0);
4596 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
4597 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
4598 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
4599 /* check another negative value */
4600 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4601 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4602 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
4603 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, -2, 0);
4604 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
4605 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
4606 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
4607 /* and value greater than max item index */
4608 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4609 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4610 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
4611 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
4612 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, r
, 0);
4613 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
4614 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
4615 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
4617 /* messaging tests */
4619 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4621 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4622 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4623 /* testing only sizing messages */
4624 ok_sequence(sequences
, EDITBOX_SEQ_INDEX
, editbox_create_pos
,
4625 "edit box create - sizing", FALSE
);
4627 /* WM_COMMAND with EN_KILLFOCUS isn't forwarded to parent */
4629 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4630 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4631 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4632 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
4634 ok_sequence(sequences
, PARENT_SEQ_INDEX
, edit_end_nochange
,
4635 "edit box WM_COMMAND (EN_KILLFOCUS)", TRUE
);
4637 DestroyWindow(hwnd
);
4640 static void test_notifyformat(void)
4645 hwnd
= create_listview_control(LVS_REPORT
);
4646 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4648 /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
4649 CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
4650 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4652 SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
4654 r
= SendMessageA(hwnd
, LVM_SETUNICODEFORMAT
, 1, 0);
4656 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4657 ok(r
== 1, "Unexpected return value %ld.\n", r
);
4658 r
= SendMessageA(hwnd
, LVM_SETUNICODEFORMAT
, 0, 0);
4660 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4663 DestroyWindow(hwnd
);
4665 /* test failure in parent WM_NOTIFYFORMAT */
4667 hwnd
= create_listview_control(LVS_REPORT
);
4668 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4669 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4670 ok(IsWindow(header
), "expected header to be created\n");
4671 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4673 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4674 ok( r
== 1, "Expected 1, got %ld\n", r
);
4675 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
4676 ok(r
!= 0, "Expected valid format\n");
4678 notifyFormat
= NFR_UNICODE
;
4679 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
4680 expect(NFR_UNICODE
, r
);
4681 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4683 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4684 ok( r
== 1, "Expected 1, got %ld\n", r
);
4686 notifyFormat
= NFR_ANSI
;
4687 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
4688 expect(NFR_ANSI
, r
);
4689 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4691 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4692 ok( r
== 1, "Expected 1, got %ld\n", r
);
4694 DestroyWindow(hwnd
);
4696 hwndparentW
= create_parent_window(TRUE
);
4697 ok(IsWindow(hwndparentW
), "Unicode parent creation failed\n");
4698 if (!IsWindow(hwndparentW
)) return;
4701 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparentW
);
4702 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4703 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4704 ok(IsWindow(header
), "expected header to be created\n");
4705 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4707 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4709 DestroyWindow(hwnd
);
4710 /* receiving error code defaulting to ansi */
4712 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparentW
);
4713 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4714 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4715 ok(IsWindow(header
), "expected header to be created\n");
4716 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4718 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4720 DestroyWindow(hwnd
);
4721 /* receiving ansi code from unicode window, use it */
4722 notifyFormat
= NFR_ANSI
;
4723 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparentW
);
4724 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4725 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4726 ok(IsWindow(header
), "expected header to be created\n");
4727 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4729 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4731 DestroyWindow(hwnd
);
4732 /* unicode listview with ansi parent window */
4734 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparent
);
4735 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4736 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4737 ok(IsWindow(header
), "expected header to be created\n");
4738 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4740 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4742 DestroyWindow(hwnd
);
4743 /* unicode listview with ansi parent window, return error code */
4745 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparent
);
4746 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4747 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4748 ok(IsWindow(header
), "expected header to be created\n");
4749 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4751 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4753 DestroyWindow(hwnd
);
4755 DestroyWindow(hwndparentW
);
4758 static void test_indentation(void)
4764 hwnd
= create_listview_control(LVS_REPORT
);
4765 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4767 memset(&item
, 0, sizeof(item
));
4768 item
.mask
= LVIF_INDENT
;
4770 item
.iIndent
= I_INDENTCALLBACK
;
4771 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4774 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4777 item
.mask
= LVIF_INDENT
;
4778 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
4781 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
4782 "get indent dispinfo", FALSE
);
4784 /* Ask for iIndent with invalid subitem. */
4785 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4787 memset(&item
, 0, sizeof(item
));
4788 item
.mask
= LVIF_INDENT
;
4790 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
4791 ok(r
, "Failed to get item.\n");
4793 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "get indent dispinfo 2", FALSE
);
4795 DestroyWindow(hwnd
);
4798 static void test_get_set_view(void)
4804 /* test style->view mapping */
4805 hwnd
= create_listview_control(LVS_REPORT
);
4806 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4808 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4809 expect(LV_VIEW_DETAILS
, ret
);
4811 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4813 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_REPORT
);
4814 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4815 expect(LV_VIEW_ICON
, ret
);
4817 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4818 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SMALLICON
);
4819 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4820 expect(LV_VIEW_SMALLICON
, ret
);
4822 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4823 SetWindowLongPtrA(hwnd
, GWL_STYLE
, (style
& ~LVS_SMALLICON
) | LVS_LIST
);
4824 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4825 expect(LV_VIEW_LIST
, ret
);
4827 /* switching view doesn't touch window style */
4828 ret
= SendMessageA(hwnd
, LVM_SETVIEW
, LV_VIEW_DETAILS
, 0);
4830 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4831 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
4832 ret
= SendMessageA(hwnd
, LVM_SETVIEW
, LV_VIEW_ICON
, 0);
4834 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4835 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
4836 ret
= SendMessageA(hwnd
, LVM_SETVIEW
, LV_VIEW_SMALLICON
, 0);
4838 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4839 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
4841 /* now change window style to see if view is remapped */
4842 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4843 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SHOWSELALWAYS
);
4844 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4845 expect(LV_VIEW_SMALLICON
, ret
);
4847 DestroyWindow(hwnd
);
4850 static void test_canceleditlabel(void)
4852 HWND hwnd
, hwndedit
;
4856 static CHAR test
[] = "test";
4857 static const CHAR test1
[] = "test1";
4859 hwnd
= create_listview_control(LVS_EDITLABELS
| LVS_REPORT
);
4860 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4862 insert_item(hwnd
, 0);
4864 /* try without edit created */
4865 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4866 ret
= SendMessageA(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
4868 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
4869 "cancel edit label without edit", FALSE
);
4871 /* cancel without data change */
4873 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4874 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
4875 ret
= SendMessageA(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
4877 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
4879 /* cancel after data change */
4880 memset(&itema
, 0, sizeof(itema
));
4881 itema
.pszText
= test
;
4882 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&itema
);
4885 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4886 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
4887 ret
= SetWindowTextA(hwndedit
, test1
);
4889 ret
= SendMessageA(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
4891 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
4892 memset(&itema
, 0, sizeof(itema
));
4893 itema
.pszText
= buff
;
4894 itema
.cchTextMax
= ARRAY_SIZE(buff
);
4895 ret
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&itema
);
4897 ok(strcmp(buff
, test1
) == 0, "Expected label text not to change\n");
4899 DestroyWindow(hwnd
);
4902 static void test_mapidindex(void)
4907 /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
4908 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
4909 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4910 insert_item(hwnd
, 0);
4911 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4913 DestroyWindow(hwnd
);
4915 hwnd
= create_listview_control(LVS_REPORT
);
4916 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4918 /* LVM_MAPINDEXTOID with invalid index */
4919 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4922 insert_item(hwnd
, 0);
4923 insert_item(hwnd
, 1);
4925 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, -1, 0);
4927 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 2, 0);
4930 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4932 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
4934 /* remove 0 indexed item, id retained */
4935 SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
4936 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4938 /* new id starts from previous value */
4939 insert_item(hwnd
, 1);
4940 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
4943 /* get index by id */
4944 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, -1, 0);
4946 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, 0, 0);
4948 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, 1, 0);
4950 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, 2, 0);
4953 DestroyWindow(hwnd
);
4956 static void test_getitemspacing(void)
4961 HIMAGELIST himl40
, himl80
;
4963 cx
= GetSystemMetrics(SM_CXICONSPACING
) - GetSystemMetrics(SM_CXICON
);
4964 cy
= GetSystemMetrics(SM_CYICONSPACING
) - GetSystemMetrics(SM_CYICON
);
4967 hwnd
= create_listview_control(LVS_ICON
);
4968 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4969 expect(cx
, LOWORD(ret
));
4970 expect(cy
, HIWORD(ret
));
4972 /* now try with icons */
4973 himl40
= pImageList_Create(40, 40, 0, 4, 4);
4974 ok(himl40
!= NULL
, "failed to create imagelist\n");
4975 himl80
= pImageList_Create(80, 80, 0, 4, 4);
4976 ok(himl80
!= NULL
, "failed to create imagelist\n");
4977 ret
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl40
);
4980 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4981 /* spacing + icon size returned */
4982 expect(cx
+ 40, LOWORD(ret
));
4983 expect(cy
+ 40, HIWORD(ret
));
4984 /* try changing icon size */
4985 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl80
);
4987 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4988 /* spacing + icon size returned */
4989 expect(cx
+ 80, LOWORD(ret
));
4990 expect(cy
+ 80, HIWORD(ret
));
4992 /* set own icon spacing */
4993 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(100, 100));
4994 expect(cx
+ 80, LOWORD(ret
));
4995 expect(cy
+ 80, HIWORD(ret
));
4997 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4998 /* set size returned */
4999 expect(100, LOWORD(ret
));
5000 expect(100, HIWORD(ret
));
5002 /* now change image list - icon spacing should be unaffected */
5003 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl40
);
5005 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5006 /* set size returned */
5007 expect(100, LOWORD(ret
));
5008 expect(100, HIWORD(ret
));
5010 /* spacing = 0 - keep previous value */
5011 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(0, -1));
5012 expect(100, LOWORD(ret
));
5013 expect(100, HIWORD(ret
));
5015 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5016 expect(100, LOWORD(ret
));
5018 expect(0xFFFF, HIWORD(ret
));
5020 if (sizeof(void*) == 8)
5022 /* NOTE: -1 is not treated the same as (DWORD)-1 by 64bit listview */
5023 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, (DWORD
)-1);
5024 expect(100, LOWORD(ret
));
5025 expect(0xFFFF, HIWORD(ret
));
5027 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, -1);
5028 expect(0xFFFF, LOWORD(ret
));
5029 expect(0xFFFF, HIWORD(ret
));
5033 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, -1);
5034 expect(100, LOWORD(ret
));
5035 expect(0xFFFF, HIWORD(ret
));
5037 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5038 /* spacing + icon size returned */
5039 expect(cx
+ 40, LOWORD(ret
));
5040 expect(cy
+ 40, HIWORD(ret
));
5042 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, 0);
5043 pImageList_Destroy(himl80
);
5044 DestroyWindow(hwnd
);
5046 hwnd
= create_listview_control(LVS_SMALLICON
);
5047 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5048 expect(cx
, LOWORD(ret
));
5049 expect(cy
, HIWORD(ret
));
5051 /* spacing does not depend on selected view type */
5052 ret
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl40
);
5055 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5056 /* spacing + icon size returned */
5057 expect(cx
+ 40, LOWORD(ret
));
5058 expect(cy
+ 40, HIWORD(ret
));
5060 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, 0);
5061 pImageList_Destroy(himl40
);
5062 DestroyWindow(hwnd
);
5064 hwnd
= create_listview_control(LVS_REPORT
);
5065 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5066 expect(cx
, LOWORD(ret
));
5067 expect(cy
, HIWORD(ret
));
5069 DestroyWindow(hwnd
);
5071 hwnd
= create_listview_control(LVS_LIST
);
5072 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
5073 expect(cx
, LOWORD(ret
));
5074 expect(cy
, HIWORD(ret
));
5076 DestroyWindow(hwnd
);
5079 static INT
get_current_font_height(HWND listview
)
5086 hwnd
= (HWND
)SendMessageA(listview
, LVM_GETHEADER
, 0, 0);
5090 hfont
= (HFONT
)SendMessageA(hwnd
, WM_GETFONT
, 0, 0);
5093 GetTextMetricsA(hdc
, &tm
);
5094 ReleaseDC(hwnd
, hdc
);
5100 oldfont
= SelectObject(hdc
, hfont
);
5101 GetTextMetricsA(hdc
, &tm
);
5102 SelectObject(hdc
, oldfont
);
5109 static void test_getcolumnwidth(void)
5118 /* default column width */
5119 hwnd
= create_listview_control(LVS_ICON
);
5120 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
5122 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5123 SetWindowLongA(hwnd
, GWL_STYLE
, style
| LVS_LIST
);
5124 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
5125 todo_wine
expect(8, ret
);
5126 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~LVS_LIST
;
5127 SetWindowLongA(hwnd
, GWL_STYLE
, style
| LVS_REPORT
);
5129 ret
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5131 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
5133 DestroyWindow(hwnd
);
5135 /* default column width with item added */
5136 hwnd
= create_listview_control(LVS_LIST
);
5137 memset(&itema
, 0, sizeof(itema
));
5138 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&itema
);
5139 ok(!ret
, "got %d\n", ret
);
5140 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
5141 height
= get_current_font_height(hwnd
);
5142 ok((ret
/ height
) >= 6, "got width %d, height %d\n", ret
, height
);
5143 DestroyWindow(hwnd
);
5146 static void test_scrollnotify(void)
5151 hwnd
= create_listview_control(LVS_REPORT
);
5153 insert_column(hwnd
, 0);
5154 insert_column(hwnd
, 1);
5155 insert_item(hwnd
, 0);
5157 /* make it scrollable - resize */
5158 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
5160 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
5163 /* try with dummy call */
5164 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5165 ret
= SendMessageA(hwnd
, LVM_SCROLL
, 0, 0);
5167 ok_sequence(sequences
, PARENT_SEQ_INDEX
, scroll_parent_seq
,
5168 "scroll notify 1", TRUE
);
5170 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5171 ret
= SendMessageA(hwnd
, LVM_SCROLL
, 1, 0);
5173 ok_sequence(sequences
, PARENT_SEQ_INDEX
, scroll_parent_seq
,
5174 "scroll notify 2", TRUE
);
5176 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5177 ret
= SendMessageA(hwnd
, LVM_SCROLL
, 1, 1);
5179 ok_sequence(sequences
, PARENT_SEQ_INDEX
, scroll_parent_seq
,
5180 "scroll notify 3", TRUE
);
5182 DestroyWindow(hwnd
);
5185 static void test_LVS_EX_TRANSPARENTBKGND(void)
5191 hwnd
= create_listview_control(LVS_REPORT
);
5193 ret
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, RGB(0, 0, 0));
5196 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_TRANSPARENTBKGND
,
5197 LVS_EX_TRANSPARENTBKGND
);
5199 ret
= SendMessageA(hwnd
, LVM_GETBKCOLOR
, 0, 0);
5200 if (ret
!= CLR_NONE
)
5202 win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n");
5203 DestroyWindow(hwnd
);
5207 /* try to set some back color and check this style bit */
5208 ret
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, RGB(0, 0, 0));
5210 ret
= SendMessageA(hwnd
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
5211 ok(!(ret
& LVS_EX_TRANSPARENTBKGND
), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
5213 /* now test what this style actually does */
5214 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_TRANSPARENTBKGND
,
5215 LVS_EX_TRANSPARENTBKGND
);
5217 hdc
= GetWindowDC(hwndparent
);
5219 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5220 SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
5221 ok_sequence(sequences
, PARENT_SEQ_INDEX
, lvs_ex_transparentbkgnd_seq
,
5222 "LVS_EX_TRANSPARENTBKGND parent", FALSE
);
5224 ReleaseDC(hwndparent
, hdc
);
5226 DestroyWindow(hwnd
);
5229 static void test_approximate_viewrect(void)
5231 static CHAR test
[] = "abracadabra, a very long item label";
5232 DWORD item_width
, item_height
, header_height
;
5233 static CHAR column_header
[] = "Header";
5234 unsigned const column_width
= 100;
5235 DWORD ret
, item_count
;
5243 hwnd
= create_listview_control(LVS_ICON
);
5244 himl
= pImageList_Create(40, 40, 0, 4, 4);
5245 ok(himl
!= NULL
, "failed to create imagelist\n");
5246 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
5247 ok(hbmp
!= NULL
, "failed to create bitmap\n");
5248 ret
= pImageList_Add(himl
, hbmp
, 0);
5250 ret
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
5253 itema
.mask
= LVIF_IMAGE
;
5257 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&itema
);
5260 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(75, 75));
5261 ok(ret
!= 0, "Unexpected return value %#lx.\n", ret
);
5263 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 11, MAKELPARAM(100,100));
5264 expect(MAKELONG(77,827), ret
);
5266 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(50, 50));
5267 ok(ret
!= 0, "got 0\n");
5269 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 11, MAKELPARAM(100,100));
5270 expect(MAKELONG(102,302), ret
);
5272 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, MAKELPARAM(100,100));
5273 expect(MAKELONG(52,52), ret
);
5275 itema
.pszText
= test
;
5276 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&itema
);
5278 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, MAKELPARAM(100,100));
5279 expect(MAKELONG(52,52), ret
);
5281 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, MAKELPARAM(100,100));
5282 expect(MAKELONG(52,2), ret
);
5283 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 1, MAKELPARAM(100,100));
5284 expect(MAKELONG(52,52), ret
);
5285 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, MAKELPARAM(100,100));
5286 expect(MAKELONG(102,52), ret
);
5287 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 3, MAKELPARAM(100,100));
5288 expect(MAKELONG(102,102), ret
);
5289 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 4, MAKELPARAM(100,100));
5290 expect(MAKELONG(102,102), ret
);
5291 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 5, MAKELPARAM(100,100));
5292 expect(MAKELONG(102,152), ret
);
5293 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 6, MAKELPARAM(100,100));
5294 expect(MAKELONG(102,152), ret
);
5295 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 7, MAKELPARAM(160,100));
5296 expect(MAKELONG(152,152), ret
);
5298 DestroyWindow(hwnd
);
5301 hwnd
= create_listview_control(LVS_REPORT
);
5303 /* Empty control without columns */
5304 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, MAKELPARAM(100, 100));
5306 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5307 ok(HIWORD(ret
) != 0, "Unexpected height %d.\n", HIWORD(ret
));
5309 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, 0);
5310 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5312 ok(HIWORD(ret
) != 0, "Unexpected height %d.\n", HIWORD(ret
));
5314 header_height
= HIWORD(ret
);
5316 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 1, 0);
5317 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5319 ok(HIWORD(ret
) > header_height
, "Unexpected height %d.\n", HIWORD(ret
));
5321 item_height
= HIWORD(ret
) - header_height
;
5323 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, 0);
5324 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5325 ok(HIWORD(ret
) == (header_height
- 2 * item_height
), "Unexpected height %d.\n", HIWORD(ret
)) ;
5327 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, 0);
5328 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5329 ok(HIWORD(ret
) == header_height
, "Unexpected height.\n");
5330 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, 0);
5331 ok(LOWORD(ret
) == 0, "Unexpected width %d.\n", LOWORD(ret
));
5332 ok(HIWORD(ret
) == header_height
+ 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5335 col
.mask
= LVCF_TEXT
| LVCF_WIDTH
;
5336 col
.pszText
= column_header
;
5337 col
.cx
= column_width
;
5338 ret
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5339 ok(ret
== 0, "Unexpected return value %ld.\n", ret
);
5341 /* Empty control with column */
5342 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, 0);
5344 ok(LOWORD(ret
) >= column_width
, "Unexpected width %d.\n", LOWORD(ret
));
5345 ok(HIWORD(ret
) != 0, "Unexpected height %d.\n", HIWORD(ret
));
5347 header_height
= HIWORD(ret
);
5348 item_width
= LOWORD(ret
);
5350 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 1, 0);
5351 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5353 ok(HIWORD(ret
) > header_height
, "Unexpected height %d.\n", HIWORD(ret
));
5355 item_height
= HIWORD(ret
) - header_height
;
5357 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, 0);
5358 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5359 ok(HIWORD(ret
) == header_height
- 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5361 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, 0);
5362 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5363 ok(HIWORD(ret
) == header_height
, "Unexpected height %d.\n", HIWORD(ret
));
5365 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, 0);
5366 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5367 ok(HIWORD(ret
) == header_height
+ 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5369 for (item_count
= 1; item_count
<= 2; ++item_count
)
5371 itema
.mask
= LVIF_TEXT
;
5374 itema
.pszText
= test
;
5375 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&itema
);
5376 ok(ret
== 0, "Unexpected return value %ld.\n", ret
);
5378 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, 0);
5379 ok(LOWORD(ret
) >= column_width
, "Unexpected width %d.\n", LOWORD(ret
));
5381 ok(HIWORD(ret
) != 0, "Unexpected height %d.\n", HIWORD(ret
));
5383 header_height
= HIWORD(ret
);
5384 item_width
= LOWORD(ret
);
5386 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 1, 0);
5387 ok(LOWORD(ret
) == item_width
, "Unexpected width %d, item %ld\n", LOWORD(ret
), item_count
- 1);
5388 ok(HIWORD(ret
) > header_height
, "Unexpected height %d. item %ld.\n", HIWORD(ret
), item_count
- 1);
5390 item_height
= HIWORD(ret
) - header_height
;
5392 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, 0);
5393 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5395 ok(HIWORD(ret
) == header_height
- 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5397 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, 0);
5398 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5399 ok(HIWORD(ret
) == header_height
+ item_count
* item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5401 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, 0);
5402 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5403 ok(HIWORD(ret
) == header_height
+ 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5405 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, MAKELONG(item_width
* 2, header_height
+ 3 * item_height
));
5406 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5407 ok(HIWORD(ret
) == header_height
+ 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5409 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, MAKELONG(item_width
* 2, 0));
5410 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5412 ok(HIWORD(ret
) == header_height
- 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5414 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -2, MAKELONG(-1, -1));
5415 ok(LOWORD(ret
) == item_width
, "Unexpected width %d.\n", LOWORD(ret
));
5417 ok(HIWORD(ret
) == header_height
- 2 * item_height
, "Unexpected height %d.\n", HIWORD(ret
));
5420 DestroyWindow(hwnd
);
5424 static void test_finditem(void)
5431 hwnd
= create_listview_control(LVS_REPORT
);
5432 insert_item(hwnd
, 0);
5434 memset(&fi
, 0, sizeof(fi
));
5436 /* full string search, inserted text was "foo" */
5438 fi
.flags
= LVFI_STRING
;
5440 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5443 fi
.flags
= LVFI_STRING
| LVFI_PARTIAL
;
5444 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5447 fi
.flags
= LVFI_PARTIAL
;
5448 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5451 /* partial string search, inserted text was "foo" */
5453 fi
.flags
= LVFI_STRING
| LVFI_PARTIAL
;
5455 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5458 fi
.flags
= LVFI_STRING
;
5459 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5462 fi
.flags
= LVFI_PARTIAL
;
5463 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5466 /* partial string search, part after start char */
5468 fi
.flags
= LVFI_STRING
| LVFI_PARTIAL
;
5470 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5473 /* try with LVFI_SUBSTRING */
5475 fi
.flags
= LVFI_SUBSTRING
;
5477 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5480 fi
.flags
= LVFI_SUBSTRING
;
5482 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5485 fi
.flags
= LVFI_SUBSTRING
;
5487 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5491 fi
.flags
= LVFI_SUBSTRING
| LVFI_PARTIAL
;
5493 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5497 fi
.flags
= LVFI_SUBSTRING
| LVFI_STRING
;
5499 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5502 fi
.flags
= LVFI_SUBSTRING
| LVFI_PARTIAL
;
5503 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5506 /* Case sensitivity. */
5508 fi
.flags
= LVFI_STRING
;
5510 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5511 ok(!r
, "Unexpected item index %d.\n", r
);
5514 fi
.flags
= LVFI_SUBSTRING
;
5516 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5517 ok(!r
, "Unexpected item index %d.\n", r
);
5519 DestroyWindow(hwnd
);
5522 static void test_LVS_EX_HEADERINALLVIEWS(void)
5527 hwnd
= create_listview_control(LVS_ICON
);
5529 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5530 LVS_EX_HEADERINALLVIEWS
);
5532 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5533 if (!IsWindow(header
))
5535 win_skip("LVS_EX_HEADERINALLVIEWS unsupported\n");
5536 DestroyWindow(hwnd
);
5540 /* LVS_NOCOLUMNHEADER works as before */
5541 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5542 SetWindowLongW(hwnd
, GWL_STYLE
, style
| LVS_NOCOLUMNHEADER
);
5543 style
= GetWindowLongA(header
, GWL_STYLE
);
5544 ok(style
& HDS_HIDDEN
, "Expected HDS_HIDDEN\n");
5545 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5546 SetWindowLongW(hwnd
, GWL_STYLE
, style
& ~LVS_NOCOLUMNHEADER
);
5547 style
= GetWindowLongA(header
, GWL_STYLE
);
5548 ok(!(style
& HDS_HIDDEN
), "Expected HDS_HIDDEN to be unset\n");
5550 /* try to remove style */
5551 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
, 0);
5552 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5553 ok(IsWindow(header
), "Expected header to be created\n");
5554 style
= GetWindowLongA(header
, GWL_STYLE
);
5555 ok(!(style
& HDS_HIDDEN
), "HDS_HIDDEN not expected\n");
5557 DestroyWindow(hwnd
);
5559 /* check other styles */
5560 hwnd
= create_listview_control(LVS_LIST
);
5561 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5562 LVS_EX_HEADERINALLVIEWS
);
5563 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5564 ok(IsWindow(header
), "Expected header to be created\n");
5565 DestroyWindow(hwnd
);
5567 hwnd
= create_listview_control(LVS_SMALLICON
);
5568 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5569 LVS_EX_HEADERINALLVIEWS
);
5570 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5571 ok(IsWindow(header
), "Expected header to be created\n");
5572 DestroyWindow(hwnd
);
5574 hwnd
= create_listview_control(LVS_REPORT
);
5575 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5576 LVS_EX_HEADERINALLVIEWS
);
5577 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5578 ok(IsWindow(header
), "Expected header to be created\n");
5579 DestroyWindow(hwnd
);
5582 static void test_hover(void)
5587 hwnd
= create_listview_control(LVS_ICON
);
5588 SetForegroundWindow(hwndparent
);
5589 fg
= GetForegroundWindow();
5590 if (fg
!= hwndparent
)
5592 skip("Window is not in the foreground. Skipping hover tests.\n");
5593 DestroyWindow(hwnd
);
5597 /* test WM_MOUSEHOVER forwarding */
5598 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5599 r
= SendMessageA(hwnd
, WM_MOUSEHOVER
, 0, 0);
5601 ok_sequence(sequences
, PARENT_SEQ_INDEX
, hover_parent
, "NM_HOVER allow test", TRUE
);
5602 g_block_hover
= TRUE
;
5603 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5604 r
= SendMessageA(hwnd
, WM_MOUSEHOVER
, 0, 0);
5606 ok_sequence(sequences
, PARENT_SEQ_INDEX
, hover_parent
, "NM_HOVER block test", TRUE
);
5607 g_block_hover
= FALSE
;
5609 r
= SendMessageA(hwnd
, LVM_SETHOVERTIME
, 0, 500);
5610 expect(HOVER_DEFAULT
, r
);
5611 r
= SendMessageA(hwnd
, LVM_GETHOVERTIME
, 0, 0);
5614 DestroyWindow(hwnd
);
5617 static void test_destroynotify(void)
5622 hwnd
= create_listview_control(LVS_REPORT
);
5623 ok(hwnd
!= NULL
, "failed to create listview window\n");
5625 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5626 DestroyWindow(hwnd
);
5627 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, listview_destroy
, "check destroy order", FALSE
);
5629 /* same for ownerdata list */
5630 hwnd
= create_listview_control(LVS_REPORT
|LVS_OWNERDATA
);
5631 ok(hwnd
!= NULL
, "failed to create listview window\n");
5633 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5634 DestroyWindow(hwnd
);
5635 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, listview_ownerdata_destroy
, "check destroy order, ownerdata", FALSE
);
5637 hwnd
= create_listview_control(LVS_REPORT
|LVS_OWNERDATA
);
5638 ok(hwnd
!= NULL
, "failed to create listview window\n");
5640 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5641 ret
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
5642 ok(ret
== TRUE
, "got %d\n", ret
);
5643 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, listview_ownerdata_deleteall
, "deleteall ownerdata", FALSE
);
5644 DestroyWindow(hwnd
);
5647 static void test_header_notification(void)
5649 static char textA
[] = "newtext";
5657 list
= create_listview_control(LVS_REPORT
);
5658 ok(list
!= NULL
, "failed to create listview window\n");
5660 memset(&col
, 0, sizeof(col
));
5661 col
.mask
= LVCF_WIDTH
;
5663 ret
= SendMessageA(list
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5666 /* check list parent notification after header item changed,
5667 this test should be placed before header subclassing to avoid
5668 Listview -> Header messages to be logged */
5669 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5671 col
.mask
= LVCF_TEXT
;
5672 col
.pszText
= textA
;
5673 r
= SendMessageA(list
, LVM_SETCOLUMNA
, 0, (LPARAM
)&col
);
5676 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_header_changed_seq
,
5677 "header notify, listview", FALSE
);
5678 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5679 "header notify, parent", FALSE
);
5681 header
= subclass_header(list
);
5683 ret
= SendMessageA(header
, HDM_GETITEMCOUNT
, 0, 0);
5686 memset(&item
, 0, sizeof(item
));
5687 item
.mask
= HDI_WIDTH
;
5688 ret
= SendMessageA(header
, HDM_GETITEMA
, 0, (LPARAM
)&item
);
5690 expect(100, item
.cxy
);
5692 nmh
.hdr
.hwndFrom
= header
;
5693 nmh
.hdr
.idFrom
= GetWindowLongPtrA(header
, GWLP_ID
);
5694 nmh
.hdr
.code
= HDN_ITEMCHANGEDA
;
5697 item
.mask
= HDI_WIDTH
;
5700 ret
= SendMessageA(list
, WM_NOTIFY
, 0, (LPARAM
)&nmh
);
5703 DestroyWindow(list
);
5706 static void test_header_notification2(void)
5708 static char textA
[] = "newtext";
5715 struct message parent_header_notify_seq
[] = {
5716 { WM_NOTIFY
, sent
|id
, 0, 0, 0 },
5720 list
= create_listview_control(LVS_REPORT
);
5721 ok(list
!= NULL
, "failed to create listview window\n");
5723 memset(&col
, 0, sizeof(col
));
5724 col
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
5726 col
.pszText
= textA
;
5727 ret
= SendMessageA(list
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5730 header
= (HWND
)SendMessageA(list
, LVM_GETHEADER
, 0, 0);
5731 ok(header
!= 0, "No header\n");
5732 memset(&itemW
, 0, sizeof(itemW
));
5733 itemW
.mask
= HDI_WIDTH
| HDI_ORDER
| HDI_TEXT
;
5734 itemW
.pszText
= buffer
;
5735 itemW
.cchTextMax
= ARRAY_SIZE(buffer
);
5736 ret
= SendMessageW(header
, HDM_GETITEMW
, 0, (LPARAM
)&itemW
);
5739 nmhdr
.hdr
.hwndFrom
= header
;
5740 nmhdr
.hdr
.idFrom
= GetWindowLongPtrW(header
, GWLP_ID
);
5743 nmhdr
.pitem
= &itemW
;
5745 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5746 nmhdr
.hdr
.code
= HDN_ITEMCHANGINGW
;
5747 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5748 ok(ret
== 0, "got %ld\n", ret
);
5749 parent_header_notify_seq
[0].id
= HDN_ITEMCHANGINGA
;
5750 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5751 "header notify, parent", TRUE
);
5753 ok(nmhdr
.hdr
.code
== HDN_ITEMCHANGINGA
, "Expected ANSI notification code\n");
5754 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5755 nmhdr
.hdr
.code
= HDN_ITEMCHANGEDW
;
5756 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5757 ok(ret
== 0, "got %ld\n", ret
);
5758 parent_header_notify_seq
[0].id
= HDN_ITEMCHANGEDA
;
5759 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5760 "header notify, parent", TRUE
);
5762 ok(nmhdr
.hdr
.code
== HDN_ITEMCHANGEDA
, "Expected ANSI notification code\n");
5763 /* HDN_ITEMCLICK sets focus to list, which generates messages we don't want to check */
5765 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5766 nmhdr
.hdr
.code
= HDN_ITEMCLICKW
;
5767 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5768 ok(ret
== 0, "got %ld\n", ret
);
5769 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_click_seq
,
5770 "header notify, parent", FALSE
);
5771 ok(nmhdr
.hdr
.code
== HDN_ITEMCLICKA
, "Expected ANSI notification code\n");
5772 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5773 nmhdr
.hdr
.code
= HDN_ITEMDBLCLICKW
;
5774 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5775 ok(ret
== 0, "got %ld\n", ret
);
5776 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5777 "header notify, parent", FALSE
);
5778 ok(nmhdr
.hdr
.code
== HDN_ITEMDBLCLICKW
, "Expected Unicode notification code\n");
5779 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5780 nmhdr
.hdr
.code
= HDN_DIVIDERDBLCLICKW
;
5781 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5782 ok(ret
== 0, "got %ld\n", ret
);
5783 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_divider_dclick_seq
,
5784 "header notify, parent", TRUE
);
5785 ok(nmhdr
.hdr
.code
== HDN_DIVIDERDBLCLICKA
, "Expected ANSI notification code\n");
5786 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5787 nmhdr
.hdr
.code
= HDN_BEGINTRACKW
;
5788 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5789 ok(ret
== 0, "got %ld\n", ret
);
5790 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5791 "header notify, parent", FALSE
);
5792 ok(nmhdr
.hdr
.code
== HDN_BEGINTRACKW
, "Expected Unicode notification code\n");
5793 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5794 nmhdr
.hdr
.code
= HDN_ENDTRACKW
;
5795 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5796 ok(ret
== 0, "got %ld\n", ret
);
5797 parent_header_notify_seq
[0].id
= HDN_ENDTRACKA
;
5798 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5799 "header notify, parent", FALSE
);
5800 ok(nmhdr
.hdr
.code
== HDN_ENDTRACKA
, "Expected ANSI notification code\n");
5801 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5802 nmhdr
.hdr
.code
= HDN_TRACKW
;
5803 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5804 ok(ret
== 0, "got %ld\n", ret
);
5805 parent_header_notify_seq
[0].id
= HDN_TRACKA
;
5806 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5807 "header notify, parent", FALSE
);
5808 ok(nmhdr
.hdr
.code
== HDN_TRACKA
, "Expected ANSI notification code\n");
5809 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5810 nmhdr
.hdr
.code
= HDN_BEGINDRAG
;
5811 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5812 ok(ret
== 1, "got %ld\n", ret
);
5813 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5814 "header notify, parent", FALSE
);
5815 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5816 nmhdr
.hdr
.code
= HDN_ENDDRAG
;
5817 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5818 ok(ret
== 0, "got %ld\n", ret
);
5819 parent_header_notify_seq
[0].id
= HDN_ENDDRAG
;
5820 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5821 "header notify, parent", FALSE
);
5822 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5823 nmhdr
.hdr
.code
= HDN_FILTERCHANGE
;
5824 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5825 ok(ret
== 0, "got %ld\n", ret
);
5826 parent_header_notify_seq
[0].id
= HDN_FILTERCHANGE
;
5827 parent_header_notify_seq
[0].flags
|= optional
; /* NT4 does not send this message */
5828 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5829 "header notify, parent", FALSE
);
5830 parent_header_notify_seq
[0].flags
&= ~optional
;
5831 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5832 nmhdr
.hdr
.code
= HDN_BEGINFILTEREDIT
;
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_ENDFILTEREDIT
;
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_ITEMSTATEICONCLICK
;
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
);
5849 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5850 nmhdr
.hdr
.code
= HDN_ITEMKEYDOWN
;
5851 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5852 ok(ret
== 0, "got %ld\n", ret
);
5853 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5854 "header notify, parent", FALSE
);
5856 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5858 DestroyWindow(list
);
5861 static void test_createdragimage(void)
5867 list
= create_listview_control(LVS_ICON
);
5868 ok(list
!= NULL
, "failed to create listview window\n");
5870 insert_item(list
, 0);
5873 himl
= (HIMAGELIST
)SendMessageA(list
, LVM_CREATEDRAGIMAGE
, 0, 0);
5874 ok(himl
== NULL
, "got %p\n", himl
);
5876 himl
= (HIMAGELIST
)SendMessageA(list
, LVM_CREATEDRAGIMAGE
, 0, (LPARAM
)&pt
);
5877 ok(himl
!= NULL
, "got %p\n", himl
);
5878 pImageList_Destroy(himl
);
5880 DestroyWindow(list
);
5883 static void test_dispinfo(void)
5885 static const char testA
[] = "TEST";
5891 hwnd
= create_listview_control(LVS_ICON
);
5892 ok(hwnd
!= NULL
, "failed to create listview window\n");
5894 insert_item(hwnd
, 0);
5896 memset(&item
, 0, sizeof(item
));
5897 item
.pszText
= LPSTR_TEXTCALLBACKA
;
5898 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
5901 g_disp_A_to_W
= TRUE
;
5902 item
.pszText
= (char*)buff
;
5903 item
.cchTextMax
= ARRAY_SIZE(buff
);
5904 ret
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
5905 ok(ret
== sizeof(testA
)-1, "got %ld, expected 4\n", ret
);
5906 g_disp_A_to_W
= FALSE
;
5908 ok(memcmp(item
.pszText
, testA
, sizeof(testA
)) == 0,
5909 "got %s, expected %s\n", item
.pszText
, testA
);
5911 DestroyWindow(hwnd
);
5914 static void test_LVM_SETITEMTEXT(void)
5916 static char testA
[] = "TEST";
5921 hwnd
= create_listview_control(LVS_ICON
);
5922 ok(hwnd
!= NULL
, "failed to create listview window\n");
5924 insert_item(hwnd
, 0);
5926 /* null item pointer */
5927 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, 0);
5930 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTW
, 0, 0);
5933 /* index out of bounds */
5934 item
.pszText
= testA
;
5935 item
.cchTextMax
= 0; /* ignored */
5938 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 1, (LPARAM
)&item
);
5941 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, -1, (LPARAM
)&item
);
5944 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
5947 DestroyWindow(hwnd
);
5950 static void test_LVM_REDRAWITEMS(void)
5955 list
= create_listview_control(LVS_ICON
);
5956 ok(list
!= NULL
, "failed to create listview window\n");
5958 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 0);
5961 insert_item(list
, 0);
5963 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, -1, 0);
5966 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, -1);
5969 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 0);
5972 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 1);
5975 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 2);
5978 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 1, 0);
5981 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 2, 3);
5984 DestroyWindow(list
);
5987 static void test_WM_PRINTCLIENT(void)
5989 static const int states
[] = {SW_HIDE
, SW_SHOW
};
5990 static const LPARAM params
[] = {0, PRF_CHECKVISIBLE
, PRF_NONCLIENT
, PRF_CLIENT
, PRF_ERASEBKGND
,
5991 PRF_CHILDREN
, PRF_OWNED
};
5992 const DWORD list_background
= RGB(255, 0, 0);
5993 const DWORD text_background
= RGB(0, 0, 255);
6001 hList
= create_listview_control(LVS_LIST
);
6002 insert_item(hList
, 0);
6004 ret
= SendMessageA(hList
, LVM_SETBKCOLOR
, 0, list_background
);
6005 ok(ret
== TRUE
, "got 0x%lx, expected 0x%x\n", ret
, TRUE
);
6007 ret
= SendMessageA(hList
, LVM_SETTEXTBKCOLOR
, 0, text_background
);
6008 ok(ret
== TRUE
, "got 0x%lx, expected 0x%x\n", ret
, TRUE
);
6010 hdc
= GetDC(hwndparent
);
6011 GetClientRect(hwndparent
, &rc
);
6013 for (i
= 0; i
< ARRAY_SIZE(states
); i
++)
6015 ShowWindow(hList
, states
[i
]);
6017 for (j
= 0; j
< ARRAY_SIZE(params
); j
++)
6019 winetest_push_context("state=%d lParam=0x%Ix", states
[i
], params
[j
]);
6021 FillRect(hdc
, &rc
, GetStockObject(BLACK_BRUSH
));
6022 clr
= GetPixel(hdc
, 1, 1);
6023 ok(clr
== RGB(0, 0, 0), "got 0x%lx\n", clr
);
6024 clr
= GetPixel(hdc
, 50, 1);
6025 ok(clr
== RGB(0, 0, 0), "got 0x%lx\n", clr
);
6026 ret
= SendMessageA(hList
, WM_PRINTCLIENT
, (WPARAM
)hdc
, params
[j
]);
6027 ok(ret
== 0, "got %ld\n", ret
);
6028 clr
= GetPixel(hdc
, 1, 1);
6029 ok(clr
== text_background
, "got 0x%lx\n", clr
);
6030 clr
= GetPixel(hdc
, 50, 1);
6031 ok(clr
== RGB(0, 0, 0), "got 0x%lx\n", clr
);
6033 winetest_pop_context();
6037 ReleaseDC(hwndparent
, hdc
);
6038 DestroyWindow(hList
);
6041 static void test_imagelists(void)
6044 HIMAGELIST himl1
, himl2
, himl3
;
6047 himl1
= pImageList_Create(40, 40, 0, 4, 4);
6048 himl2
= pImageList_Create(40, 40, 0, 4, 4);
6049 himl3
= pImageList_Create(40, 40, 0, 4, 4);
6050 ok(himl1
!= NULL
, "Failed to create imagelist\n");
6051 ok(himl2
!= NULL
, "Failed to create imagelist\n");
6052 ok(himl3
!= NULL
, "Failed to create imagelist\n");
6054 hwnd
= create_listview_control(LVS_REPORT
| LVS_SHAREIMAGELISTS
);
6055 header
= subclass_header(hwnd
);
6057 ok(header
!= NULL
, "Expected header\n");
6058 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
6059 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6061 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6063 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl1
);
6064 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6065 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6066 "set normal image list", FALSE
);
6068 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6070 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl2
);
6071 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6072 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6073 "set state image list", TRUE
);
6075 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
6076 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6078 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6080 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl3
);
6081 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6082 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_header_set_imagelist
,
6083 "set small image list", FALSE
);
6085 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
6086 ok((HIMAGELIST
)ret
== himl3
, "Expected imagelist %p, got %p\n", himl3
, (HIMAGELIST
)ret
);
6087 DestroyWindow(hwnd
);
6089 hwnd
= create_listview_control(WS_VISIBLE
| LVS_ICON
);
6091 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6093 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl1
);
6094 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6095 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6096 "set normal image list", FALSE
);
6098 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6100 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl2
);
6101 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6102 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6103 "set state image list", FALSE
);
6105 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6107 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl3
);
6108 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
6109 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
6110 "set small image list", FALSE
);
6112 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
6113 ok(header
== NULL
, "Expected no header, got %p\n", header
);
6115 SetWindowLongPtrA(hwnd
, GWL_STYLE
, GetWindowLongPtrA(hwnd
, GWL_STYLE
) | LVS_REPORT
);
6117 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
6118 ok(header
!= NULL
, "Expected header, got NULL\n");
6120 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
6121 ok((HIMAGELIST
)ret
== himl3
, "Expected imagelist %p, got %p\n", himl3
, (HIMAGELIST
)ret
);
6123 DestroyWindow(hwnd
);
6126 static void test_deleteitem(void)
6133 hwnd
= create_listview_control(LVS_REPORT
);
6135 insert_item(hwnd
, 0);
6136 insert_item(hwnd
, 0);
6137 insert_item(hwnd
, 0);
6138 insert_item(hwnd
, 0);
6139 insert_item(hwnd
, 0);
6141 g_focus_test_LVN_DELETEITEM
= TRUE
;
6143 /* delete focused item (not the last index) */
6144 item
.stateMask
= LVIS_FOCUSED
;
6145 item
.state
= LVIS_FOCUSED
;
6146 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 2, (LPARAM
)&item
);
6147 ok(ret
== TRUE
, "got %d\n", ret
);
6148 ret
= SendMessageA(hwnd
, LVM_DELETEITEM
, 2, 0);
6149 ok(ret
== TRUE
, "got %d\n", ret
);
6150 /* next item gets focus */
6151 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_FOCUSED
);
6152 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6154 /* focus last item and delete it */
6155 item
.stateMask
= LVIS_FOCUSED
;
6156 item
.state
= LVIS_FOCUSED
;
6157 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 3, (LPARAM
)&item
);
6158 ok(ret
== TRUE
, "got %d\n", ret
);
6159 ret
= SendMessageA(hwnd
, LVM_DELETEITEM
, 3, 0);
6160 ok(ret
== TRUE
, "got %d\n", ret
);
6161 /* new last item gets focus */
6162 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_FOCUSED
);
6163 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6165 /* focus first item and delete it */
6166 item
.stateMask
= LVIS_FOCUSED
;
6167 item
.state
= LVIS_FOCUSED
;
6168 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6169 ok(ret
== TRUE
, "got %d\n", ret
);
6170 ret
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
6171 ok(ret
== TRUE
, "got %d\n", ret
);
6172 /* new first item gets focus */
6173 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_FOCUSED
);
6174 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6176 g_focus_test_LVN_DELETEITEM
= FALSE
;
6178 DestroyWindow(hwnd
);
6181 static const struct message parent_insert_focused0_seq
[] = {
6182 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 0, LVIF_STATE
, LVN_ITEMCHANGING
},
6183 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 0, LVIF_STATE
, LVN_ITEMCHANGED
},
6184 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_INSERTITEM
},
6188 static const struct message parent_insert_focused1_seq
[] = {
6189 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 1, LVIF_STATE
, LVN_ITEMCHANGING
},
6190 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 0, LVIF_STATE
, LVN_ITEMCHANGING
},
6191 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 0, LVIF_STATE
, LVN_ITEMCHANGED
},
6192 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 1, LVIF_STATE
, LVN_ITEMCHANGED
},
6193 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_INSERTITEM
},
6197 static const struct message parent_insert_item_seq
[] = {
6198 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_INSERTITEM
},
6202 static const struct message parent_insert_selected_seq
[] = {
6203 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 3, LVIF_STATE
, LVN_ITEMCHANGING
},
6204 { WM_NOTIFY
, sent
|id
|wparam
|lparam
, 3, LVIF_STATE
, LVN_ITEMCHANGED
},
6205 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_INSERTITEM
},
6209 #define LVIS_ALL (LVIS_FOCUSED | LVIS_SELECTED | LVIS_CUT | LVIS_DROPHILITED | LVIS_ACTIVATING)
6211 static void test_LVM_INSERTITEM(void)
6215 UINT mask
, state
, stateMask
;
6218 { LVIF_STATE
, LVIS_FOCUSED
, LVIS_FOCUSED
},
6219 { LVIF_STATE
, LVIS_FOCUSED
, 0 },
6220 { LVIF_STATE
, 0, LVIS_FOCUSED
},
6222 { LVIF_STATE
, LVIS_SELECTED
, LVIS_SELECTED
},
6223 { LVIF_STATE
, LVIS_SELECTED
, 0 },
6224 { LVIF_STATE
, 0, LVIS_SELECTED
},
6226 { LVIF_STATE
, LVIS_FOCUSED
| LVIS_SELECTED
, LVIS_FOCUSED
| LVIS_SELECTED
},
6227 { LVIF_STATE
, LVIS_FOCUSED
| LVIS_SELECTED
, 0 },
6228 { LVIF_STATE
, 0, LVIS_FOCUSED
| LVIS_SELECTED
},
6230 { LVIF_STATE
, LVIS_FOCUSED
, LVIS_ALL
},
6231 { LVIF_STATE
, LVIS_SELECTED
, LVIS_ALL
},
6232 { LVIF_STATE
, LVIS_CUT
, LVIS_ALL
},
6233 { LVIF_STATE
, LVIS_DROPHILITED
, LVIS_ALL
},
6234 { LVIF_STATE
, LVIS_ACTIVATING
, LVIS_ALL
},
6236 { LVIF_STATE
, LVIS_ALL
, LVIS_ALL
},
6237 { LVIF_STATE
, LVIS_ALL
, 0 },
6238 { LVIF_STATE
, 0, LVIS_ALL
},
6240 { LVIF_STATE
| LVIF_PARAM
, 0, 0 },
6241 { LVIF_STATE
| LVIF_PARAM
, LVIS_FOCUSED
, LVIS_FOCUSED
},
6242 { LVIF_STATE
| LVIF_PARAM
, LVIS_FOCUSED
, 0 },
6243 { LVIF_STATE
| LVIF_PARAM
, 0, LVIS_FOCUSED
},
6245 { LVIF_STATE
| LVIF_PARAM
, LVIS_SELECTED
, LVIS_SELECTED
},
6246 { LVIF_STATE
| LVIF_PARAM
, LVIS_SELECTED
, 0 },
6247 { LVIF_STATE
| LVIF_PARAM
, 0, LVIS_SELECTED
},
6249 { LVIF_STATE
, 0, 0 },
6250 { LVIF_PARAM
, 0, 0 },
6252 { LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, 0 },
6253 { LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_FOCUSED
, LVIS_FOCUSED
},
6254 { LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_FOCUSED
, 0 },
6255 { LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, LVIS_FOCUSED
},
6257 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, 0 },
6258 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_FOCUSED
, LVIS_FOCUSED
},
6259 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_FOCUSED
, 0 },
6260 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, LVIS_FOCUSED
},
6262 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, 0 },
6263 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_ALL
, LVIS_ALL
},
6264 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, LVIS_ALL
, 0 },
6265 { LVIF_STATE
| LVIF_PARAM
| LVIF_TEXT
| LVIF_IMAGE
, 0, LVIS_ALL
},
6273 for (i
= 0; i
< ARRAYSIZE(insert_item
); i
++)
6275 hwnd
= create_listview_control(LVS_REPORT
);
6277 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6279 item
.mask
= insert_item
[i
].mask
;
6280 item
.state
= insert_item
[i
].state
;
6281 item
.stateMask
= insert_item
[i
].stateMask
;
6282 item
.pszText
= (LPSTR
)"Hello World!";
6283 item
.iImage
= I_IMAGECALLBACK
;
6286 item
.lParam
= 0xdeadbeef;
6287 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6288 ok(ret
== 0, "%d: got %d\n", i
, ret
);
6290 if ((insert_item
[i
].mask
& LVIF_STATE
) && (insert_item
[i
].state
& (LVIS_FOCUSED
| LVIS_SELECTED
)))
6292 sprintf(buf
, "%d: insert focused", i
);
6293 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_focused0_seq
, buf
, FALSE
);
6297 sprintf(buf
, "%d: insert item", i
);
6298 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_item_seq
, buf
, FALSE
);
6301 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_ALL
);
6302 if ((insert_item
[i
].mask
& LVIF_STATE
) && insert_item
[i
].state
)
6303 ok(state
== insert_item
[i
].state
, "%d: expected %#x, got %#x\n", i
, insert_item
[i
].state
, state
);
6305 ok(state
== 0, "%d: expected 0, got %#x\n", i
, state
);
6307 DestroyWindow(hwnd
);
6311 static void test_insertitem(void)
6318 hwnd
= create_listview_control(LVS_REPORT
);
6320 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6322 /* insert item 0 focused */
6323 item
.mask
= LVIF_STATE
;
6324 item
.state
= LVIS_FOCUSED
;
6325 item
.stateMask
= LVIS_FOCUSED
;
6328 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6329 ok(ret
== 0, "got %d\n", ret
);
6330 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_focused0_seq
, "insert focused 0", FALSE
);
6332 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_FOCUSED
);
6333 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6335 /* insert item 1, focus shift */
6336 item
.mask
= LVIF_STATE
;
6337 item
.state
= LVIS_FOCUSED
;
6338 item
.stateMask
= LVIS_FOCUSED
;
6341 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6342 ok(ret
== 1, "got %d\n", ret
);
6343 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_focused1_seq
, "insert focused 1", FALSE
);
6345 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_FOCUSED
);
6346 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6348 /* insert item 2, no focus shift */
6349 item
.mask
= LVIF_STATE
;
6351 item
.stateMask
= LVIS_FOCUSED
;
6354 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6355 ok(ret
== 2, "got %d\n", ret
);
6356 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_item_seq
, "insert focused 2", FALSE
);
6358 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_FOCUSED
);
6359 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
6362 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
6363 item
.state
= LVIS_SELECTED
;
6364 item
.stateMask
= LVIS_SELECTED
;
6367 item
.lParam
= 0xdeadbeef;
6368 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6369 ok(ret
== 3, "got %d\n", ret
);
6370 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_selected_seq
, "insert selected", FALSE
);
6373 item
.mask
= LVIF_PARAM
;
6378 item
.lParam
= 0xdeadbeef;
6379 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6380 ok(ret
== 4, "got %d\n", ret
);
6381 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_item_seq
, "insert param", FALSE
);
6384 item
.mask
= LVIF_STATE
;
6389 item
.lParam
= 0xdeadbeef;
6390 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6391 ok(ret
== 5, "got %d\n", ret
);
6392 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_item_seq
, "insert state", FALSE
);
6394 DestroyWindow(hwnd
);
6397 static void test_header_proc(void)
6399 HWND hwnd
, header
, hdr
;
6400 WNDPROC proc1
, proc2
;
6402 hwnd
= create_listview_control(LVS_REPORT
);
6404 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
6405 ok(header
!= NULL
, "got %p\n", header
);
6407 hdr
= CreateWindowExA(0, WC_HEADERA
, NULL
,
6408 WS_BORDER
|WS_VISIBLE
|HDS_BUTTONS
|HDS_HORZ
,
6410 NULL
, NULL
, NULL
, NULL
);
6411 ok(hdr
!= NULL
, "got %p\n", hdr
);
6413 proc1
= (WNDPROC
)GetWindowLongPtrW(header
, GWLP_WNDPROC
);
6414 proc2
= (WNDPROC
)GetWindowLongPtrW(hdr
, GWLP_WNDPROC
);
6415 ok(proc1
== proc2
, "got %p, expected %p\n", proc1
, proc2
);
6418 DestroyWindow(hwnd
);
6421 static void flush_events(void)
6425 int min_timeout
= 100;
6426 DWORD time
= GetTickCount() + diff
;
6430 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
6431 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
6432 diff
= time
- GetTickCount();
6436 static void test_oneclickactivate(void)
6438 TRACKMOUSEEVENT track
;
6439 char item1
[] = "item1";
6446 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo", WS_VISIBLE
|WS_CHILD
|LVS_LIST
,
6447 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
6448 ok(hwnd
!= NULL
, "failed to create listview window\n");
6449 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_ONECLICKACTIVATE
);
6450 ok(r
== 0, "should return zero\n");
6452 SetForegroundWindow(hwndparent
);
6454 fg
= GetForegroundWindow();
6455 if (fg
!= hwndparent
)
6457 skip("Window is not in the foreground. Skipping oneclickactivate tests.\n");
6458 DestroyWindow(hwnd
);
6462 item
.mask
= LVIF_TEXT
;
6466 item
.pszText
= item1
;
6467 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
6468 ok(r
== 0, "should not fail\n");
6470 GetWindowRect(hwnd
, &rect
);
6471 GetCursorPos(&orig_pos
);
6472 SetCursorPos(rect
.left
+5, rect
.top
+5);
6474 r
= SendMessageA(hwnd
, WM_MOUSEMOVE
, MAKELONG(1, 1), 0);
6477 track
.cbSize
= sizeof(track
);
6478 track
.dwFlags
= TME_QUERY
;
6479 p_TrackMouseEvent(&track
);
6480 ok(track
.hwndTrack
== hwnd
, "hwndTrack != hwnd\n");
6481 ok(track
.dwFlags
== TME_LEAVE
, "dwFlags = %lx\n", track
.dwFlags
);
6483 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
6485 r
= SendMessageA(hwnd
, WM_MOUSEHOVER
, MAKELONG(1, 1), 0);
6487 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
6490 DestroyWindow(hwnd
);
6491 SetCursorPos(orig_pos
.x
, orig_pos
.y
);
6494 static void test_callback_mask(void)
6501 hwnd
= create_listview_control(LVS_REPORT
);
6503 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, ~0u, 0);
6504 ok(ret
, "got %d\n", ret
);
6506 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, ~0u, 1);
6507 ok(ret
, "got %d\n", ret
);
6509 mask
= SendMessageA(hwnd
, LVM_GETCALLBACKMASK
, 0, 0);
6510 ok(mask
== ~0u, "got 0x%08lx\n", mask
);
6512 /* Ask for state, invalid subitem. */
6513 insert_item(hwnd
, 0);
6515 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_FOCUSED
, 0);
6516 ok(ret
, "Failed to set callback mask.\n");
6518 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6520 memset(&item
, 0, sizeof(item
));
6522 item
.mask
= LVIF_STATE
;
6523 item
.stateMask
= LVIS_SELECTED
;
6524 ret
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6525 ok(ret
, "Failed to get item data.\n");
6527 memset(&item
, 0, sizeof(item
));
6528 item
.mask
= LVIF_STATE
;
6529 item
.stateMask
= LVIS_SELECTED
;
6530 ret
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6531 ok(ret
, "Failed to get item data.\n");
6533 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "parent seq, callback mask/invalid subitem 1", TRUE
);
6535 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6537 memset(&item
, 0, sizeof(item
));
6538 memset(&g_itema
, 0, sizeof(g_itema
));
6540 item
.mask
= LVIF_STATE
;
6541 item
.stateMask
= LVIS_FOCUSED
| LVIS_SELECTED
;
6542 ret
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6543 ok(ret
, "Failed to get item data.\n");
6544 ok(g_itema
.iSubItem
== 1, "Unexpected LVN_DISPINFO subitem %d.\n", g_itema
.iSubItem
);
6545 ok(g_itema
.stateMask
== LVIS_FOCUSED
, "Unexpected state mask %#x.\n", g_itema
.stateMask
);
6547 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
6548 "parent seq, callback mask/invalid subitem 2", FALSE
);
6550 DestroyWindow(hwnd
);
6552 /* LVS_OWNERDATA, mask LVIS_FOCUSED */
6553 hwnd
= create_listview_control(LVS_REPORT
| LVS_OWNERDATA
);
6555 mask
= SendMessageA(hwnd
, LVM_GETCALLBACKMASK
, 0, 0);
6556 ok(mask
== 0, "Unexpected callback mask %#lx.\n", mask
);
6558 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_FOCUSED
, 0);
6559 ok(ret
, "Failed to set callback mask, %d\n", ret
);
6561 mask
= SendMessageA(hwnd
, LVM_GETCALLBACKMASK
, 0, 0);
6562 ok(mask
== LVIS_FOCUSED
, "Unexpected callback mask %#lx.\n", mask
);
6564 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6565 ok(ret
, "Failed to set item count.\n");
6567 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6568 ok(ret
== -1, "Unexpected selection mark, %d\n", ret
);
6570 item
.stateMask
= LVIS_FOCUSED
;
6571 item
.state
= LVIS_FOCUSED
;
6572 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6573 ok(ret
, "Failed to set item state.\n");
6575 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6577 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6579 ok(ret
== 0, "Unexpected focused item, ret %d\n", ret
);
6581 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6583 ok(ret
== 0, "Unexpected selection mark, %d\n", ret
);
6585 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 0, 0);
6586 ok(ret
, "Failed to set item count.\n");
6588 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6589 ok(ret
== -1, "Unexpected focused item, ret %d\n", ret
);
6591 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6592 ok(ret
== -1, "Unexpected selection mark, %d\n", ret
);
6594 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6595 ok(ret
, "Failed to set item count.\n");
6597 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6598 ok(ret
== -1, "Unexpected focused item, ret %d\n", ret
);
6600 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "parent seq, owner data/focus 1", FALSE
);
6602 /* LVS_OWNDERDATA, empty mask */
6603 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, 0, 0);
6604 ok(ret
, "Failed to set callback mask, %d\n", ret
);
6606 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6607 ok(ret
, "Failed to set item count.\n");
6609 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6610 ok(ret
== -1, "Unexpected selection mark, %d\n", ret
);
6612 item
.stateMask
= LVIS_FOCUSED
;
6613 item
.state
= LVIS_FOCUSED
;
6614 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6615 ok(ret
, "Failed to set item state.\n");
6617 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6618 ok(ret
== 0, "Unexpected selection mark, %d\n", ret
);
6620 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6622 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6623 ok(ret
== 0, "Unexpected focused item, ret %d\n", ret
);
6625 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 0, 0);
6626 ok(ret
, "Failed to set item count.\n");
6628 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6629 ok(ret
== -1, "Unexpected focused item, ret %d\n", ret
);
6631 ret
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
6633 ok(ret
== -1, "Unexpected selection mark, %d\n", ret
);
6635 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6636 ok(ret
, "Failed to set item count.\n");
6638 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6639 ok(ret
== -1, "Unexpected focused item, ret %d\n", ret
);
6641 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "parent seq, owner data/focus 2", FALSE
);
6643 /* 2 items, focus on index 0, reduce to 1 item. */
6644 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6646 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 2, 0);
6647 ok(ret
, "Failed to set item count.\n");
6649 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6650 ok(ret
, "Failed to set item state.\n");
6652 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6653 ok(ret
== 0, "Unexpected focused item, ret %d\n", ret
);
6655 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
6656 ok(ret
, "Failed to set item count.\n");
6658 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
6659 ok(ret
== 0, "Unexpected focused item, ret %d\n", ret
);
6661 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_focus_change_ownerdata_seq
,
6662 "parent seq, owner data/focus 3", TRUE
);
6664 DestroyWindow(hwnd
);
6667 static void test_state_image(void)
6669 static const DWORD styles
[] =
6678 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
6680 static char text
[] = "Item";
6681 static char subtext
[] = "Subitem";
6687 hwnd
= create_listview_control(styles
[i
]);
6689 insert_column(hwnd
, 0);
6690 insert_column(hwnd
, 1);
6692 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
6695 item
.pszText
= text
;
6696 item
.lParam
= 123456;
6697 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6698 ok(r
== 0, "Failed to insert an item.\n");
6700 item
.mask
= LVIF_STATE
;
6701 item
.state
= INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED
| LVIS_FOCUSED
;
6702 item
.stateMask
= LVIS_STATEIMAGEMASK
| LVIS_SELECTED
| LVIS_FOCUSED
;
6705 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
6706 ok(r
, "Failed to set item state.\n");
6708 item
.mask
= LVIF_TEXT
;
6711 item
.pszText
= subtext
;
6712 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
6713 ok(r
, "Failed to set subitem text.\n");
6715 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
6716 item
.stateMask
= ~0u;
6721 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6722 ok(r
, "Failed to get item state.\n");
6723 ok(item
.state
== (INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED
| LVIS_FOCUSED
),
6724 "Unexpected item state %#x.\n", item
.state
);
6725 ok(item
.lParam
== 123456, "Unexpected lParam %Id.\n", item
.lParam
);
6728 item
.stateMask
= ~0u;
6729 item
.state
= INDEXTOSTATEIMAGEMASK(2);
6732 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6733 ok(r
, "Failed to get subitem state.\n");
6734 ok(item
.state
== INDEXTOSTATEIMAGEMASK(2), "Unexpected state %#x.\n", item
.state
);
6736 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
6737 item
.stateMask
= ~0u;
6738 item
.state
= INDEXTOSTATEIMAGEMASK(2);
6742 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6743 ok(r
, "Failed to get subitem state.\n");
6744 ok(item
.state
== 0, "Unexpected state %#x.\n", item
.state
);
6745 ok(item
.lParam
== 123456, "Unexpected lParam %Id.\n", item
.lParam
);
6747 item
.mask
= LVIF_STATE
;
6748 item
.stateMask
= LVIS_FOCUSED
;
6752 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6753 ok(r
, "Failed to get subitem state.\n");
6754 ok(item
.state
== 0, "Unexpected state %#x.\n", item
.state
);
6756 item
.mask
= LVIF_STATE
;
6757 item
.stateMask
= ~0u;
6758 item
.state
= INDEXTOSTATEIMAGEMASK(2);
6761 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6762 ok(r
, "Failed to get subitem state.\n");
6763 ok(item
.state
== 0, "Unexpected state %#x.\n", item
.state
);
6765 item
.mask
= LVIF_TEXT
;
6768 item
.pszText
= buff
;
6769 item
.cchTextMax
= sizeof(buff
);
6770 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
6771 ok(r
, "Failed to get subitem text %d.\n", r
);
6772 ok(!strcmp(buff
, subtext
), "Unexpected subitem text %s.\n", buff
);
6774 DestroyWindow(hwnd
);
6778 static void test_LVSCW_AUTOSIZE(void)
6784 hwnd
= create_listview_control(LVS_REPORT
);
6785 ok(hwnd
!= NULL
, "failed to create a listview window\n");
6787 insert_column(hwnd
, 0);
6788 insert_column(hwnd
, 1);
6789 insert_item(hwnd
, 0);
6791 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
6792 ok(ret
, "Failed to set column width.\n");
6794 width
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
6795 ok(width
> 0, "Unexpected column width %d.\n", width
);
6797 /* Turn on checkboxes. */
6798 ret
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
6799 ok(ret
== 0, "Unexpected previous extended style.\n");
6801 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
6802 ok(ret
, "Failed to set column width.\n");
6804 width2
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
6805 ok(width2
> 0, "Unexpected column width %d.\n", width2
);
6806 ok(width2
> width
, "Expected increased column width.\n");
6808 /* Turn off checkboxes. */
6809 ret
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
6810 ok(ret
== LVS_EX_CHECKBOXES
, "Unexpected previous extended style.\n");
6812 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
6813 ok(ret
, "Failed to set column width.\n");
6815 width
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
6816 ok(width
> 0, "Unexpected column width %d.\n", width2
);
6817 ok(width2
> width
, "Expected reduced column width.\n");
6819 DestroyWindow(hwnd
);
6822 static void test_LVN_ENDLABELEDIT(void)
6824 WCHAR text
[] = {'l','a','l','a',0};
6825 HWND hwnd
, hwndedit
;
6829 hwnd
= create_listview_control(LVS_REPORT
| LVS_EDITLABELS
);
6831 insert_column(hwnd
, 0);
6833 item
.mask
= LVIF_TEXT
;
6834 item
.pszText
= text
;
6835 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6837 /* Test normal editing */
6839 hwndedit
= (HWND
)SendMessageW(hwnd
, LVM_EDITLABELW
, 0, 0);
6840 ok(hwndedit
!= NULL
, "Failed to get edit control.\n");
6842 ret
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)"test");
6843 ok(ret
, "Failed to set edit text.\n");
6845 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6847 ret
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_RETURN
, 0);
6848 ok_sequence(sequences
, PARENT_SEQ_INDEX
, listview_end_label_edit
, "Label edit", FALSE
);
6850 /* Test editing with kill focus */
6852 hwndedit
= (HWND
)SendMessageW(hwnd
, LVM_EDITLABELW
, 0, 0);
6853 ok(hwndedit
!= NULL
, "Failed to get edit control.\n");
6855 ret
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)"test2");
6856 ok(ret
, "Failed to set edit text.\n");
6858 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6860 g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT
= TRUE
;
6861 ret
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_RETURN
, 0);
6862 g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT
= FALSE
;
6864 ok_sequence(sequences
, PARENT_SEQ_INDEX
, listview_end_label_edit_kill_focus
,
6865 "Label edit, kill focus", FALSE
);
6866 ok(GetFocus() == hwnd
, "Unexpected focused window.\n");
6868 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
6870 DestroyWindow(hwnd
);
6873 static LRESULT CALLBACK
create_item_height_wndproc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
6875 if (msg
== WM_CREATE
)
6878 return CallWindowProcA(listviewWndProc
, hwnd
, msg
, wParam
, lParam
);
6881 static void test_LVM_GETCOUNTPERPAGE(void)
6883 static const DWORD styles
[] = { LVS_ICON
, LVS_LIST
, LVS_REPORT
, LVS_SMALLICON
};
6890 cls
.cbSize
= sizeof(WNDCLASSEXA
);
6891 ret
= GetClassInfoExA(GetModuleHandleA(NULL
), WC_LISTVIEWA
, &cls
);
6892 ok(ret
, "Failed to get class info.\n");
6893 listviewWndProc
= cls
.lpfnWndProc
;
6894 cls
.lpfnWndProc
= create_item_height_wndproc
;
6895 cls
.lpszClassName
= "CountPerPageClass";
6896 class = RegisterClassExA(&cls
);
6897 ok(class, "Failed to register class.\n");
6899 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
6901 static char text
[] = "item text";
6902 LVITEMA item
= { 0 };
6905 hwnd
= create_listview_control(styles
[i
]);
6906 ok(hwnd
!= NULL
, "Failed to create listview window.\n");
6908 count
= SendMessageA(hwnd
, LVM_GETCOUNTPERPAGE
, 0, 0);
6909 if (styles
[i
] == LVS_LIST
|| styles
[i
] == LVS_REPORT
)
6910 ok(count
> 0 || broken(styles
[i
] == LVS_LIST
&& count
== 0), "%u: unexpected count %u.\n", i
, count
);
6912 ok(count
== 0, "%u: unexpected count %u.\n", i
, count
);
6914 for (j
= 0; j
< 10; j
++)
6916 item
.mask
= LVIF_TEXT
;
6917 item
.pszText
= text
;
6918 SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
6921 count2
= SendMessageA(hwnd
, LVM_GETCOUNTPERPAGE
, 0, 0);
6922 if (styles
[i
] == LVS_LIST
|| styles
[i
] == LVS_REPORT
)
6923 ok(count
== count2
, "%u: unexpected count %u.\n", i
, count2
);
6925 ok(count2
== 10, "%u: unexpected count %u.\n", i
, count2
);
6927 DestroyWindow(hwnd
);
6929 hwnd
= CreateWindowA("CountPerPageClass", "Test", WS_VISIBLE
| styles
[i
], 0, 0, 100, 100, NULL
, NULL
,
6930 GetModuleHandleA(NULL
), 0);
6931 ok(hwnd
!= NULL
, "Failed to create a window.\n");
6933 count
= SendMessageA(hwnd
, LVM_GETCOUNTPERPAGE
, 0, 0);
6934 ok(count
== 0, "%u: unexpected count %u.\n", i
, count
);
6936 DestroyWindow(hwnd
);
6939 ret
= UnregisterClassA("CountPerPageClass", NULL
);
6940 ok(ret
, "Failed to unregister test class.\n");
6943 static void test_item_state_change(void)
6945 static const DWORD styles
[] = { LVS_ICON
, LVS_LIST
, LVS_REPORT
, LVS_SMALLICON
};
6951 for (i
= 0; i
< ARRAY_SIZE(styles
); i
++)
6953 hwnd
= create_listview_control(styles
[i
]);
6955 insert_item(hwnd
, 0);
6957 /* LVM_SETITEMSTATE with mask */
6958 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
6959 memset(&item
, 0, sizeof(item
));
6960 item
.mask
= LVIF_STATE
;
6961 item
.stateMask
= LVIS_SELECTED
;
6962 item
.state
= LVIS_SELECTED
;
6963 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6964 ok(res
, "Failed to set item state.\n");
6966 ok(g_nmlistview
.iItem
== item
.iItem
, "Unexpected item %d.\n", g_nmlistview
.iItem
);
6967 ok(g_nmlistview
.iSubItem
== item
.iSubItem
, "Unexpected subitem %d.\n", g_nmlistview
.iSubItem
);
6968 ok(g_nmlistview
.lParam
== item
.lParam
, "Unexpected lParam.\n");
6969 ok(g_nmlistview
.uNewState
== LVIS_SELECTED
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
6970 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
6971 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
6973 /* LVM_SETITEMSTATE 0 mask */
6974 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
6975 memset(&item
, 0, sizeof(item
));
6976 item
.stateMask
= LVIS_SELECTED
;
6978 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
6979 ok(res
, "Failed to set item state.\n");
6981 ok(g_nmlistview
.iItem
== item
.iItem
, "Unexpected item %d.\n", g_nmlistview
.iItem
);
6982 ok(g_nmlistview
.iSubItem
== item
.iSubItem
, "Unexpected subitem %d.\n", g_nmlistview
.iSubItem
);
6983 ok(g_nmlistview
.lParam
== item
.lParam
, "Unexpected lParam.\n");
6984 ok(g_nmlistview
.uNewState
== 0, "Unexpected new state %#x.\n", g_nmlistview
.uNewState
);
6985 ok(g_nmlistview
.uOldState
== LVIS_SELECTED
, "Unexpected old state %#x.\n", g_nmlistview
.uOldState
);
6986 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "Unexpected change mask %#x.\n", g_nmlistview
.uChanged
);
6988 /* LVM_SETITEM changes state */
6989 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
6990 memset(&item
, 0, sizeof(item
));
6991 item
.stateMask
= LVIS_SELECTED
;
6992 item
.state
= LVIS_SELECTED
;
6993 item
.mask
= LVIF_STATE
;
6994 res
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
6995 ok(res
, "Failed to set item.\n");
6997 ok(g_nmlistview
.iItem
== item
.iItem
, "Unexpected item %d.\n", g_nmlistview
.iItem
);
6998 ok(g_nmlistview
.iSubItem
== item
.iSubItem
, "Unexpected subitem %d.\n", g_nmlistview
.iSubItem
);
6999 ok(g_nmlistview
.lParam
== item
.lParam
, "Unexpected lParam.\n");
7000 ok(g_nmlistview
.uNewState
== LVIS_SELECTED
, "Unexpected new state %#x.\n", g_nmlistview
.uNewState
);
7001 ok(g_nmlistview
.uOldState
== 0, "Unexpected old state %#x.\n", g_nmlistview
.uOldState
);
7002 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "Unexpected change mask %#x.\n", g_nmlistview
.uChanged
);
7004 /* LVM_SETITEM no state changes */
7005 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
7006 memset(&item
, 0, sizeof(item
));
7008 item
.mask
= LVIF_PARAM
;
7009 res
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
7010 ok(res
, "Failed to set item.\n");
7012 ok(g_nmlistview
.iItem
== item
.iItem
, "Unexpected item %d.\n", g_nmlistview
.iItem
);
7013 ok(g_nmlistview
.iSubItem
== item
.iSubItem
, "Unexpected subitem %d.\n", g_nmlistview
.iSubItem
);
7014 ok(g_nmlistview
.lParam
== item
.lParam
, "Unexpected lParam.\n");
7015 ok(g_nmlistview
.uNewState
== 0, "Unexpected new state %#x.\n", g_nmlistview
.uNewState
);
7016 ok(g_nmlistview
.uOldState
== 0, "Unexpected old state %#x.\n", g_nmlistview
.uOldState
);
7017 ok(g_nmlistview
.uChanged
== LVIF_PARAM
, "Unexpected change mask %#x.\n", g_nmlistview
.uChanged
);
7019 DestroyWindow(hwnd
);
7023 static void test_selected_column(void)
7025 static const DWORD styles
[] = { LVS_ICON
, LVS_LIST
, LVS_REPORT
, LVS_SMALLICON
};
7029 for (i
= 0; i
< ARRAY_SIZE(styles
); ++i
)
7031 hwnd
= create_listview_control(styles
[i
]);
7034 ret
= SendMessageA(hwnd
, LVM_GETSELECTEDCOLUMN
, 0, 0);
7035 ok(ret
== -1, "Unexpected column %d.\n", ret
);
7037 ret
= SendMessageA(hwnd
, LVM_SETSELECTEDCOLUMN
, -100, 0);
7038 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
7040 ret
= SendMessageA(hwnd
, LVM_GETSELECTEDCOLUMN
, 0, 0);
7041 ok(ret
== -100, "Unexpected column %d.\n", ret
);
7043 ret
= SendMessageA(hwnd
, LVM_SETSELECTEDCOLUMN
, 100, 0);
7044 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
7046 ret
= SendMessageA(hwnd
, LVM_GETSELECTEDCOLUMN
, 0, 0);
7047 ok(ret
== 100, "Unexpected column %d.\n", ret
);
7049 ret
= SendMessageA(hwnd
, LVM_SETSELECTEDCOLUMN
, -1, 0);
7050 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
7052 ret
= SendMessageA(hwnd
, LVM_GETSELECTEDCOLUMN
, 0, 0);
7053 ok(ret
== -1, "Unexpected column %d.\n", ret
);
7055 DestroyWindow(hwnd
);
7059 static void test_LVM_GETNEXTITEMINDEX(void)
7065 hwnd
= create_listview_control(LVS_REPORT
);
7067 insert_item(hwnd
, 0);
7068 insert_item(hwnd
, 1);
7070 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEMINDEX
, 0, LVNI_ALL
);
7071 ok(!ret
, "Unexpected return value %d.\n", ret
);
7075 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEMINDEX
, (WPARAM
)&index
, LVNI_ALL
);
7076 ok(ret
, "Unexpected return value %d.\n", ret
);
7077 ok(index
.iItem
== 0, "Unexpected item index %d.\n", index
.iItem
);
7079 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEMINDEX
, (WPARAM
)&index
, LVNI_ALL
);
7080 ok(ret
, "Unexpected return value %d.\n", ret
);
7081 ok(index
.iItem
== 1, "Unexpected item index %d.\n", index
.iItem
);
7083 ret
= SendMessageA(hwnd
, LVM_GETNEXTITEMINDEX
, (WPARAM
)&index
, LVNI_ALL
);
7084 ok(!ret
, "Unexpected return value %d.\n", ret
);
7085 ok(index
.iItem
== -1, "Unexpected item index %d.\n", index
.iItem
);
7087 DestroyWindow(hwnd
);
7090 static void test_LVM_SETBKIMAGE(BOOL is_v6
)
7100 hbmp
= CreateBitmap(32, 32, 1, 1, NULL
);
7101 hwnd
= create_listview_control(LVS_REPORT
);
7103 image
.ulFlags
= LVBKIF_SOURCE_NONE
;
7105 image
.pszImage
= NULL
;
7106 image
.cchImageMax
= 0;
7107 image
.xOffsetPercent
= 0;
7108 image
.yOffsetPercent
= 0;
7109 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7110 ok(!ret
, "got %d\n", ret
);
7112 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7113 ok(ret
== sizeof(bm
), "got %d\n", ret
);
7115 image
.ulFlags
= LVBKIF_SOURCE_HBITMAP
;
7117 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7119 ok(ret
, "got %d\n", ret
);
7121 todo_wine
ok(!ret
, "got %d\n", ret
);
7123 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7124 ok(ret
== sizeof(bm
), "got %d\n", ret
);
7126 image
.ulFlags
= LVBKIF_SOURCE_NONE
;
7128 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7129 ok(!ret
, "got %d\n", ret
);
7131 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7132 ok(!ret
, "got %d\n", ret
);
7134 hbmp
= CreateBitmap(32, 32, 1, 1, NULL
);
7136 image
.ulFlags
= LVBKIF_SOURCE_HBITMAP
;
7138 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7140 ok(ret
, "got %d\n", ret
);
7142 todo_wine
ok(!ret
, "got %d\n", ret
);
7144 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7145 ok(ret
== sizeof(bm
), "got %d\n", ret
);
7147 image
.ulFlags
= LVBKIF_SOURCE_HBITMAP
;
7149 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7150 ok(!ret
, "got %d\n", ret
);
7152 ret
= GetObjectA(hbmp
, sizeof(bm
), &bm
);
7153 ok(!ret
, "got %d\n", ret
);
7155 image
.ulFlags
= LVBKIF_SOURCE_NONE
;
7157 ret
= SendMessageA(hwnd
, LVM_SETBKIMAGEA
, 0, (LPARAM
)&image
);
7158 ok(!ret
, "got %d\n", ret
);
7160 DestroyWindow(hwnd
);
7165 START_TEST(listview
)
7167 ULONG_PTR ctx_cookie
;
7172 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
7174 hwndparent
= create_parent_window(FALSE
);
7175 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
7177 test_header_notification();
7178 test_header_notification2();
7185 test_icon_spacing();
7188 test_item_position();
7193 test_subitem_rect();
7196 test_ownerdata_multiselect();
7198 test_nosortheader();
7202 test_getitemposition();
7204 test_notifyformat();
7206 test_getitemspacing();
7207 test_getcolumnwidth();
7208 test_approximate_viewrect();
7211 test_destroynotify();
7212 test_createdragimage();
7214 test_LVM_SETITEMTEXT();
7215 test_LVM_REDRAWITEMS();
7216 test_WM_PRINTCLIENT();
7220 test_LVM_INSERTITEM();
7222 test_oneclickactivate();
7223 test_callback_mask();
7225 test_LVSCW_AUTOSIZE();
7226 test_LVN_ENDLABELEDIT();
7227 test_LVM_GETCOUNTPERPAGE();
7228 test_item_state_change();
7229 test_LVM_SETBKIMAGE(FALSE
);
7231 if (!load_v6_module(&ctx_cookie
, &hCtx
))
7233 DestroyWindow(hwndparent
);
7239 /* comctl32 version 6 tests start here */
7240 test_get_set_view();
7241 test_canceleditlabel();
7243 test_scrollnotify();
7244 test_LVS_EX_TRANSPARENTBKGND();
7245 test_LVS_EX_HEADERINALLVIEWS();
7258 test_ownerdata_multiselect();
7260 test_nosortheader();
7264 test_destroynotify();
7265 test_createdragimage();
7267 test_LVM_SETITEMTEXT();
7268 test_LVM_REDRAWITEMS();
7269 test_WM_PRINTCLIENT();
7270 test_oneclickactivate();
7272 test_LVSCW_AUTOSIZE();
7273 test_LVN_ENDLABELEDIT();
7274 test_LVM_GETCOUNTPERPAGE();
7275 test_item_state_change();
7276 test_selected_column();
7277 test_LVM_GETNEXTITEMINDEX();
7278 test_LVM_SETBKIMAGE(TRUE
);
7280 unload_v6_module(ctx_cookie
, hCtx
);
7282 DestroyWindow(hwndparent
);