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
27 #include "wine/test.h"
33 PARENT_FULL_SEQ_INDEX
,
44 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
45 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
46 "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
48 static const WCHAR testparentclassW
[] =
49 {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
51 static HWND hwndparent
, hwndparentW
;
52 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
53 static BOOL blockEdit
;
54 /* return nonzero on NM_HOVER */
55 static BOOL g_block_hover
;
56 /* notification data for LVN_ITEMCHANGED */
57 static NMLISTVIEW g_nmlistview
;
58 /* notification data for LVN_ITEMCHANGING */
59 static NMLISTVIEW g_nmlistview_changing
;
60 /* format reported to control:
61 -1 falls to defproc, anything else returned */
62 static INT notifyFormat
;
63 /* indicates we're running < 5.80 version */
64 static BOOL g_is_below_5
;
65 /* item data passed to LVN_GETDISPINFOA */
66 static LVITEMA g_itema
;
67 /* alter notification code A->W */
68 static BOOL g_disp_A_to_W
;
69 /* dispinfo data sent with LVN_LVN_ENDLABELEDIT */
70 static NMLVDISPINFOA g_editbox_disp_info
;
71 /* when this is set focus will be tested on LVN_DELETEITEM */
72 static BOOL g_focus_test_LVN_DELETEITEM
;
74 static HWND
subclass_editbox(HWND hwndListview
);
76 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
78 static const struct message create_ownerdrawfixed_parent_seq
[] = {
79 { WM_NOTIFYFORMAT
, sent
},
80 { WM_QUERYUISTATE
, sent
|optional
}, /* Win2K and higher */
81 { WM_MEASUREITEM
, sent
},
82 { WM_PARENTNOTIFY
, sent
},
86 static const struct message redraw_listview_seq
[] = {
87 { WM_PAINT
, sent
|id
, 0, 0, LISTVIEW_ID
},
88 { WM_PAINT
, sent
|id
, 0, 0, HEADER_ID
},
89 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
90 { WM_ERASEBKGND
, sent
|id
|defwinproc
|optional
, 0, 0, HEADER_ID
},
91 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
92 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
93 { WM_ERASEBKGND
, sent
|id
|defwinproc
|optional
, 0, 0, LISTVIEW_ID
},
97 static const struct message listview_icon_spacing_seq
[] = {
98 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(20, 30) },
99 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(25, 35) },
100 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(-1, -1) },
104 static const struct message listview_color_seq
[] = {
105 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
106 { LVM_GETBKCOLOR
, sent
},
107 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
108 { LVM_GETTEXTCOLOR
, sent
},
109 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
110 { LVM_GETTEXTBKCOLOR
, sent
},
112 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
113 { LVM_GETBKCOLOR
, sent
},
114 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
115 { LVM_GETTEXTCOLOR
, sent
},
116 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
117 { LVM_GETTEXTBKCOLOR
, sent
},
119 { LVM_SETBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
120 { LVM_GETBKCOLOR
, sent
},
121 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, CLR_NONE
},
122 { LVM_GETTEXTCOLOR
, sent
},
123 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
124 { LVM_GETTEXTBKCOLOR
, sent
},
126 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
127 { LVM_GETBKCOLOR
, sent
},
128 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
129 { LVM_GETTEXTCOLOR
, sent
},
130 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
131 { LVM_GETTEXTBKCOLOR
, sent
},
135 static const struct message listview_item_count_seq
[] = {
136 { LVM_GETITEMCOUNT
, sent
},
137 { LVM_INSERTITEMA
, sent
},
138 { LVM_INSERTITEMA
, sent
},
139 { LVM_INSERTITEMA
, sent
},
140 { LVM_GETITEMCOUNT
, sent
},
141 { LVM_DELETEITEM
, sent
|wparam
, 2 },
142 { WM_NCPAINT
, sent
|optional
},
143 { WM_ERASEBKGND
, sent
|optional
},
144 { LVM_GETITEMCOUNT
, sent
},
145 { LVM_DELETEALLITEMS
, sent
},
146 { LVM_GETITEMCOUNT
, sent
},
147 { LVM_INSERTITEMA
, sent
},
148 { LVM_INSERTITEMA
, sent
},
149 { LVM_GETITEMCOUNT
, sent
},
150 { LVM_INSERTITEMA
, sent
},
151 { LVM_GETITEMCOUNT
, sent
},
155 static const struct message listview_itempos_seq
[] = {
156 { LVM_INSERTITEMA
, sent
},
157 { LVM_INSERTITEMA
, sent
},
158 { LVM_INSERTITEMA
, sent
},
159 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 1, MAKELPARAM(10,5) },
160 { WM_NCPAINT
, sent
|optional
},
161 { WM_ERASEBKGND
, sent
|optional
},
162 { LVM_GETITEMPOSITION
, sent
|wparam
, 1 },
163 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 2, MAKELPARAM(0,0) },
164 { LVM_GETITEMPOSITION
, sent
|wparam
, 2 },
165 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 0, MAKELPARAM(20,20) },
166 { LVM_GETITEMPOSITION
, sent
|wparam
, 0 },
170 static const struct message listview_ownerdata_switchto_seq
[] = {
171 { WM_STYLECHANGING
, sent
},
172 { WM_STYLECHANGED
, sent
},
176 static const struct message listview_getorderarray_seq
[] = {
177 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
178 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
179 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 0, 0, LISTVIEW_ID
},
180 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 0, 0, HEADER_ID
},
184 static const struct message listview_setorderarray_seq
[] = {
185 { LVM_SETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
186 { HDM_SETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
187 { LVM_SETCOLUMNORDERARRAY
, sent
|id
|wparam
, 0, 0, LISTVIEW_ID
},
188 { HDM_SETORDERARRAY
, sent
|id
|wparam
, 0, 0, HEADER_ID
},
192 static const struct message empty_seq
[] = {
196 static const struct message forward_erasebkgnd_parent_seq
[] = {
197 { WM_ERASEBKGND
, sent
},
201 static const struct message ownerdata_select_focus_parent_seq
[] = {
202 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
203 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
204 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, LVN_GETDISPINFOA
}, /* version 4.7x */
208 static const struct message ownerdata_setstate_all_parent_seq
[] = {
209 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
213 static const struct message ownerdata_defocus_all_parent_seq
[] = {
214 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
215 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
216 { WM_NOTIFY
, sent
|id
|optional
, 0, 0, LVN_GETDISPINFOA
},
217 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
221 static const struct message ownerdata_deselect_all_parent_seq
[] = {
222 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ODCACHEHINT
},
223 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
227 static const struct message change_all_parent_seq
[] = {
228 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
229 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
231 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
232 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
234 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
235 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
237 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
238 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
240 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
241 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
245 static const struct message changing_all_parent_seq
[] = {
246 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
247 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
248 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
249 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
250 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
254 static const struct message textcallback_set_again_parent_seq
[] = {
255 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
256 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
260 static const struct message single_getdispinfo_parent_seq
[] = {
261 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
265 static const struct message getitemposition_seq1
[] = {
266 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
270 static const struct message getitemposition_seq2
[] = {
271 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
272 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
276 static const struct message getsubitemrect_seq
[] = {
277 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, -1, 0, LISTVIEW_ID
},
278 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
279 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, 0, 0, LISTVIEW_ID
},
280 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
281 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, -10, 0, LISTVIEW_ID
},
282 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
283 { LVM_GETSUBITEMRECT
, sent
|id
|wparam
, 20, 0, LISTVIEW_ID
},
284 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
288 static const struct message editbox_create_pos
[] = {
289 /* sequence sent after LVN_BEGINLABELEDIT */
290 /* next two are 4.7x specific */
291 { WM_WINDOWPOSCHANGING
, sent
},
292 { WM_WINDOWPOSCHANGED
, sent
|optional
},
294 { WM_WINDOWPOSCHANGING
, sent
|optional
},
295 { WM_NCCALCSIZE
, sent
},
296 { WM_WINDOWPOSCHANGED
, sent
},
297 { WM_MOVE
, sent
|defwinproc
},
298 { WM_SIZE
, sent
|defwinproc
},
299 /* the rest is todo, skipped in 4.7x */
300 { WM_WINDOWPOSCHANGING
, sent
|optional
},
301 { WM_WINDOWPOSCHANGED
, sent
|optional
},
305 static const struct message scroll_parent_seq
[] = {
306 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_BEGINSCROLL
},
307 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDSCROLL
},
311 static const struct message setredraw_seq
[] = {
312 { WM_SETREDRAW
, sent
|id
|wparam
, FALSE
, 0, LISTVIEW_ID
},
316 static const struct message lvs_ex_transparentbkgnd_seq
[] = {
317 { WM_PRINTCLIENT
, sent
|lparam
, 0, PRF_ERASEBKGND
},
321 static const struct message edit_end_nochange
[] = {
322 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ENDLABELEDITA
},
323 { WM_NOTIFY
, sent
|id
, 0, 0, NM_CUSTOMDRAW
}, /* todo */
324 { WM_NOTIFY
, sent
|id
, 0, 0, NM_SETFOCUS
},
328 static const struct message hover_parent
[] = {
329 { WM_GETDLGCODE
, sent
}, /* todo_wine */
330 { WM_NOTIFY
, sent
|id
, 0, 0, NM_HOVER
},
334 static const struct message listview_destroy
[] = {
335 { 0x0090, sent
|optional
}, /* Vista */
336 { WM_PARENTNOTIFY
, sent
},
337 { WM_SHOWWINDOW
, sent
},
338 { WM_WINDOWPOSCHANGING
, sent
},
339 { WM_WINDOWPOSCHANGED
, sent
|optional
},
340 { WM_DESTROY
, sent
},
341 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_DELETEALLITEMS
},
342 { WM_NCDESTROY
, sent
},
346 static const struct message listview_ownerdata_destroy
[] = {
347 { 0x0090, sent
|optional
}, /* Vista */
348 { WM_PARENTNOTIFY
, sent
},
349 { WM_SHOWWINDOW
, sent
},
350 { WM_WINDOWPOSCHANGING
, sent
},
351 { WM_WINDOWPOSCHANGED
, sent
|optional
},
352 { WM_DESTROY
, sent
},
353 { WM_NCDESTROY
, sent
},
357 static const struct message listview_ownerdata_deleteall
[] = {
358 { LVM_DELETEALLITEMS
, sent
},
359 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_DELETEALLITEMS
},
363 static const struct message listview_header_changed_seq
[] = {
364 { LVM_SETCOLUMNA
, sent
},
365 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
366 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
370 static const struct message parent_header_click_seq
[] = {
371 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_COLUMNCLICK
},
372 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_ITEMCLICKA
},
376 static const struct message parent_header_divider_dclick_seq
[] = {
377 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_ITEMCHANGINGA
},
378 { WM_NOTIFY
, sent
|id
, 0, 0, NM_CUSTOMDRAW
},
379 { WM_NOTIFY
, sent
|id
, 0, 0, NM_CUSTOMDRAW
},
380 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_ITEMCHANGEDA
},
381 { WM_NOTIFY
, sent
|id
, 0, 0, HDN_DIVIDERDBLCLICKA
},
385 static const struct message listview_set_imagelist
[] = {
386 { LVM_SETIMAGELIST
, sent
|id
, 0, 0, LISTVIEW_ID
},
390 static const struct message listview_header_set_imagelist
[] = {
391 { LVM_SETIMAGELIST
, sent
|id
, 0, 0, LISTVIEW_ID
},
392 { HDM_SETIMAGELIST
, sent
|id
, 0, 0, HEADER_ID
},
396 static const struct message parent_insert_focused_seq
[] = {
397 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
398 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
399 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
400 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
401 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_INSERTITEM
},
405 static const struct message parent_report_cd_seq
[] = {
406 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_PREPAINT
},
407 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
},
408 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
|CDDS_SUBITEM
},
409 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
|CDDS_SUBITEM
},
410 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
|CDDS_SUBITEM
},
411 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
|CDDS_SUBITEM
},
412 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
},
413 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_POSTPAINT
},
417 static const struct message parent_list_cd_seq
[] = {
418 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_PREPAINT
},
419 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPREPAINT
},
420 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_ITEMPOSTPAINT
},
421 { WM_NOTIFY
, sent
|id
|custdraw
, 0, 0, NM_CUSTOMDRAW
, CDDS_POSTPAINT
},
425 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
427 static LONG defwndproc_counter
= 0;
431 msg
.message
= message
;
432 msg
.flags
= sent
|wparam
|lparam
;
433 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
436 if (message
== WM_NOTIFY
&& lParam
) msg
.id
= ((NMHDR
*)lParam
)->code
;
438 /* log system messages, except for painting */
439 if (message
< WM_USER
&&
440 message
!= WM_PAINT
&&
441 message
!= WM_ERASEBKGND
&&
442 message
!= WM_NCPAINT
&&
443 message
!= WM_NCHITTEST
&&
444 message
!= WM_GETTEXT
&&
445 message
!= WM_GETICON
&&
446 message
!= WM_DEVICECHANGE
)
448 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
449 add_message(sequences
, COMBINED_SEQ_INDEX
, &msg
);
451 add_message(sequences
, PARENT_FULL_SEQ_INDEX
, &msg
);
457 switch (((NMHDR
*)lParam
)->code
)
459 case LVN_BEGINLABELEDITA
:
463 /* subclass edit box */
465 edit
= subclass_editbox(((NMHDR
*)lParam
)->hwndFrom
);
469 INT len
= SendMessageA(edit
, EM_GETLIMITTEXT
, 0, 0);
470 ok(len
== 259 || broken(len
== 260) /* includes NULL in NT4 */,
471 "text limit %d, expected 259\n", len
);
476 case LVN_ENDLABELEDITA
:
480 /* always accept new item text */
481 NMLVDISPINFOA
*di
= (NMLVDISPINFOA
*)lParam
;
482 g_editbox_disp_info
= *di
;
483 trace("LVN_ENDLABELEDIT: text=%s\n", di
->item
.pszText
? di
->item
.pszText
: "(null)");
485 /* edit control still available from this notification */
486 edit
= (HWND
)SendMessageA(((NMHDR
*)lParam
)->hwndFrom
, LVM_GETEDITCONTROL
, 0, 0);
487 ok(IsWindow(edit
), "expected valid edit control handle\n");
488 ok((GetWindowLongA(edit
, GWL_STYLE
) & ES_MULTILINE
) == 0, "edit is multiline\n");
492 case LVN_BEGINSCROLL
:
495 NMLVSCROLL
*pScroll
= (NMLVSCROLL
*)lParam
;
497 trace("LVN_%sSCROLL: (%d,%d)\n", pScroll
->hdr
.code
== LVN_BEGINSCROLL
?
498 "BEGIN" : "END", pScroll
->dx
, pScroll
->dy
);
501 case LVN_ITEMCHANGING
:
503 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
504 g_nmlistview_changing
= *nmlv
;
507 case LVN_ITEMCHANGED
:
509 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
510 g_nmlistview
= *nmlv
;
513 case LVN_GETDISPINFOA
:
515 NMLVDISPINFOA
*dispinfo
= (NMLVDISPINFOA
*)lParam
;
516 g_itema
= dispinfo
->item
;
518 if (g_disp_A_to_W
&& (dispinfo
->item
.mask
& LVIF_TEXT
))
520 static const WCHAR testW
[] = {'T','E','S','T',0};
521 dispinfo
->hdr
.code
= LVN_GETDISPINFOW
;
522 memcpy(dispinfo
->item
.pszText
, testW
, sizeof(testW
));
525 /* test control buffer size for text, 10 used to mask cases when control
526 is using caller buffer to process LVM_GETITEM for example */
527 if (dispinfo
->item
.mask
& LVIF_TEXT
&& dispinfo
->item
.cchTextMax
> 10)
528 ok(dispinfo
->item
.cchTextMax
== 260 ||
529 broken(dispinfo
->item
.cchTextMax
== 264) /* NT4 reports aligned size */,
530 "buffer size %d\n", dispinfo
->item
.cchTextMax
);
534 if (g_focus_test_LVN_DELETEITEM
)
536 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lParam
;
539 state
= SendMessageA(((NMHDR
*)lParam
)->hwndFrom
, LVM_GETITEMSTATE
, nmlv
->iItem
, LVIS_FOCUSED
);
540 ok(state
== 0, "got state %x\n", state
);
544 if (g_block_hover
) return 1;
549 case WM_NOTIFYFORMAT
:
551 /* force to return format */
552 if (lParam
== NF_QUERY
&& notifyFormat
!= -1) return notifyFormat
;
557 defwndproc_counter
++;
558 if (IsWindowUnicode(hwnd
))
559 ret
= DefWindowProcW(hwnd
, message
, wParam
, lParam
);
561 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
562 defwndproc_counter
--;
567 static BOOL
register_parent_wnd_class(BOOL Unicode
)
575 clsW
.lpfnWndProc
= parent_wnd_proc
;
578 clsW
.hInstance
= GetModuleHandleW(NULL
);
580 clsW
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
581 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
582 clsW
.lpszMenuName
= NULL
;
583 clsW
.lpszClassName
= testparentclassW
;
588 clsA
.lpfnWndProc
= parent_wnd_proc
;
591 clsA
.hInstance
= GetModuleHandleA(NULL
);
593 clsA
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
594 clsA
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
595 clsA
.lpszMenuName
= NULL
;
596 clsA
.lpszClassName
= "Listview test parent class";
599 return Unicode
? RegisterClassW(&clsW
) : RegisterClassA(&clsA
);
602 static HWND
create_parent_window(BOOL Unicode
)
604 static const WCHAR nameW
[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W',0};
607 if (!register_parent_wnd_class(Unicode
))
614 hwnd
= CreateWindowExW(0, testparentclassW
, nameW
,
615 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
616 WS_MAXIMIZEBOX
| WS_VISIBLE
,
618 GetDesktopWindow(), NULL
, GetModuleHandleW(NULL
), NULL
);
620 hwnd
= CreateWindowExA(0, "Listview test parent class",
621 "Listview test parent window",
622 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
623 WS_MAXIMIZEBOX
| WS_VISIBLE
,
625 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
626 SetWindowPos( hwnd
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
630 static LRESULT WINAPI
listview_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
632 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
633 static LONG defwndproc_counter
= 0;
637 /* some debug output for style changing */
638 if ((message
== WM_STYLECHANGING
||
639 message
== WM_STYLECHANGED
) && lParam
)
641 STYLESTRUCT
*style
= (STYLESTRUCT
*)lParam
;
642 trace("\told style: 0x%08x, new style: 0x%08x\n", style
->styleOld
, style
->styleNew
);
645 msg
.message
= message
;
646 msg
.flags
= sent
|wparam
|lparam
;
647 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
650 msg
.id
= LISTVIEW_ID
;
651 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
652 add_message(sequences
, COMBINED_SEQ_INDEX
, &msg
);
654 defwndproc_counter
++;
655 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
656 defwndproc_counter
--;
660 static HWND
create_listview_control(DWORD style
)
666 GetClientRect(hwndparent
, &rect
);
667 hwnd
= CreateWindowExA(0, WC_LISTVIEWA
, "foo",
668 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
669 0, 0, rect
.right
, rect
.bottom
,
670 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
671 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
673 if (!hwnd
) return NULL
;
675 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
676 (LONG_PTR
)listview_subclass_proc
);
677 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
682 /* unicode listview window with specified parent */
683 static HWND
create_listview_controlW(DWORD style
, HWND parent
)
688 static const WCHAR nameW
[] = {'f','o','o',0};
690 GetClientRect(parent
, &rect
);
691 hwnd
= CreateWindowExW(0, WC_LISTVIEWW
, nameW
,
692 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
693 0, 0, rect
.right
, rect
.bottom
,
694 parent
, NULL
, GetModuleHandleW(NULL
), NULL
);
695 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
697 if (!hwnd
) return NULL
;
699 oldproc
= (WNDPROC
)SetWindowLongPtrW(hwnd
, GWLP_WNDPROC
,
700 (LONG_PTR
)listview_subclass_proc
);
701 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
706 static LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
708 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
709 static LONG defwndproc_counter
= 0;
710 struct message msg
= { 0 };
713 msg
.message
= message
;
714 msg
.flags
= sent
|wparam
|lparam
;
715 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
719 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
721 defwndproc_counter
++;
722 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
723 defwndproc_counter
--;
727 static HWND
subclass_header(HWND hwndListview
)
732 hwnd
= (HWND
)SendMessageA(hwndListview
, LVM_GETHEADER
, 0, 0);
733 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
734 (LONG_PTR
)header_subclass_proc
);
735 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
740 static LRESULT WINAPI
editbox_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
742 WNDPROC oldproc
= (WNDPROC
)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
743 static LONG defwndproc_counter
= 0;
744 struct message msg
= { 0 };
747 msg
.message
= message
;
748 msg
.flags
= sent
|wparam
|lparam
;
749 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
753 /* all we need is sizing */
754 if (message
== WM_WINDOWPOSCHANGING
||
755 message
== WM_NCCALCSIZE
||
756 message
== WM_WINDOWPOSCHANGED
||
757 message
== WM_MOVE
||
760 add_message(sequences
, EDITBOX_SEQ_INDEX
, &msg
);
763 defwndproc_counter
++;
764 ret
= CallWindowProcA(oldproc
, hwnd
, message
, wParam
, lParam
);
765 defwndproc_counter
--;
769 static HWND
subclass_editbox(HWND hwndListview
)
774 hwnd
= (HWND
)SendMessageA(hwndListview
, LVM_GETEDITCONTROL
, 0, 0);
775 oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
776 (LONG_PTR
)editbox_subclass_proc
);
777 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)oldproc
);
782 /* Performs a single LVM_HITTEST test */
783 static void test_lvm_hittest_(HWND hwnd
, INT x
, INT y
, INT item
, UINT flags
, UINT broken_flags
,
784 BOOL todo_item
, BOOL todo_flags
, int line
)
793 ret
= SendMessageA(hwnd
, LVM_HITTEST
, 0, (LPARAM
)&lpht
);
795 todo_wine_if(todo_item
)
797 ok_(__FILE__
, line
)(ret
== item
, "Expected %d retval, got %d\n", item
, ret
);
798 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
799 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
805 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags 0x%x, got 0x%x\n", flags
, lpht
.flags
);
807 else if (broken_flags
)
808 ok_(__FILE__
, line
)(lpht
.flags
== flags
|| broken(lpht
.flags
== broken_flags
),
809 "Expected flags %x, got %x\n", flags
, lpht
.flags
);
811 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags 0x%x, got 0x%x\n", flags
, lpht
.flags
);
814 #define test_lvm_hittest(a,b,c,d,e,f,g,h) test_lvm_hittest_(a,b,c,d,e,f,g,h,__LINE__)
816 /* Performs a single LVM_SUBITEMHITTEST test */
817 static void test_lvm_subitemhittest_(HWND hwnd
, INT x
, INT y
, INT item
, INT subitem
, UINT flags
,
818 BOOL todo_item
, BOOL todo_subitem
, BOOL todo_flags
, int line
)
826 ret
= SendMessageA(hwnd
, LVM_SUBITEMHITTEST
, 0, (LPARAM
)&lpht
);
828 todo_wine_if(todo_item
)
830 ok_(__FILE__
, line
)(ret
== item
, "Expected %d retval, got %d\n", item
, ret
);
831 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
834 todo_wine_if(todo_subitem
)
835 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
837 todo_wine_if(todo_flags
)
838 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags 0x%x, got 0x%x\n", flags
, lpht
.flags
);
841 #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__)
843 static void test_images(void)
851 static CHAR hello
[] = "hello";
853 himl
= ImageList_Create(40, 40, 0, 4, 4);
854 ok(himl
!= NULL
, "failed to create imagelist\n");
856 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
857 ok(hbmp
!= NULL
, "failed to create bitmap\n");
859 r
= ImageList_Add(himl
, hbmp
, 0);
860 ok(r
== 0, "should be zero\n");
862 hwnd
= CreateWindowExA(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED
,
863 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
864 ok(hwnd
!= NULL
, "failed to create listview window\n");
866 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0,
867 LVS_EX_UNDERLINEHOT
| LVS_EX_FLATSB
| LVS_EX_ONECLICKACTIVATE
);
869 ok(r
== 0, "should return zero\n");
871 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
872 ok(r
== 0, "should return zero\n");
874 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELONG(100,50));
875 ok(r
!= 0, "got 0\n");
877 /* returns dimensions */
879 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
880 ok(r
== 0, "should be zero items\n");
882 item
.mask
= LVIF_IMAGE
| LVIF_TEXT
;
887 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
888 ok(r
== -1, "should fail\n");
891 item
.pszText
= hello
;
892 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
893 ok(r
== 0, "should not fail\n");
895 SetRect(&r1
, LVIR_ICON
, 0, 0, 0);
896 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r1
);
899 r
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
900 ok(r
== TRUE
, "should not fail\n");
903 item
.pszText
= hello
;
904 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
905 ok(r
== 0, "should not fail\n");
907 SetRect(&r2
, LVIR_ICON
, 0, 0, 0);
908 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r2
);
911 ok(EqualRect(&r1
, &r2
), "rectangle should be the same\n");
916 static void test_checkboxes(void)
921 static CHAR text
[] = "Text",
925 hwnd
= CreateWindowExA(0, "SysListView32", "foo", LVS_REPORT
,
926 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
927 ok(hwnd
!= NULL
, "failed to create listview window\n");
929 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
930 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
931 item
.stateMask
= 0xffff;
936 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
940 item
.mask
= LVIF_STATE
;
941 item
.stateMask
= 0xffff;
942 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
944 ok(item
.state
== 0xfccc, "state %x\n", item
.state
);
946 /* Don't set LVIF_STATE */
947 item
.mask
= LVIF_TEXT
;
948 item
.stateMask
= 0xffff;
953 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
957 item
.mask
= LVIF_STATE
;
958 item
.stateMask
= 0xffff;
959 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
961 ok(item
.state
== 0, "state %x\n", item
.state
);
963 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
966 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
968 item
.mask
= LVIF_STATE
;
969 item
.stateMask
= 0xffff;
970 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
972 if (item
.state
!= 0x1ccc)
974 win_skip("LVS_EX_CHECKBOXES style is unavailable. Skipping.\n");
979 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
981 item
.mask
= LVIF_TEXT
;
983 item
.pszText
= text2
;
984 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
988 item
.mask
= LVIF_STATE
;
989 item
.stateMask
= 0xffff;
990 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
992 ok(item
.state
== 0x1000, "state %x\n", item
.state
);
994 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
996 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
997 item
.stateMask
= 0xffff;
999 item
.pszText
= text3
;
1000 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1004 item
.mask
= LVIF_STATE
;
1005 item
.stateMask
= 0xffff;
1006 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1008 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
1010 /* Set an item's state to checked */
1012 item
.mask
= LVIF_STATE
;
1013 item
.stateMask
= 0xf000;
1014 item
.state
= 0x2000;
1015 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1019 item
.mask
= LVIF_STATE
;
1020 item
.stateMask
= 0xffff;
1021 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1023 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
1025 /* Check that only the bits we asked for are returned,
1026 * and that all the others are set to zero
1029 item
.mask
= LVIF_STATE
;
1030 item
.stateMask
= 0xf000;
1031 item
.state
= 0xffff;
1032 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1034 ok(item
.state
== 0x2000, "state %x\n", item
.state
);
1036 /* Set the style again and check that doesn't change an item's state */
1037 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
1038 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
1041 item
.mask
= LVIF_STATE
;
1042 item
.stateMask
= 0xffff;
1043 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1045 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
1047 /* Unsetting the checkbox extended style doesn't change an item's state */
1048 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
1049 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
1052 item
.mask
= LVIF_STATE
;
1053 item
.stateMask
= 0xffff;
1054 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1056 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
1058 /* Now setting the style again will change an item's state */
1059 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
1063 item
.mask
= LVIF_STATE
;
1064 item
.stateMask
= 0xffff;
1065 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1067 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
1069 /* Toggle checkbox tests (bug 9934) */
1070 memset (&item
, 0xcc, sizeof(item
));
1071 item
.mask
= LVIF_STATE
;
1074 item
.state
= LVIS_FOCUSED
;
1075 item
.stateMask
= LVIS_FOCUSED
;
1076 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1080 item
.mask
= LVIF_STATE
;
1081 item
.stateMask
= 0xffff;
1082 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1084 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
1086 r
= SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
1088 r
= SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
1092 item
.mask
= LVIF_STATE
;
1093 item
.stateMask
= 0xffff;
1094 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1096 ok(item
.state
== 0x2aab, "state %x\n", item
.state
);
1098 r
= SendMessageA(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
1100 r
= SendMessageA(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
1104 item
.mask
= LVIF_STATE
;
1105 item
.stateMask
= 0xffff;
1106 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1108 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
1110 DestroyWindow(hwnd
);
1113 static void insert_column(HWND hwnd
, int idx
)
1118 memset(&column
, 0xcc, sizeof(column
));
1119 column
.mask
= LVCF_SUBITEM
;
1120 column
.iSubItem
= idx
;
1122 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, idx
, (LPARAM
)&column
);
1126 static void insert_item(HWND hwnd
, int idx
)
1128 static CHAR text
[] = "foo";
1133 memset(&item
, 0xcc, sizeof (item
));
1134 item
.mask
= LVIF_TEXT
;
1137 item
.pszText
= text
;
1139 rc
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
1143 static void test_items(void)
1145 const LPARAM lparamTest
= 0x42;
1146 static CHAR text
[] = "Text";
1152 hwnd
= CreateWindowExA(0, "SysListView32", "foo", LVS_REPORT
,
1153 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1154 ok(hwnd
!= NULL
, "failed to create listview window\n");
1157 * Test setting/getting item params
1160 /* Set up two columns */
1161 insert_column(hwnd
, 0);
1162 insert_column(hwnd
, 1);
1164 /* LVIS_SELECTED with zero stateMask */
1166 memset (&item
, 0, sizeof (item
));
1167 item
.mask
= LVIF_STATE
;
1168 item
.state
= LVIS_SELECTED
;
1172 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1175 memset (&item
, 0xcc, sizeof (item
));
1176 item
.mask
= LVIF_STATE
;
1177 item
.stateMask
= LVIS_SELECTED
;
1181 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1183 ok(item
.state
& LVIS_SELECTED
, "Expected LVIS_SELECTED\n");
1184 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
1185 ok(r
, "got %d\n", r
);
1187 /* LVIS_SELECTED with zero stateMask */
1189 memset (&item
, 0, sizeof (item
));
1190 item
.mask
= LVIF_STATE
;
1191 item
.state
= LVIS_FOCUSED
;
1195 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1198 memset (&item
, 0xcc, sizeof (item
));
1199 item
.mask
= LVIF_STATE
;
1200 item
.stateMask
= LVIS_FOCUSED
;
1204 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1206 ok(item
.state
& LVIS_FOCUSED
, "Expected LVIS_FOCUSED\n");
1207 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
1208 ok(r
, "got %d\n", r
);
1210 /* LVIS_CUT with LVIS_FOCUSED stateMask */
1212 memset (&item
, 0, sizeof (item
));
1213 item
.mask
= LVIF_STATE
;
1214 item
.state
= LVIS_CUT
;
1215 item
.stateMask
= LVIS_FOCUSED
;
1218 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1221 memset (&item
, 0xcc, sizeof (item
));
1222 item
.mask
= LVIF_STATE
;
1223 item
.stateMask
= LVIS_CUT
;
1227 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1229 ok(item
.state
& LVIS_CUT
, "Expected LVIS_CUT\n");
1230 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
1231 ok(r
, "got %d\n", r
);
1233 /* Insert an item with just a param */
1234 memset (&item
, 0xcc, sizeof (item
));
1235 item
.mask
= LVIF_PARAM
;
1238 item
.lParam
= lparamTest
;
1239 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1242 /* Test getting of the param */
1243 memset (&item
, 0xcc, sizeof (item
));
1244 item
.mask
= LVIF_PARAM
;
1247 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1249 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1251 /* Set up a subitem */
1252 memset (&item
, 0xcc, sizeof (item
));
1253 item
.mask
= LVIF_TEXT
;
1256 item
.pszText
= text
;
1257 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1260 item
.mask
= LVIF_TEXT
;
1263 item
.pszText
= buffA
;
1264 item
.cchTextMax
= sizeof(buffA
);
1265 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1267 ok(!memcmp(item
.pszText
, text
, sizeof(text
)), "got text %s, expected %s\n", item
.pszText
, text
);
1269 /* set up with extra flag */
1270 /* 1. reset subitem text */
1271 item
.mask
= LVIF_TEXT
;
1274 item
.pszText
= NULL
;
1275 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1278 item
.mask
= LVIF_TEXT
;
1281 item
.pszText
= buffA
;
1283 item
.cchTextMax
= sizeof(buffA
);
1284 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1286 ok(item
.pszText
[0] == 0, "got %p\n", item
.pszText
);
1288 /* 2. set new text with extra flag specified */
1289 item
.mask
= LVIF_TEXT
| LVIF_DI_SETITEM
;
1292 item
.pszText
= text
;
1293 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1294 ok(r
== 1 || broken(r
== 0) /* NT4 */, "ret %d\n", r
);
1298 item
.mask
= LVIF_TEXT
;
1301 item
.pszText
= buffA
;
1303 item
.cchTextMax
= sizeof(buffA
);
1304 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1306 ok(!memcmp(item
.pszText
, text
, sizeof(text
)), "got %s, expected %s\n", item
.pszText
, text
);
1309 /* Query param from subitem: returns main item param */
1310 memset (&item
, 0xcc, sizeof (item
));
1311 item
.mask
= LVIF_PARAM
;
1314 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1316 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1318 /* Set up param on first subitem: no effect */
1319 memset (&item
, 0xcc, sizeof (item
));
1320 item
.mask
= LVIF_PARAM
;
1323 item
.lParam
= lparamTest
+1;
1324 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1327 /* Query param from subitem again: should still return main item param */
1328 memset (&item
, 0xcc, sizeof (item
));
1329 item
.mask
= LVIF_PARAM
;
1332 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1334 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1336 /**** Some tests of state highlighting ****/
1337 memset (&item
, 0xcc, sizeof (item
));
1338 item
.mask
= LVIF_STATE
;
1341 item
.state
= LVIS_SELECTED
;
1342 item
.stateMask
= LVIS_SELECTED
| LVIS_DROPHILITED
;
1343 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1346 item
.state
= LVIS_DROPHILITED
;
1347 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1350 memset (&item
, 0xcc, sizeof (item
));
1351 item
.mask
= LVIF_STATE
;
1354 item
.stateMask
= -1;
1355 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1357 ok(item
.state
== LVIS_SELECTED
, "got state %x, expected %x\n", item
.state
, LVIS_SELECTED
);
1359 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1361 todo_wine
ok(item
.state
== LVIS_DROPHILITED
, "got state %x, expected %x\n", item
.state
, LVIS_DROPHILITED
);
1363 /* some notnull but meaningless masks */
1364 memset (&item
, 0, sizeof(item
));
1365 item
.mask
= LVIF_NORECOMPUTE
;
1368 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1370 memset (&item
, 0, sizeof(item
));
1371 item
.mask
= LVIF_DI_SETITEM
;
1374 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1377 /* set text to callback value already having it */
1378 r
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1380 memset (&item
, 0, sizeof (item
));
1381 item
.mask
= LVIF_TEXT
;
1382 item
.pszText
= LPSTR_TEXTCALLBACKA
;
1384 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1386 memset (&item
, 0, sizeof (item
));
1388 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1390 item
.pszText
= LPSTR_TEXTCALLBACKA
;
1391 r
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0 , (LPARAM
) &item
);
1394 ok_sequence(sequences
, PARENT_SEQ_INDEX
, textcallback_set_again_parent_seq
,
1395 "check callback text comparison rule", FALSE
);
1397 DestroyWindow(hwnd
);
1400 static void test_columns(void)
1409 hwnd
= CreateWindowExA(0, "SysListView32", "foo", LVS_LIST
,
1410 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1411 ok(hwnd
!= NULL
, "failed to create listview window\n");
1413 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1414 ok(header
== NULL
, "got %p\n", header
);
1416 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1417 ok(rc
== 0, "got %d\n", rc
);
1419 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
1420 ok(header
== NULL
, "got %p\n", header
);
1422 DestroyWindow(hwnd
);
1424 hwnd
= CreateWindowExA(0, "SysListView32", "foo", LVS_REPORT
,
1425 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1426 ok(hwnd
!= NULL
, "failed to create listview window\n");
1428 rc
= SendMessageA(hwnd
, LVM_DELETECOLUMN
, -1, 0);
1429 ok(!rc
, "got %d\n", rc
);
1431 rc
= SendMessageA(hwnd
, LVM_DELETECOLUMN
, 0, 0);
1432 ok(!rc
, "got %d\n", rc
);
1434 /* Add a column with no mask */
1435 memset(&column
, 0xcc, sizeof(column
));
1437 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&column
);
1438 ok(rc
== 0, "Inserting column with no mask failed with %d\n", rc
);
1440 /* Check its width */
1441 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
1442 ok(rc
== 10, "Inserting column with no mask failed to set width to 10 with %d\n", rc
);
1444 DestroyWindow(hwnd
);
1446 /* LVM_GETCOLUMNORDERARRAY */
1447 hwnd
= create_listview_control(LVS_REPORT
);
1448 subclass_header(hwnd
);
1450 memset(&column
, 0, sizeof(column
));
1451 column
.mask
= LVCF_WIDTH
;
1453 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&column
);
1457 rc
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 1, (LPARAM
)&column
);
1460 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1462 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1464 ok(order
[0] == 0, "Expected order 0, got %d\n", order
[0]);
1465 ok(order
[1] == 1, "Expected order 1, got %d\n", order
[1]);
1467 rc
= SendMessageA(hwnd
, LVM_GETCOLUMNORDERARRAY
, 0, 0);
1470 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_getorderarray_seq
, "get order array", FALSE
);
1472 /* LVM_SETCOLUMNORDERARRAY */
1473 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1477 rc
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1480 rc
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 0, 0);
1483 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_setorderarray_seq
, "set order array", FALSE
);
1485 /* after column added subitem is considered as present */
1486 insert_item(hwnd
, 0);
1488 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1490 item
.pszText
= buff
;
1491 item
.cchTextMax
= sizeof(buff
);
1494 item
.mask
= LVIF_TEXT
;
1495 memset(&g_itema
, 0, sizeof(g_itema
));
1496 rc
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
1498 ok(g_itema
.iSubItem
== 1, "got %d\n", g_itema
.iSubItem
);
1500 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
1501 "get subitem text after column added", FALSE
);
1503 DestroyWindow(hwnd
);
1506 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1507 static WNDPROC listviewWndProc
;
1508 static HIMAGELIST test_create_imagelist
;
1510 static LRESULT CALLBACK
create_test_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1514 if (uMsg
== WM_CREATE
)
1516 CREATESTRUCTA
*lpcs
= (CREATESTRUCTA
*)lParam
;
1517 lpcs
->style
|= LVS_REPORT
;
1519 ret
= CallWindowProcA(listviewWndProc
, hwnd
, uMsg
, wParam
, lParam
);
1520 if (uMsg
== WM_CREATE
) SendMessageA(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)test_create_imagelist
);
1524 static void test_create(void)
1535 cls
.cbSize
= sizeof(WNDCLASSEXA
);
1536 ok(GetClassInfoExA(GetModuleHandleA(NULL
), "SysListView32", &cls
), "GetClassInfoEx failed\n");
1537 listviewWndProc
= cls
.lpfnWndProc
;
1538 cls
.lpfnWndProc
= create_test_wndproc
;
1539 cls
.lpszClassName
= "MyListView32";
1540 ok(RegisterClassExA(&cls
), "RegisterClassEx failed\n");
1542 test_create_imagelist
= ImageList_Create(16, 16, 0, 5, 10);
1543 hList
= CreateWindowA("MyListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1544 ok((HIMAGELIST
)SendMessageA(hList
, LVM_GETIMAGELIST
, 0, 0) == test_create_imagelist
, "Image list not obtained\n");
1545 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1547 if (!IsWindow(hHeader
))
1550 win_skip("LVM_GETHEADER not implemented. Skipping.\n");
1551 DestroyWindow(hList
);
1555 ok(IsWindow(hHeader
) && IsWindowVisible(hHeader
), "Listview not in report mode\n");
1556 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1557 DestroyWindow(hList
);
1559 /* header isn't created on LVS_ICON and LVS_LIST styles */
1560 hList
= CreateWindowA("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1561 GetModuleHandleA(NULL
), 0);
1562 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1563 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1564 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1566 memset(&col
, 0, sizeof(LVCOLUMNA
));
1567 col
.mask
= LVCF_WIDTH
;
1569 r
= SendMessageA(hList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
1571 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1572 ok(IsWindow(hHeader
), "Header should be created\n");
1573 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1574 style
= GetWindowLongA(hHeader
, GWL_STYLE
);
1575 ok(!(style
& HDS_HIDDEN
), "Not expected HDS_HIDDEN\n");
1576 DestroyWindow(hList
);
1578 hList
= CreateWindowA("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1579 GetModuleHandleA(NULL
), 0);
1580 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1581 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1582 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1584 memset(&col
, 0, sizeof(LVCOLUMNA
));
1585 col
.mask
= LVCF_WIDTH
;
1587 r
= SendMessageA(hList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
1589 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1590 ok(IsWindow(hHeader
), "Header should be created\n");
1591 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1592 DestroyWindow(hList
);
1594 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1595 hList
= CreateWindowA("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1596 GetModuleHandleA(NULL
), 0);
1597 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
, GetWindowLongPtrA(hList
, GWL_STYLE
) | LVS_REPORT
);
1598 ok(ret
& WS_VISIBLE
, "Style wrong, should have WS_VISIBLE\n");
1599 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1600 ok(IsWindow(hHeader
), "Header should be created\n");
1601 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
, GetWindowLongA(hList
, GWL_STYLE
) & ~LVS_REPORT
);
1602 ok((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1603 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1604 ok(IsWindow(hHeader
), "Header should be created\n");
1605 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1606 DestroyWindow(hList
);
1608 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1609 hList
= CreateWindowA("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1610 GetModuleHandleA(NULL
), 0);
1611 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
,
1612 (GetWindowLongPtrA(hList
, GWL_STYLE
) & ~LVS_LIST
) | LVS_REPORT
);
1613 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_LIST
)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1614 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1615 ok(IsWindow(hHeader
), "Header should be created\n");
1616 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1617 ret
= SetWindowLongPtrA(hList
, GWL_STYLE
,
1618 (GetWindowLongPtrA(hList
, GWL_STYLE
) & ~LVS_REPORT
) | LVS_LIST
);
1619 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1620 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1621 ok(IsWindow(hHeader
), "Header should be created\n");
1622 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1623 DestroyWindow(hList
);
1625 /* LVS_REPORT without WS_VISIBLE */
1626 hList
= CreateWindowA("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1627 GetModuleHandleA(NULL
), 0);
1628 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1629 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1630 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1632 memset(&col
, 0, sizeof(LVCOLUMNA
));
1633 col
.mask
= LVCF_WIDTH
;
1635 r
= SendMessageA(hList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
1637 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1638 ok(IsWindow(hHeader
), "Header should be created\n");
1639 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1640 DestroyWindow(hList
);
1642 /* LVS_REPORT without WS_VISIBLE, try to show it */
1643 hList
= CreateWindowA("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1644 GetModuleHandleA(NULL
), 0);
1645 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1646 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1647 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1648 ShowWindow(hList
, SW_SHOW
);
1649 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1650 ok(IsWindow(hHeader
), "Header should be created\n");
1651 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1652 DestroyWindow(hList
);
1654 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1655 hList
= CreateWindowA("SysListView32", "Test", LVS_REPORT
|LVS_NOCOLUMNHEADER
|WS_VISIBLE
,
1656 0, 0, 100, 100, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1657 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1658 ok(IsWindow(hHeader
), "Header should be created\n");
1659 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1660 /* HDS_DRAGDROP set by default */
1661 ok(GetWindowLongPtrA(hHeader
, GWL_STYLE
) & HDS_DRAGDROP
, "Expected header to have HDS_DRAGDROP\n");
1662 DestroyWindow(hList
);
1664 /* setting LVS_EX_HEADERDRAGDROP creates header */
1665 hList
= CreateWindowA("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1666 GetModuleHandleA(NULL
), 0);
1667 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1668 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1669 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1670 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1671 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1672 ok(IsWindow(hHeader
) ||
1673 broken(!IsWindow(hHeader
)), /* 4.7x common controls */
1674 "Header should be created\n");
1675 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1676 DestroyWindow(hList
);
1678 /* setting LVS_EX_GRIDLINES creates header */
1679 hList
= CreateWindowA("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1680 GetModuleHandleA(NULL
), 0);
1681 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1682 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1683 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1684 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_GRIDLINES
);
1685 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1686 ok(IsWindow(hHeader
) ||
1687 broken(!IsWindow(hHeader
)), /* 4.7x common controls */
1688 "Header should be created\n");
1689 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1690 DestroyWindow(hList
);
1692 /* setting LVS_EX_FULLROWSELECT creates header */
1693 hList
= CreateWindowA("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1694 GetModuleHandleA(NULL
), 0);
1695 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1696 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1697 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1698 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
1699 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1700 ok(IsWindow(hHeader
) ||
1701 broken(!IsWindow(hHeader
)), /* 4.7x common controls */
1702 "Header should be created\n");
1703 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1704 DestroyWindow(hList
);
1706 /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1707 hList
= create_listview_control(LVS_ICON
);
1708 SendMessageA(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1709 r
= SendMessageA(hList
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1710 ok(r
& LVS_EX_HEADERDRAGDROP
, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1711 DestroyWindow(hList
);
1713 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1714 hList
= CreateWindowA("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1715 GetModuleHandleA(NULL
), 0);
1716 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1717 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1719 SetRect(&rect
, LVIR_BOUNDS
, 1, -10, -10);
1720 r
= SendMessageA(hList
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1721 /* right value contains garbage, probably because header columns are not set up */
1722 expect(0, rect
.bottom
);
1725 hHeader
= (HWND
)SendMessageA(hList
, LVM_GETHEADER
, 0, 0);
1726 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1727 ok(GetDlgItem(hList
, 0) == NULL
, "NULL dialog item expected\n");
1729 DestroyWindow(hList
);
1731 /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1732 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1733 hList
= create_listview_control(LVS_OWNERDRAWFIXED
| LVS_REPORT
);
1734 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_ownerdrawfixed_parent_seq
,
1735 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE
);
1736 DestroyWindow(hList
);
1739 static void test_redraw(void)
1746 hwnd
= create_listview_control(LVS_REPORT
);
1747 subclass_header(hwnd
);
1749 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1751 InvalidateRect(hwnd
, NULL
, TRUE
);
1753 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, redraw_listview_seq
, "redraw listview", FALSE
);
1755 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1757 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1758 /* 1. Without backbuffer */
1759 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
1762 hdc
= GetWindowDC(hwndparent
);
1764 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1765 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1766 ok(r
== 1, "Expected not zero result\n");
1767 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1768 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1770 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_DEFAULT
);
1773 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1774 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1776 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1777 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1779 /* 2. With backbuffer */
1780 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_DOUBLEBUFFER
,
1781 LVS_EX_DOUBLEBUFFER
);
1782 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
1785 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1786 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1788 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1789 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1791 res
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_DEFAULT
);
1794 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1795 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1796 todo_wine
expect(1, r
);
1797 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1798 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1800 ReleaseDC(hwndparent
, hdc
);
1802 DestroyWindow(hwnd
);
1805 static LRESULT WINAPI
cd_wndproc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1807 COLORREF clr
, c0ffee
= RGB(0xc0, 0xff, 0xee);
1809 if(message
== WM_NOTIFY
) {
1810 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
1811 if(nmhdr
->code
== NM_CUSTOMDRAW
) {
1812 NMLVCUSTOMDRAW
*nmlvcd
= (NMLVCUSTOMDRAW
*)nmhdr
;
1815 msg
.message
= message
;
1816 msg
.flags
= sent
|wparam
|lparam
|custdraw
;
1817 msg
.wParam
= wParam
;
1818 msg
.lParam
= lParam
;
1819 msg
.id
= nmhdr
->code
;
1820 msg
.stage
= nmlvcd
->nmcd
.dwDrawStage
;
1821 add_message(sequences
, PARENT_CD_SEQ_INDEX
, &msg
);
1823 switch(nmlvcd
->nmcd
.dwDrawStage
) {
1825 SetBkColor(nmlvcd
->nmcd
.hdc
, c0ffee
);
1826 return CDRF_NOTIFYITEMDRAW
|CDRF_NOTIFYPOSTPAINT
;
1827 case CDDS_ITEMPREPAINT
:
1828 nmlvcd
->clrTextBk
= CLR_DEFAULT
;
1829 nmlvcd
->clrText
= RGB(0, 255, 0);
1830 return CDRF_NOTIFYSUBITEMDRAW
|CDRF_NOTIFYPOSTPAINT
;
1831 case CDDS_ITEMPREPAINT
| CDDS_SUBITEM
:
1832 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1833 ok(nmlvcd
->clrTextBk
== CLR_DEFAULT
, "got 0x%x\n", nmlvcd
->clrTextBk
);
1834 ok(nmlvcd
->clrText
== RGB(0, 255, 0), "got 0x%x\n", nmlvcd
->clrText
);
1835 todo_wine_if(nmlvcd
->iSubItem
)
1836 ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1837 return CDRF_NOTIFYPOSTPAINT
;
1838 case CDDS_ITEMPOSTPAINT
| CDDS_SUBITEM
:
1839 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1840 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1841 ok(nmlvcd
->clrTextBk
== CLR_DEFAULT
, "got 0x%x\n", nmlvcd
->clrTextBk
);
1842 ok(nmlvcd
->clrText
== RGB(0, 255, 0), "got 0x%x\n", nmlvcd
->clrText
);
1843 return CDRF_DODEFAULT
;
1845 return CDRF_DODEFAULT
;
1849 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
1852 static void test_customdraw(void)
1857 hwnd
= create_listview_control(LVS_REPORT
);
1859 insert_column(hwnd
, 0);
1860 insert_column(hwnd
, 1);
1861 insert_item(hwnd
, 0);
1863 oldwndproc
= (WNDPROC
)SetWindowLongPtrA(hwndparent
, GWLP_WNDPROC
,
1864 (LONG_PTR
)cd_wndproc
);
1866 InvalidateRect(hwnd
, NULL
, TRUE
);
1870 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1871 InvalidateRect(hwnd
, NULL
, TRUE
);
1873 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_report_cd_seq
, "parent customdraw, LVS_REPORT", FALSE
);
1875 DestroyWindow(hwnd
);
1877 hwnd
= create_listview_control(LVS_LIST
);
1879 insert_column(hwnd
, 0);
1880 insert_column(hwnd
, 1);
1881 insert_item(hwnd
, 0);
1883 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1884 InvalidateRect(hwnd
, NULL
, TRUE
);
1886 ok_sequence(sequences
, PARENT_CD_SEQ_INDEX
, parent_list_cd_seq
, "parent customdraw, LVS_LIST", FALSE
);
1888 SetWindowLongPtrA(hwndparent
, GWLP_WNDPROC
, (LONG_PTR
)oldwndproc
);
1889 DestroyWindow(hwnd
);
1892 static void test_icon_spacing(void)
1894 /* LVM_SETICONSPACING */
1895 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1901 hwnd
= create_listview_control(LVS_ICON
);
1902 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1904 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, (WPARAM
)hwndparent
, NF_REQUERY
);
1905 expect(NFR_ANSI
, r
);
1907 /* reset the icon spacing to defaults */
1908 SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1910 /* now we can request what the defaults are */
1911 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1915 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1917 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(20, 30));
1918 ok(r
== MAKELONG(w
, h
) ||
1919 broken(r
== MAKELONG(w
, w
)), /* win98 */
1920 "Expected %d, got %d\n", MAKELONG(w
, h
), r
);
1922 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(25, 35));
1926 win_skip("LVM_SETICONSPACING unimplemented. Skipping.\n");
1927 DestroyWindow(hwnd
);
1930 expect(MAKELONG(20,30), r
);
1932 r
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1,-1));
1933 expect(MAKELONG(25,35), r
);
1935 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_icon_spacing_seq
, "test icon spacing seq", FALSE
);
1937 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1938 DestroyWindow(hwnd
);
1941 static void test_color(void)
1949 COLORREF colors
[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE
, RGB(255,255,255)};
1951 hwnd
= create_listview_control(LVS_REPORT
);
1952 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1954 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1956 for (i
= 0; i
< 4; i
++)
1960 r
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, color
);
1962 r
= SendMessageA(hwnd
, LVM_GETBKCOLOR
, 0, 0);
1965 r
= SendMessageA(hwnd
, LVM_SETTEXTCOLOR
, 0, color
);
1967 r
= SendMessageA(hwnd
, LVM_GETTEXTCOLOR
, 0, 0);
1970 r
= SendMessageA(hwnd
, LVM_SETTEXTBKCOLOR
, 0, color
);
1972 r
= SendMessageA(hwnd
, LVM_GETTEXTBKCOLOR
, 0, 0);
1976 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_color_seq
, "test color seq", FALSE
);
1977 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1979 /* invalidation test done separately to avoid a message chain mess */
1980 r
= ValidateRect(hwnd
, NULL
);
1982 r
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, colors
[0]);
1985 rect
.right
= rect
.bottom
= 1;
1986 r
= GetUpdateRect(hwnd
, &rect
, TRUE
);
1987 todo_wine
expect(FALSE
, r
);
1988 ok(rect
.right
== 0 && rect
.bottom
== 0, "got update rectangle\n");
1990 r
= ValidateRect(hwnd
, NULL
);
1992 r
= SendMessageA(hwnd
, LVM_SETTEXTCOLOR
, 0, colors
[0]);
1995 rect
.right
= rect
.bottom
= 1;
1996 r
= GetUpdateRect(hwnd
, &rect
, TRUE
);
1997 todo_wine
expect(FALSE
, r
);
1998 ok(rect
.right
== 0 && rect
.bottom
== 0, "got update rectangle\n");
2000 r
= ValidateRect(hwnd
, NULL
);
2002 r
= SendMessageA(hwnd
, LVM_SETTEXTBKCOLOR
, 0, colors
[0]);
2005 rect
.right
= rect
.bottom
= 1;
2006 r
= GetUpdateRect(hwnd
, &rect
, TRUE
);
2007 todo_wine
expect(FALSE
, r
);
2008 ok(rect
.right
== 0 && rect
.bottom
== 0, "got update rectangle\n");
2010 DestroyWindow(hwnd
);
2013 static void test_item_count(void)
2015 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
2028 static CHAR item0text
[] = "item0";
2029 static CHAR item1text
[] = "item1";
2030 static CHAR item2text
[] = "item2";
2032 hwnd
= create_listview_control(LVS_REPORT
);
2033 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2035 /* resize in dpiaware manner to fit all 3 items added */
2037 hOldFont
= SelectObject(hdc
, GetStockObject(SYSTEM_FONT
));
2038 GetTextMetricsA(hdc
, &tm
);
2039 /* 2 extra pixels for bounds and header border */
2040 height
= tm
.tmHeight
+ 2;
2041 SelectObject(hdc
, hOldFont
);
2044 GetWindowRect(hwnd
, &rect
);
2045 /* 3 items + 1 header + 1 to be sure */
2046 MoveWindow(hwnd
, 0, 0, rect
.right
- rect
.left
, 5 * height
, FALSE
);
2048 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2050 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2054 item0
.mask
= LVIF_TEXT
;
2057 item0
.pszText
= item0text
;
2058 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item0
);
2061 /* [item0, item1] */
2062 item1
.mask
= LVIF_TEXT
;
2065 item1
.pszText
= item1text
;
2066 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2069 /* [item0, item1, item2] */
2070 item2
.mask
= LVIF_TEXT
;
2073 item2
.pszText
= item2text
;
2074 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item2
);
2077 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2080 /* [item0, item1] */
2081 r
= SendMessageA(hwnd
, LVM_DELETEITEM
, 2, 0);
2084 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2088 r
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
2091 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2095 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2098 /* [item0, item1] */
2099 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2102 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2105 /* [item0, item1, item2] */
2106 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item2
);
2109 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2112 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_item_count_seq
, "test item count seq", FALSE
);
2114 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2115 DestroyWindow(hwnd
);
2118 static void test_item_position(void)
2120 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
2129 static CHAR item0text
[] = "item0";
2130 static CHAR item1text
[] = "item1";
2131 static CHAR item2text
[] = "item2";
2133 hwnd
= create_listview_control(LVS_ICON
);
2134 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2136 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2139 item0
.mask
= LVIF_TEXT
;
2142 item0
.pszText
= item0text
;
2143 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item0
);
2146 /* [item0, item1] */
2147 item1
.mask
= LVIF_TEXT
;
2150 item1
.pszText
= item1text
;
2151 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item1
);
2154 /* [item0, item1, item2] */
2155 item2
.mask
= LVIF_TEXT
;
2158 item2
.pszText
= item2text
;
2159 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item2
);
2162 r
= SendMessageA(hwnd
, LVM_SETITEMPOSITION
, 1, MAKELPARAM(10,5));
2164 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 1, (LPARAM
) &position
);
2166 expect2(10, 5, position
.x
, position
.y
);
2168 r
= SendMessageA(hwnd
, LVM_SETITEMPOSITION
, 2, MAKELPARAM(0,0));
2170 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 2, (LPARAM
) &position
);
2172 expect2(0, 0, position
.x
, position
.y
);
2174 r
= SendMessageA(hwnd
, LVM_SETITEMPOSITION
, 0, MAKELPARAM(20,20));
2176 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
) &position
);
2178 expect2(20, 20, position
.x
, position
.y
);
2180 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_itempos_seq
, "test item position seq", TRUE
);
2182 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2183 DestroyWindow(hwnd
);
2186 static void test_getorigin(void)
2194 position
.x
= position
.y
= 0;
2196 hwnd
= create_listview_control(LVS_ICON
);
2197 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2198 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2200 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2202 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2203 DestroyWindow(hwnd
);
2205 hwnd
= create_listview_control(LVS_SMALLICON
);
2206 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2207 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2209 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2211 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2212 DestroyWindow(hwnd
);
2214 hwnd
= create_listview_control(LVS_LIST
);
2215 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2216 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2218 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2220 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2221 DestroyWindow(hwnd
);
2223 hwnd
= create_listview_control(LVS_REPORT
);
2224 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2225 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2227 r
= SendMessageA(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
2229 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2230 DestroyWindow(hwnd
);
2233 static void test_multiselect(void)
2235 typedef struct t_select_task
2247 static const int items
=5;
2254 static struct t_select_task task_list
[] = {
2255 { "using VK_DOWN", 0, VK_DOWN
, -1, -1 },
2256 { "using VK_UP", -1, VK_UP
, -1, -1 },
2257 { "using VK_END", 0, VK_END
, 1, -1 },
2258 { "using VK_HOME", -1, VK_HOME
, 1, -1 }
2261 hwnd
= create_listview_control(LVS_REPORT
);
2263 for (i
= 0; i
< items
; i
++)
2264 insert_item(hwnd
, 0);
2266 item_count
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2267 expect(items
, item_count
);
2269 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2270 ok(r
== -1, "got %d\n", r
);
2272 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, 0);
2273 ok(r
== -1, "got %d\n", r
);
2275 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, 0);
2276 ok(r
== 0, "got %d\n", r
);
2278 /* out of range index */
2279 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, items
);
2280 ok(r
== 0, "got %d\n", r
);
2282 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2283 ok(r
== 0, "got %d\n", r
);
2285 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -2);
2286 ok(r
== 0, "got %d\n", r
);
2288 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2289 ok(r
== 0, "got %d\n", r
);
2291 for (i
= 0; i
< sizeof(task_list
)/sizeof(task_list
[0]); i
++) {
2292 DWORD selected_count
;
2295 task
= task_list
[i
];
2297 /* deselect all items */
2299 item
.stateMask
= LVIS_SELECTED
;
2300 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2301 ok(r
, "got %d\n", r
);
2302 SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2304 /* set initial position */
2305 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, (task
.initPos
== -1 ? item_count
-1 : task
.initPos
));
2306 ok(r
, "got %d\n", r
);
2308 item
.state
= LVIS_SELECTED
;
2309 item
.stateMask
= LVIS_SELECTED
;
2310 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, task
.initPos
== -1 ? item_count
-1 : task
.initPos
, (LPARAM
)&item
);
2311 ok(r
, "got %d\n", r
);
2313 selected_count
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2314 ok(selected_count
== 1, "expected 1, got %d\n", selected_count
);
2316 /* Set SHIFT key pressed */
2317 GetKeyboardState(kstate
);
2318 kstate
[VK_SHIFT
]=0x80;
2319 SetKeyboardState(kstate
);
2321 for (j
=1;j
<=(task
.count
== -1 ? item_count
: task
.count
);j
++) {
2322 r
= SendMessageA(hwnd
, WM_KEYDOWN
, task
.loopVK
, 0);
2324 r
= SendMessageA(hwnd
, WM_KEYUP
, task
.loopVK
, 0);
2328 selected_count
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2330 ok((task
.result
== -1 ? item_count
: task
.result
) == selected_count
,
2331 "Failed multiple selection %s. There should be %d selected items (is %d)\n",
2332 task
.descr
, item_count
, selected_count
);
2334 /* Set SHIFT key released */
2335 GetKeyboardState(kstate
);
2336 kstate
[VK_SHIFT
]=0x00;
2337 SetKeyboardState(kstate
);
2339 DestroyWindow(hwnd
);
2341 /* make multiple selection, then switch to LVS_SINGLESEL */
2342 hwnd
= create_listview_control(LVS_REPORT
);
2343 for (i
=0;i
<items
;i
++) {
2344 insert_item(hwnd
, 0);
2346 item_count
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2347 expect(items
,item_count
);
2349 /* try with NULL pointer */
2350 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, 0);
2353 /* select all, check notifications */
2355 item
.stateMask
= LVIS_SELECTED
;
2356 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2357 ok(r
, "got %d\n", r
);
2359 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2361 item
.stateMask
= LVIS_SELECTED
;
2362 item
.state
= LVIS_SELECTED
;
2363 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2366 ok_sequence(sequences
, PARENT_SEQ_INDEX
, change_all_parent_seq
,
2367 "select all notification", FALSE
);
2369 /* select all again (all selected already) */
2370 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2372 memset(&g_nmlistview_changing
, 0xcc, sizeof(g_nmlistview_changing
));
2374 item
.stateMask
= LVIS_SELECTED
;
2375 item
.state
= LVIS_SELECTED
;
2376 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2379 ok(g_nmlistview_changing
.uNewState
== LVIS_SELECTED
, "got 0x%x\n", g_nmlistview_changing
.uNewState
);
2380 ok(g_nmlistview_changing
.uOldState
== LVIS_SELECTED
, "got 0x%x\n", g_nmlistview_changing
.uOldState
);
2381 ok(g_nmlistview_changing
.uChanged
== LVIF_STATE
, "got 0x%x\n", g_nmlistview_changing
.uChanged
);
2383 ok_sequence(sequences
, PARENT_SEQ_INDEX
, changing_all_parent_seq
,
2384 "select all notification 2", FALSE
);
2386 /* deselect all items */
2387 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2390 item
.stateMask
= LVIS_SELECTED
;
2391 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2392 ok(r
, "got %d\n", r
);
2394 ok_sequence(sequences
, PARENT_SEQ_INDEX
, change_all_parent_seq
,
2395 "deselect all notification", FALSE
);
2397 /* deselect all items again */
2398 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2400 item
.stateMask
= LVIS_SELECTED
;
2401 SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2402 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "deselect all notification 2", FALSE
);
2404 /* any non-zero state value does the same */
2405 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2407 memset(&g_nmlistview_changing
, 0xcc, sizeof(g_nmlistview_changing
));
2409 item
.stateMask
= LVIS_SELECTED
;
2410 item
.state
= LVIS_CUT
;
2411 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2414 ok(g_nmlistview_changing
.uNewState
== 0, "got 0x%x\n", g_nmlistview_changing
.uNewState
);
2415 ok(g_nmlistview_changing
.uOldState
== 0, "got 0x%x\n", g_nmlistview_changing
.uOldState
);
2416 ok(g_nmlistview_changing
.uChanged
== LVIF_STATE
, "got 0x%x\n", g_nmlistview_changing
.uChanged
);
2418 ok_sequence(sequences
, PARENT_SEQ_INDEX
, changing_all_parent_seq
,
2419 "set state all notification 3", FALSE
);
2421 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2422 ok(r
, "got %d\n", r
);
2423 for (i
= 0; i
< 3; i
++) {
2424 item
.state
= LVIS_SELECTED
;
2425 item
.stateMask
= LVIS_SELECTED
;
2426 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
2427 ok(r
, "got %d\n", r
);
2430 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2432 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2435 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2436 ok(!(style
& LVS_SINGLESEL
), "LVS_SINGLESEL isn't expected\n");
2437 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SINGLESEL
);
2438 /* check that style is accepted */
2439 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2440 ok(style
& LVS_SINGLESEL
, "LVS_SINGLESEL expected\n");
2443 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, i
, LVIS_SELECTED
);
2444 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
2446 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2448 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2449 ok(r
== -1, "got %d\n", r
);
2451 /* select one more */
2452 item
.state
= LVIS_SELECTED
;
2453 item
.stateMask
= LVIS_SELECTED
;
2454 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 3, (LPARAM
)&item
);
2455 ok(r
, "got %d\n", r
);
2458 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, i
, LVIS_SELECTED
);
2459 ok(!(r
& LVIS_SELECTED
), "Expected item %d to be unselected\n", i
);
2462 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 3, LVIS_SELECTED
);
2463 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
2465 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2467 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2470 /* try to select all on LVS_SINGLESEL */
2471 memset(&item
, 0, sizeof(item
));
2472 item
.stateMask
= LVIS_SELECTED
;
2473 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2475 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2476 ok(r
== -1, "got %d\n", r
);
2478 item
.stateMask
= LVIS_SELECTED
;
2479 item
.state
= LVIS_SELECTED
;
2480 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2483 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2485 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2488 /* try to deselect all on LVS_SINGLESEL */
2489 item
.stateMask
= LVIS_SELECTED
;
2490 item
.state
= LVIS_SELECTED
;
2491 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2494 item
.stateMask
= LVIS_SELECTED
;
2496 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2498 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2501 /* 1. selection mark is update when new focused item is set */
2502 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2503 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SINGLESEL
);
2505 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2508 item
.stateMask
= LVIS_FOCUSED
;
2509 item
.state
= LVIS_FOCUSED
;
2510 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2513 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2516 /* it's not updated if already set */
2517 item
.stateMask
= LVIS_FOCUSED
;
2518 item
.state
= LVIS_FOCUSED
;
2519 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 1, (LPARAM
)&item
);
2522 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2525 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2528 item
.stateMask
= LVIS_FOCUSED
;
2529 item
.state
= LVIS_FOCUSED
;
2530 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 1, (LPARAM
)&item
);
2533 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2536 /* need to reset focused item first */
2537 item
.stateMask
= LVIS_FOCUSED
;
2539 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2542 item
.stateMask
= LVIS_FOCUSED
;
2543 item
.state
= LVIS_FOCUSED
;
2544 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 2, (LPARAM
)&item
);
2547 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2550 item
.stateMask
= LVIS_FOCUSED
;
2552 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2555 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2558 /* 2. same tests, with LVM_SETITEM */
2559 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2560 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SINGLESEL
);
2562 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2565 item
.stateMask
= LVIS_FOCUSED
;
2566 item
.state
= LVIS_FOCUSED
;
2567 item
.mask
= LVIF_STATE
;
2568 item
.iItem
= item
.iSubItem
= 0;
2569 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2572 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2575 /* it's not updated if already set */
2576 item
.stateMask
= LVIS_FOCUSED
;
2577 item
.state
= LVIS_FOCUSED
;
2578 item
.mask
= LVIF_STATE
;
2581 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2584 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2587 r
= SendMessageA(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
2590 item
.stateMask
= LVIS_FOCUSED
;
2591 item
.state
= LVIS_FOCUSED
;
2592 item
.mask
= LVIF_STATE
;
2595 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2598 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2601 /* need to reset focused item first */
2602 item
.stateMask
= LVIS_FOCUSED
;
2604 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2607 item
.stateMask
= LVIS_FOCUSED
;
2608 item
.state
= LVIS_FOCUSED
;
2609 item
.mask
= LVIF_STATE
;
2612 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
2615 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2618 item
.stateMask
= LVIS_FOCUSED
;
2620 r
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2623 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2626 DestroyWindow(hwnd
);
2629 static void test_subitem_rect(void)
2637 /* test LVM_GETSUBITEMRECT for header */
2638 hwnd
= create_listview_control(LVS_REPORT
);
2639 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2640 /* add some columns */
2641 memset(&col
, 0, sizeof(LVCOLUMNA
));
2642 col
.mask
= LVCF_WIDTH
;
2644 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
2647 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 1, (LPARAM
)&col
);
2650 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 2, (LPARAM
)&col
);
2652 /* item = -1 means header, subitem index is 1 based */
2653 SetRect(&rect
, LVIR_BOUNDS
, 0, 0, 0);
2654 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2657 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2658 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2661 expect(100, rect
.left
);
2662 expect(250, rect
.right
);
2663 expect(3, rect
.top
);
2665 SetRect(&rect
, LVIR_BOUNDS
, 2, 0, 0);
2666 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2669 expect(250, rect
.left
);
2670 expect(450, rect
.right
);
2671 expect(3, rect
.top
);
2673 /* item LVS_REPORT padding isn't applied to subitems */
2674 insert_item(hwnd
, 0);
2676 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2677 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2679 expect(100, rect
.left
);
2680 expect(250, rect
.right
);
2682 SetRect(&rect
, LVIR_ICON
, 1, 0, 0);
2683 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2685 /* no icon attached - zero width rectangle, with no left padding */
2686 expect(100, rect
.left
);
2687 expect(100, rect
.right
);
2689 SetRect(&rect
, LVIR_LABEL
, 1, 0, 0);
2690 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2692 /* same as full LVIR_BOUNDS */
2693 expect(100, rect
.left
);
2694 expect(250, rect
.right
);
2696 r
= SendMessageA(hwnd
, LVM_SCROLL
, 10, 0);
2697 ok(r
, "got %d\n", r
);
2699 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2700 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2702 expect(90, rect
.left
);
2703 expect(240, rect
.right
);
2705 SendMessageA(hwnd
, LVM_SCROLL
, -10, 0);
2707 /* test header interaction */
2708 subclass_header(hwnd
);
2709 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2711 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2712 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2715 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2716 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2719 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2720 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -10, (LPARAM
)&rect
);
2723 SetRect(&rect
, LVIR_BOUNDS
, 1, 0, 0);
2724 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 20, (LPARAM
)&rect
);
2727 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getsubitemrect_seq
, "LVM_GETSUBITEMRECT negative index", FALSE
);
2729 DestroyWindow(hwnd
);
2731 /* test subitem rects after re-arranging columns */
2732 hwnd
= create_listview_control(LVS_REPORT
);
2733 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2734 memset(&col
, 0, sizeof(LVCOLUMNA
));
2735 col
.mask
= LVCF_WIDTH
;
2738 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
2742 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 1, (LPARAM
)&col
);
2746 r
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 2, (LPARAM
)&col
);
2749 insert_item(hwnd
, 0);
2750 insert_item(hwnd
, 1);
2752 /* wrong item is refused for main item */
2753 SetRect(&rect
, LVIR_BOUNDS
, 0, -1, -1);
2754 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 2, (LPARAM
)&rect
);
2757 /* for subitems rectangle is calculated even if there's no item added */
2758 SetRect(&rect
, LVIR_BOUNDS
, 1, -1, -1);
2759 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 1, (LPARAM
)&rect
);
2762 SetRect(&rect2
, LVIR_BOUNDS
, 1, -1, -1);
2763 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 2, (LPARAM
)&rect2
);
2765 expect(rect
.right
, rect2
.right
);
2766 expect(rect
.left
, rect2
.left
);
2767 expect(rect
.bottom
, rect2
.top
);
2768 ok(rect2
.bottom
> rect2
.top
, "expected not zero height\n");
2770 arr
[0] = 1; arr
[1] = 0; arr
[2] = 2;
2771 r
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 3, (LPARAM
)arr
);
2774 SetRect(&rect
, LVIR_BOUNDS
, 0, -1, -1);
2775 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2777 expect(0, rect
.left
);
2778 expect(600, rect
.right
);
2780 SetRect(&rect
, LVIR_BOUNDS
, 1, -1, -1);
2781 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2783 expect(0, rect
.left
);
2784 expect(200, rect
.right
);
2786 SetRect(&rect2
, LVIR_BOUNDS
, 1, -1, -1);
2787 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 1, (LPARAM
)&rect2
);
2789 expect(0, rect2
.left
);
2790 expect(200, rect2
.right
);
2791 /* items are of the same height */
2792 ok(rect2
.top
> 0, "expected positive item height\n");
2793 expect(rect
.bottom
, rect2
.top
);
2794 expect(rect
.bottom
* 2 - rect
.top
, rect2
.bottom
);
2796 SetRect(&rect
, LVIR_BOUNDS
, 2, -1, -1);
2797 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2799 expect(300, rect
.left
);
2800 expect(600, rect
.right
);
2802 DestroyWindow(hwnd
);
2804 /* try it for non LVS_REPORT style */
2805 hwnd
= CreateWindowA("SysListView32", "Test", LVS_ICON
, 0, 0, 100, 100, NULL
, NULL
,
2806 GetModuleHandleA(NULL
), 0);
2807 SetRect(&rect
, LVIR_BOUNDS
, 1, -10, -10);
2808 r
= SendMessageA(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2810 /* rect is unchanged */
2811 expect(0, rect
.left
);
2812 expect(-10, rect
.right
);
2813 expect(1, rect
.top
);
2814 expect(-10, rect
.bottom
);
2815 DestroyWindow(hwnd
);
2818 /* comparison callback for test_sorting */
2819 static INT WINAPI
test_CallBackCompare(LPARAM first
, LPARAM second
, LPARAM lParam
)
2821 if (first
== second
) return 0;
2822 return (first
> second
? 1 : -1);
2825 static void test_sorting(void)
2831 static CHAR names
[][5] = {"A", "B", "C", "D", "0"};
2834 hwnd
= create_listview_control(LVS_REPORT
);
2835 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2837 /* insert some items */
2838 item
.mask
= LVIF_PARAM
| LVIF_STATE
;
2839 item
.state
= LVIS_SELECTED
;
2843 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
2846 item
.mask
= LVIF_PARAM
;
2850 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
2853 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
2854 item
.state
= LVIS_SELECTED
;
2858 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
2861 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2864 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2867 r
= SendMessageA(hwnd
, LVM_SORTITEMS
, 0, (LPARAM
)test_CallBackCompare
);
2870 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2872 r
= SendMessageA(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2874 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_SELECTED
);
2876 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_SELECTED
);
2877 expect(LVIS_SELECTED
, r
);
2878 r
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_SELECTED
);
2879 expect(LVIS_SELECTED
, r
);
2881 DestroyWindow(hwnd
);
2883 /* switch to LVS_SORTASCENDING when some items added */
2884 hwnd
= create_listview_control(LVS_REPORT
);
2885 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2887 item
.mask
= LVIF_TEXT
;
2890 item
.pszText
= names
[1];
2891 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
2894 item
.mask
= LVIF_TEXT
;
2897 item
.pszText
= names
[2];
2898 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
2901 item
.mask
= LVIF_TEXT
;
2904 item
.pszText
= names
[0];
2905 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
2908 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2909 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
2910 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2911 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2913 /* no sorting performed when switched to LVS_SORTASCENDING */
2914 item
.mask
= LVIF_TEXT
;
2916 item
.pszText
= buff
;
2917 item
.cchTextMax
= sizeof(buff
);
2918 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2920 ok(lstrcmpA(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2923 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2925 ok(lstrcmpA(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2928 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2930 ok(lstrcmpA(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2932 /* adding new item doesn't resort list */
2933 item
.mask
= LVIF_TEXT
;
2936 item
.pszText
= names
[3];
2937 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
2940 item
.mask
= LVIF_TEXT
;
2942 item
.pszText
= buff
;
2943 item
.cchTextMax
= sizeof(buff
);
2944 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2946 ok(lstrcmpA(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2949 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2951 ok(lstrcmpA(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2954 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2956 ok(lstrcmpA(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2959 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2961 ok(lstrcmpA(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
2963 /* corner case - item should be placed at first position */
2964 item
.mask
= LVIF_TEXT
;
2967 item
.pszText
= names
[4];
2968 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
2972 item
.pszText
= buff
;
2973 item
.cchTextMax
= sizeof(buff
);
2974 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2976 ok(lstrcmpA(buff
, names
[4]) == 0, "Expected '%s', got '%s'\n", names
[4], buff
);
2979 item
.pszText
= buff
;
2980 item
.cchTextMax
= sizeof(buff
);
2981 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2983 ok(lstrcmpA(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2986 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2988 ok(lstrcmpA(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2991 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2993 ok(lstrcmpA(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2996 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
2998 ok(lstrcmpA(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
3000 DestroyWindow(hwnd
);
3003 static void test_ownerdata(void)
3005 static char test_str
[] = "test";
3008 LONG_PTR style
, ret
;
3012 /* it isn't possible to set LVS_OWNERDATA after creation */
3015 win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
3019 hwnd
= create_listview_control(LVS_REPORT
);
3020 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3021 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3022 ok(!(style
& LVS_OWNERDATA
) && style
, "LVS_OWNERDATA isn't expected\n");
3024 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3026 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
3027 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
3028 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
3029 "try to switch to LVS_OWNERDATA seq", FALSE
);
3031 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3032 ok(!(style
& LVS_OWNERDATA
), "LVS_OWNERDATA isn't expected\n");
3033 DestroyWindow(hwnd
);
3036 /* try to set LVS_OWNERDATA after creation just having it */
3037 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3038 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3039 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3040 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
3042 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3044 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
3045 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
3046 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
3047 "try to switch to LVS_OWNERDATA seq", FALSE
);
3048 DestroyWindow(hwnd
);
3050 /* try to remove LVS_OWNERDATA after creation just having it */
3053 win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
3057 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3058 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3059 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3060 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
3062 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3064 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_OWNERDATA
);
3065 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
3066 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
3067 "try to switch to LVS_OWNERDATA seq", FALSE
);
3068 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3069 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
3070 DestroyWindow(hwnd
);
3073 /* try select an item */
3074 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3075 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3076 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3078 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3080 memset(&item
, 0, sizeof(item
));
3081 item
.stateMask
= LVIS_SELECTED
;
3082 item
.state
= LVIS_SELECTED
;
3083 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3085 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
3087 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
3089 DestroyWindow(hwnd
);
3091 /* LVM_SETITEM and LVM_SETITEMTEXT is unsupported on LVS_OWNERDATA */
3092 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3093 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3094 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3096 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
3098 memset(&item
, 0, sizeof(item
));
3099 item
.mask
= LVIF_STATE
;
3101 item
.stateMask
= LVIS_SELECTED
;
3102 item
.state
= LVIS_SELECTED
;
3103 res
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
3105 memset(&item
, 0, sizeof(item
));
3106 item
.pszText
= test_str
;
3107 res
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
3109 DestroyWindow(hwnd
);
3111 /* check notifications after focused/selected changed */
3112 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3113 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3114 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 20, 0);
3117 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3119 memset(&item
, 0, sizeof(item
));
3120 item
.stateMask
= LVIS_SELECTED
;
3121 item
.state
= LVIS_SELECTED
;
3122 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3125 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_select_focus_parent_seq
,
3126 "ownerdata select notification", TRUE
);
3128 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3130 memset(&item
, 0, sizeof(item
));
3131 item
.stateMask
= LVIS_FOCUSED
;
3132 item
.state
= LVIS_FOCUSED
;
3133 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3136 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_select_focus_parent_seq
,
3137 "ownerdata focus notification", TRUE
);
3139 /* select all, check notifications */
3140 item
.stateMask
= LVIS_SELECTED
;
3142 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3145 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3147 item
.stateMask
= LVIS_SELECTED
;
3148 item
.state
= LVIS_SELECTED
;
3150 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3151 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3153 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3154 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3155 ok(g_nmlistview
.uNewState
== LVIS_SELECTED
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3156 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3157 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3158 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3159 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3161 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3162 "ownerdata select all notification", FALSE
);
3164 /* select all again, note that all items are selected already */
3165 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3166 item
.stateMask
= LVIS_SELECTED
;
3167 item
.state
= LVIS_SELECTED
;
3169 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3170 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3172 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3173 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3174 ok(g_nmlistview
.uNewState
== LVIS_SELECTED
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3175 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3176 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3177 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3178 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3180 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3181 "ownerdata select all notification", FALSE
);
3184 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3185 item
.stateMask
= LVIS_SELECTED
;
3188 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3189 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3191 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3192 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3193 ok(g_nmlistview
.uNewState
== 0, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3194 ok(g_nmlistview
.uOldState
== LVIS_SELECTED
, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3195 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3196 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3197 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3199 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_deselect_all_parent_seq
,
3200 "ownerdata deselect all notification", TRUE
);
3202 /* nothing selected, deselect all again */
3203 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3204 item
.stateMask
= LVIS_SELECTED
;
3207 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3210 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "ownerdata deselect all notification", FALSE
);
3212 /* select one, then deselect all */
3213 item
.stateMask
= LVIS_SELECTED
;
3214 item
.state
= LVIS_SELECTED
;
3215 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3217 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3218 item
.stateMask
= LVIS_SELECTED
;
3221 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3222 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3224 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3225 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3226 ok(g_nmlistview
.uNewState
== 0, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3227 ok(g_nmlistview
.uOldState
== LVIS_SELECTED
, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3228 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3229 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3230 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3232 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_deselect_all_parent_seq
,
3233 "ownerdata select all notification", TRUE
);
3235 /* remove focused, try to focus all */
3236 item
.stateMask
= LVIS_FOCUSED
;
3237 item
.state
= LVIS_FOCUSED
;
3238 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3240 item
.stateMask
= LVIS_FOCUSED
;
3242 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3244 item
.stateMask
= LVIS_FOCUSED
;
3245 res
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_FOCUSED
);
3248 /* setting all to focused returns failure value */
3249 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3250 item
.stateMask
= LVIS_FOCUSED
;
3251 item
.state
= LVIS_FOCUSED
;
3253 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3256 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3257 "ownerdata focus all notification", FALSE
);
3259 /* focus single item, remove all */
3260 item
.stateMask
= LVIS_FOCUSED
;
3261 item
.state
= LVIS_FOCUSED
;
3262 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3264 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3265 item
.stateMask
= LVIS_FOCUSED
;
3268 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3269 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3271 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3272 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3273 ok(g_nmlistview
.uNewState
== 0, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3274 ok(g_nmlistview
.uOldState
== LVIS_FOCUSED
, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3275 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3276 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3277 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3279 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_defocus_all_parent_seq
,
3280 "ownerdata remove focus all notification", TRUE
);
3283 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3284 item
.stateMask
= LVIS_CUT
;
3285 item
.state
= LVIS_CUT
;
3287 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3288 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3290 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3291 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3292 ok(g_nmlistview
.uNewState
== LVIS_CUT
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3293 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3294 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3295 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3296 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3298 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3299 "ownerdata cut all notification", FALSE
);
3301 /* all marked cut, try again */
3302 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3303 item
.stateMask
= LVIS_CUT
;
3304 item
.state
= LVIS_CUT
;
3306 memset(&g_nmlistview
, 0xcc, sizeof(g_nmlistview
));
3307 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
3309 ok(g_nmlistview
.iItem
== -1, "got item %d\n", g_nmlistview
.iItem
);
3310 ok(g_nmlistview
.iSubItem
== 0, "got subitem %d\n", g_nmlistview
.iSubItem
);
3311 ok(g_nmlistview
.uNewState
== LVIS_CUT
, "got new state 0x%08x\n", g_nmlistview
.uNewState
);
3312 ok(g_nmlistview
.uOldState
== 0, "got old state 0x%08x\n", g_nmlistview
.uOldState
);
3313 ok(g_nmlistview
.uChanged
== LVIF_STATE
, "got changed 0x%08x\n", g_nmlistview
.uChanged
);
3314 ok(g_nmlistview
.ptAction
.x
== 0 && g_nmlistview
.ptAction
.y
== 0, "got wrong ptAction value\n");
3315 ok(g_nmlistview
.lParam
== 0, "got wrong lparam\n");
3317 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownerdata_setstate_all_parent_seq
,
3318 "ownerdata cut all notification #2", FALSE
);
3320 DestroyWindow(hwnd
);
3322 /* check notifications on LVM_GETITEM */
3323 /* zero callback mask */
3324 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3325 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3326 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3329 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3331 memset(&item
, 0, sizeof(item
));
3332 item
.stateMask
= LVIS_SELECTED
;
3333 item
.mask
= LVIF_STATE
;
3334 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3337 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3338 "ownerdata getitem selected state 1", FALSE
);
3340 /* non zero callback mask but not we asking for */
3341 res
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_OVERLAYMASK
, 0);
3344 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3346 memset(&item
, 0, sizeof(item
));
3347 item
.stateMask
= LVIS_SELECTED
;
3348 item
.mask
= LVIF_STATE
;
3349 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3352 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3353 "ownerdata getitem selected state 2", FALSE
);
3355 /* LVIS_OVERLAYMASK callback mask, asking for index */
3356 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3358 memset(&item
, 0, sizeof(item
));
3359 item
.stateMask
= LVIS_OVERLAYMASK
;
3360 item
.mask
= LVIF_STATE
;
3361 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3364 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
3365 "ownerdata getitem selected state 2", FALSE
);
3367 DestroyWindow(hwnd
);
3369 /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
3370 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_SORTASCENDING
| LVS_REPORT
);
3371 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3372 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3373 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
3374 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
3375 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SORTASCENDING
);
3376 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3377 ok(!(style
& LVS_SORTASCENDING
), "Expected LVS_SORTASCENDING not set\n");
3378 DestroyWindow(hwnd
);
3379 /* apparently it's allowed to switch these style on after creation */
3380 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3381 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3382 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3383 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
3384 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
3385 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3386 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
3387 DestroyWindow(hwnd
);
3389 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3390 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3391 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3392 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
3393 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTDESCENDING
);
3394 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3395 ok(style
& LVS_SORTDESCENDING
, "Expected LVS_SORTDESCENDING to be set\n");
3396 DestroyWindow(hwnd
);
3398 /* The focused item is updated after the invalidation */
3399 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3400 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3401 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 3, 0);
3404 memset(&item
, 0, sizeof(item
));
3405 item
.stateMask
= LVIS_FOCUSED
;
3406 item
.state
= LVIS_FOCUSED
;
3407 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
3410 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3411 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 0, 0);
3413 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3414 "ownerdata setitemcount", FALSE
);
3416 res
= SendMessageA(hwnd
, LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
3418 DestroyWindow(hwnd
);
3421 static void test_norecompute(void)
3423 static CHAR testA
[] = "test";
3429 /* self containing control */
3430 hwnd
= create_listview_control(LVS_REPORT
);
3431 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3432 memset(&item
, 0, sizeof(item
));
3433 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
3435 item
.stateMask
= LVIS_SELECTED
;
3436 item
.state
= LVIS_SELECTED
;
3437 item
.pszText
= testA
;
3438 res
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3440 /* retrieve with LVIF_NORECOMPUTE */
3441 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
3443 item
.pszText
= buff
;
3444 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
3445 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3447 ok(lstrcmpA(buff
, testA
) == 0, "Expected (%s), got (%s)\n", testA
, buff
);
3449 item
.mask
= LVIF_TEXT
;
3451 item
.pszText
= LPSTR_TEXTCALLBACKA
;
3452 res
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3455 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
3457 item
.pszText
= buff
;
3458 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
3460 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3461 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3463 ok(item
.pszText
== LPSTR_TEXTCALLBACKA
, "Expected (%p), got (%p)\n",
3464 LPSTR_TEXTCALLBACKA
, (VOID
*)item
.pszText
);
3465 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq", FALSE
);
3467 DestroyWindow(hwnd
);
3470 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3471 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3473 item
.mask
= LVIF_STATE
;
3474 item
.stateMask
= LVIS_SELECTED
;
3475 item
.state
= LVIS_SELECTED
;
3477 res
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3480 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
3482 item
.pszText
= buff
;
3483 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
3484 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3485 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3487 ok(item
.pszText
== LPSTR_TEXTCALLBACKA
, "Expected (%p), got (%p)\n",
3488 LPSTR_TEXTCALLBACKA
, (VOID
*)item
.pszText
);
3489 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE
);
3491 DestroyWindow(hwnd
);
3494 static void test_nosortheader(void)
3499 hwnd
= create_listview_control(LVS_REPORT
);
3500 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3502 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
3503 ok(IsWindow(header
), "header expected\n");
3505 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3506 ok(style
& HDS_BUTTONS
, "expected header to have HDS_BUTTONS\n");
3508 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3509 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_NOSORTHEADER
);
3510 /* HDS_BUTTONS retained */
3511 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3512 ok(style
& HDS_BUTTONS
, "expected header to retain HDS_BUTTONS\n");
3514 DestroyWindow(hwnd
);
3516 /* create with LVS_NOSORTHEADER */
3517 hwnd
= create_listview_control(LVS_NOSORTHEADER
| LVS_REPORT
);
3518 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3520 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
3521 ok(IsWindow(header
), "header expected\n");
3523 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3524 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
3526 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3527 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_NOSORTHEADER
);
3528 /* not changed here */
3529 style
= GetWindowLongPtrA(header
, GWL_STYLE
);
3530 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
3532 DestroyWindow(hwnd
);
3535 static void test_setredraw(void)
3543 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
3544 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3546 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
3547 ListView seems to handle it internally without DefWinProc */
3549 /* default value first */
3550 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3553 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3554 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
3555 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3557 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
3558 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
3559 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3562 /* check update rect after redrawing */
3563 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3565 InvalidateRect(hwnd
, NULL
, FALSE
);
3566 RedrawWindow(hwnd
, NULL
, NULL
, RDW_UPDATENOW
);
3567 rect
.right
= rect
.bottom
= 1;
3568 GetUpdateRect(hwnd
, &rect
, FALSE
);
3569 expect(0, rect
.right
);
3570 expect(0, rect
.bottom
);
3573 hdc
= GetWindowDC(hwndparent
);
3574 ret
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
3576 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3578 ret
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
3580 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, TRUE
, 0);
3582 ReleaseDC(hwndparent
, hdc
);
3584 /* check notification messages to show that repainting is disabled */
3585 ret
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
3587 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3589 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3591 InvalidateRect(hwnd
, NULL
, TRUE
);
3593 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3594 "redraw after WM_SETREDRAW (FALSE)", FALSE
);
3596 ret
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
3598 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3599 InvalidateRect(hwnd
, NULL
, TRUE
);
3601 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
3602 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE
);
3604 /* message isn't forwarded to header */
3605 subclass_header(hwnd
);
3606 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3607 ret
= SendMessageA(hwnd
, WM_SETREDRAW
, FALSE
, 0);
3609 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, setredraw_seq
,
3610 "WM_SETREDRAW: not forwarded to header", FALSE
);
3612 DestroyWindow(hwnd
);
3615 static void test_hittest(void)
3621 static CHAR text
[] = "1234567890ABCDEFGHIJKLMNOPQRST";
3625 HIMAGELIST himl
, himl2
;
3628 hwnd
= create_listview_control(LVS_REPORT
);
3629 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3631 /* LVS_REPORT with a single subitem (2 columns) */
3632 insert_column(hwnd
, 0);
3633 insert_column(hwnd
, 1);
3634 insert_item(hwnd
, 0);
3637 /* the only purpose of that line is to be as long as a half item rect */
3638 item
.pszText
= text
;
3639 r
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
3642 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
3644 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
3647 SetRect(&bounds
, LVIR_BOUNDS
, 0, 0, 0);
3648 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&bounds
);
3650 ok(bounds
.bottom
- bounds
.top
> 0, "Expected non zero item height\n");
3651 ok(bounds
.right
- bounds
.left
> 0, "Expected non zero item width\n");
3652 r
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, TRUE
, 0);
3654 ok(bounds
.bottom
- bounds
.top
== vert
,
3655 "Vertical spacing inconsistent (%d != %d)\n", bounds
.bottom
- bounds
.top
, vert
);
3656 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pos
);
3659 /* LVS_EX_FULLROWSELECT not set, no icons attached */
3661 /* outside columns by x position - valid is [0, 199] */
3663 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3664 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TOLEFT
, 0, FALSE
, FALSE
);
3665 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3667 x
= pos
.x
+ 50; /* column half width */
3668 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3669 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMLABEL
, 0, FALSE
, FALSE
);
3670 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3671 x
= pos
.x
+ 150; /* outside column */
3672 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3673 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
3674 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3675 y
= (bounds
.bottom
- bounds
.top
) / 2;
3676 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
3677 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3678 /* outside possible client rectangle (to right) */
3680 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3681 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
3682 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3683 y
= (bounds
.bottom
- bounds
.top
) / 2;
3684 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
3685 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3686 /* subitem returned with -1 item too */
3688 y
= bounds
.top
- vert
;
3689 test_lvm_subitemhittest(hwnd
, x
, y
, -1, 1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3690 test_lvm_subitemhittest(hwnd
, x
, y
- vert
+ 1, -1, 1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3691 /* return values appear to underflow with negative indices */
3695 test_lvm_subitemhittest(hwnd
, x
, y
, i
, 1, LVHT_ONITEMLABEL
, TRUE
, FALSE
, TRUE
);
3696 test_lvm_subitemhittest(hwnd
, x
, y
- vert
+ 1, i
, 1, LVHT_ONITEMLABEL
, TRUE
, FALSE
, TRUE
);
3700 /* parent client area is 100x100 by default */
3701 MoveWindow(hwnd
, 0, 0, 300, 100, FALSE
);
3702 x
= pos
.x
+ 150; /* outside column */
3703 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3704 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, 0, FALSE
, FALSE
);
3705 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3706 y
= (bounds
.bottom
- bounds
.top
) / 2;
3707 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, 0, FALSE
, TRUE
);
3708 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3709 /* the same with LVS_EX_FULLROWSELECT */
3710 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
3711 x
= pos
.x
+ 150; /* outside column */
3712 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3713 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEM
, LVHT_ONITEMLABEL
, FALSE
, FALSE
);
3714 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3715 y
= (bounds
.bottom
- bounds
.top
) / 2;
3716 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3717 MoveWindow(hwnd
, 0, 0, 100, 100, FALSE
);
3718 x
= pos
.x
+ 150; /* outside column */
3719 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3720 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
3721 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3722 y
= (bounds
.bottom
- bounds
.top
) / 2;
3723 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
3724 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
);
3725 /* outside possible client rectangle (to right) */
3727 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3728 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, FALSE
);
3729 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3730 y
= (bounds
.bottom
- bounds
.top
) / 2;
3731 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, 0, FALSE
, TRUE
);
3732 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
);
3733 /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
3734 himl
= ImageList_Create(16, 16, 0, 4, 4);
3735 ok(himl
!= NULL
, "failed to create imagelist\n");
3736 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
3737 ok(hbmp
!= NULL
, "failed to create bitmap\n");
3738 r
= ImageList_Add(himl
, hbmp
, 0);
3739 ok(r
== 0, "should be zero\n");
3740 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
3741 ok(hbmp
!= NULL
, "failed to create bitmap\n");
3742 r
= ImageList_Add(himl
, hbmp
, 0);
3743 ok(r
== 1, "should be one\n");
3745 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
3748 item
.mask
= LVIF_IMAGE
;
3752 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
3756 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3757 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, 0, FALSE
, FALSE
);
3758 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
3759 y
= (bounds
.bottom
- bounds
.top
) / 2;
3760 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
3762 /* state icons indices are 1 based, check with valid index */
3763 item
.mask
= LVIF_STATE
;
3764 item
.state
= INDEXTOSTATEIMAGEMASK(1);
3765 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3768 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
3772 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3773 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, 0, FALSE
, FALSE
);
3774 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
3775 y
= (bounds
.bottom
- bounds
.top
) / 2;
3776 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
);
3778 himl2
= (HIMAGELIST
)SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, 0);
3779 ok(himl2
== himl
, "should return handle\n");
3781 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
3785 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
3786 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMICON
, 0, FALSE
, FALSE
);
3787 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
);
3788 y
= (bounds
.bottom
- bounds
.top
) / 2;
3789 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
);
3791 DestroyWindow(hwnd
);
3794 static void test_getviewrect(void)
3801 hwnd
= create_listview_control(LVS_REPORT
);
3802 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3805 r
= SendMessageA(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
3808 insert_column(hwnd
, 0);
3809 insert_column(hwnd
, 1);
3811 memset(&item
, 0, sizeof(item
));
3814 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3815 ok(!r
, "got %d\n", r
);
3817 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
3819 r
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(120, 0));
3822 SetRect(&rect
, -1, -1, -1, -1);
3823 r
= SendMessageA(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
3825 /* left is set to (2e31-1) - XP SP2 */
3826 expect(0, rect
.right
);
3827 expect(0, rect
.top
);
3828 expect(0, rect
.bottom
);
3830 /* switch to LVS_ICON */
3831 SetWindowLongA(hwnd
, GWL_STYLE
, GetWindowLongA(hwnd
, GWL_STYLE
) & ~LVS_REPORT
);
3833 SetRect(&rect
, -1, -1, -1, -1);
3834 r
= SendMessageA(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
3836 expect(0, rect
.left
);
3837 expect(0, rect
.top
);
3838 /* precise value differs for 2k, XP and Vista */
3839 ok(rect
.bottom
> 0, "Expected positive bottom value, got %d\n", rect
.bottom
);
3840 ok(rect
.right
> 0, "Expected positive right value, got %d\n", rect
.right
);
3842 DestroyWindow(hwnd
);
3845 static void test_getitemposition(void)
3852 hwnd
= create_listview_control(LVS_REPORT
);
3853 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3854 header
= subclass_header(hwnd
);
3856 /* LVS_REPORT, single item, no columns added */
3857 insert_item(hwnd
, 0);
3859 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3862 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
3864 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq1
, "get item position 1", FALSE
);
3866 /* LVS_REPORT, single item, single column */
3867 insert_column(hwnd
, 0);
3869 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3872 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
3874 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq2
, "get item position 2", TRUE
);
3876 SetRectEmpty(&rect
);
3877 r
= SendMessageA(header
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3878 ok(r
, "got %d\n", r
);
3881 /* offset by header height */
3882 expect(rect
.bottom
- rect
.top
, pt
.y
);
3884 DestroyWindow(hwnd
);
3887 static void test_columnscreation(void)
3892 hwnd
= create_listview_control(LVS_REPORT
);
3893 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3895 insert_item(hwnd
, 0);
3897 /* headers columns aren't created automatically */
3898 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
3899 ok(IsWindow(header
), "Expected header handle\n");
3900 r
= SendMessageA(header
, HDM_GETITEMCOUNT
, 0, 0);
3903 DestroyWindow(hwnd
);
3906 static void test_getitemrect(void)
3909 HIMAGELIST himl
, himl_ret
;
3918 /* rectangle isn't empty for empty text items */
3919 hwnd
= create_listview_control(LVS_LIST
);
3920 memset(&item
, 0, sizeof(item
));
3923 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3925 rect
.left
= LVIR_LABEL
;
3926 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3928 expect(0, rect
.left
);
3929 expect(0, rect
.top
);
3930 /* estimate it as width / height ratio */
3932 ok((rect
.right
/ rect
.bottom
) >= 5, "got right %d, bottom %d\n", rect
.right
, rect
.bottom
);
3933 DestroyWindow(hwnd
);
3935 hwnd
= create_listview_control(LVS_REPORT
);
3936 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3939 memset(&item
, 0, sizeof(item
));
3942 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3945 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
3946 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3949 /* zero width rectangle with no padding */
3950 expect(0, rect
.left
);
3951 expect(0, rect
.right
);
3953 insert_column(hwnd
, 0);
3954 insert_column(hwnd
, 1);
3956 col
.mask
= LVCF_WIDTH
;
3958 r
= SendMessageA(hwnd
, LVM_SETCOLUMNA
, 0, (LPARAM
)&col
);
3961 col
.mask
= LVCF_WIDTH
;
3963 r
= SendMessageA(hwnd
, LVM_SETCOLUMNA
, 1, (LPARAM
)&col
);
3966 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
3967 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3970 /* still no left padding */
3971 expect(0, rect
.left
);
3972 expect(150, rect
.right
);
3974 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
3975 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3978 expect(2, rect
.left
);
3980 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
3981 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3983 /* padding, column width */
3984 expect(2, rect
.left
);
3985 expect(50, rect
.right
);
3987 /* no icons attached */
3988 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
3989 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3992 expect(2, rect
.left
);
3993 expect(2, rect
.right
);
3996 order
[0] = 1; order
[1] = 0;
3997 r
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
4000 r
= SendMessageA(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
4002 /* 1 indexed column width + padding */
4004 /* rect is at zero too */
4005 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4006 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4008 expect(0, rect
.left
);
4009 /* just width sum */
4010 expect(150, rect
.right
);
4012 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4013 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4015 /* column width + padding */
4016 expect(102, rect
.left
);
4018 /* back to initial order */
4019 order
[0] = 0; order
[1] = 1;
4020 r
= SendMessageA(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
4024 himl
= ImageList_Create(16, 16, 0, 2, 2);
4025 ok(himl
!= NULL
, "failed to create imagelist\n");
4026 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
4027 ok(hbm
!= NULL
, "failed to create bitmap\n");
4028 r
= ImageList_Add(himl
, hbm
, 0);
4030 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
4031 ok(hbm
!= NULL
, "failed to create bitmap\n");
4032 r
= ImageList_Add(himl
, hbm
, 0);
4035 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
4038 item
.mask
= LVIF_STATE
;
4039 item
.state
= INDEXTOSTATEIMAGEMASK(1);
4040 item
.stateMask
= LVIS_STATEIMAGEMASK
;
4043 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4047 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4048 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4050 /* padding + stateicon width */
4051 expect(18, rect
.left
);
4052 expect(18, rect
.right
);
4054 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4055 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4057 /* padding + stateicon width -> column width */
4058 expect(18, rect
.left
);
4059 expect(50, rect
.right
);
4061 himl_ret
= (HIMAGELIST
)SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, 0);
4062 ok(himl_ret
== himl
, "got %p, expected %p\n", himl_ret
, himl
);
4064 r
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
4067 item
.mask
= LVIF_STATE
| LVIF_IMAGE
;
4070 item
.stateMask
= ~0;
4073 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4077 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4078 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4080 /* padding, icon width */
4081 expect(2, rect
.left
);
4082 expect(18, rect
.right
);
4084 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4085 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4087 /* padding + icon width -> column width */
4088 expect(18, rect
.left
);
4089 expect(50, rect
.right
);
4092 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4093 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4095 /* padding, column width */
4096 expect(2, rect
.left
);
4097 expect(50, rect
.right
);
4099 /* try with indentation */
4100 item
.mask
= LVIF_INDENT
;
4104 r
= SendMessageA(hwnd
, LVM_SETITEMA
, 0, (LPARAM
)&item
);
4108 SetRect(&rect
, LVIR_BOUNDS
, -1, -1, -1);
4109 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4111 /* padding + 1 icon width, column width */
4112 expect(0, rect
.left
);
4113 expect(150, rect
.right
);
4116 SetRect(&rect
, LVIR_SELECTBOUNDS
, -1, -1, -1);
4117 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4119 /* padding + 1 icon width, column width */
4120 expect(2 + 16, rect
.left
);
4121 expect(50, rect
.right
);
4124 SetRect(&rect
, LVIR_LABEL
, -1, -1, -1);
4125 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4127 /* padding + 2 icon widths, column width */
4128 expect(2 + 16*2, rect
.left
);
4129 expect(50, rect
.right
);
4132 SetRect(&rect
, LVIR_ICON
, -1, -1, -1);
4133 r
= SendMessageA(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
4135 /* padding + 1 icon width indentation, icon width */
4136 expect(2 + 16, rect
.left
);
4137 expect(34, rect
.right
);
4139 DestroyWindow(hwnd
);
4142 static void test_editbox(void)
4144 static CHAR testitemA
[] = "testitem";
4145 static CHAR testitem1A
[] = "testitem_quitelongname";
4146 static CHAR testitem2A
[] = "testITEM_quitelongname";
4147 static CHAR buffer
[25];
4148 HWND hwnd
, hwndedit
, hwndedit2
, header
;
4152 hwnd
= create_listview_control(LVS_EDITLABELS
| LVS_REPORT
);
4153 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4155 insert_column(hwnd
, 0);
4157 memset(&item
, 0, sizeof(item
));
4158 item
.mask
= LVIF_TEXT
;
4159 item
.pszText
= testitemA
;
4162 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4165 /* test notifications without edit created */
4166 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4167 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_SETFOCUS
), (LPARAM
)0xdeadbeef);
4169 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
4170 "edit box WM_COMMAND (EN_SETFOCUS), no edit created", FALSE
);
4171 /* same thing but with valid window */
4172 hwndedit
= CreateWindowA("Edit", "Test edit", WS_VISIBLE
| WS_CHILD
, 0, 0, 20,
4173 10, hwnd
, (HMENU
)1, (HINSTANCE
)GetWindowLongPtrA(hwnd
, GWLP_HINSTANCE
), 0);
4174 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4175 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_SETFOCUS
), (LPARAM
)hwndedit
);
4177 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
4178 "edit box WM_COMMAND (EN_SETFOCUS), no edit created #2", FALSE
);
4179 DestroyWindow(hwndedit
);
4181 /* setting focus is necessary */
4183 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4184 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4186 /* test children Z-order after Edit box created */
4187 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4188 ok(IsWindow(header
), "Expected header to be created\n");
4189 ok(GetTopWindow(hwnd
) == header
, "Expected header to be on top\n");
4190 ok(GetNextWindow(header
, GW_HWNDNEXT
) == hwndedit
, "got %p\n", GetNextWindow(header
, GW_HWNDNEXT
));
4192 /* modify initial string */
4193 r
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
4196 /* edit window is resized and repositioned,
4197 check again for Z-order - it should be preserved */
4198 ok(GetTopWindow(hwnd
) == header
, "Expected header to be on top\n");
4199 ok(GetNextWindow(header
, GW_HWNDNEXT
) == hwndedit
, "got %p\n", GetNextWindow(header
, GW_HWNDNEXT
));
4201 /* return focus to listview */
4204 memset(&item
, 0, sizeof(item
));
4205 item
.mask
= LVIF_TEXT
;
4206 item
.pszText
= buffer
;
4207 item
.cchTextMax
= sizeof(buffer
);
4210 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
4213 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
4215 /* send LVM_EDITLABEL on already created edit */
4217 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4218 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4219 /* focus will be set to edit */
4220 ok(GetFocus() == hwndedit
, "Expected Edit window to be focused\n");
4221 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4222 ok(IsWindow(hwndedit2
), "Expected Edit window to be created\n");
4224 /* creating label disabled when control isn't focused */
4226 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4227 todo_wine
ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
4229 /* check EN_KILLFOCUS handling */
4230 memset(&item
, 0, sizeof(item
));
4231 item
.pszText
= testitemA
;
4234 r
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
4238 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4239 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4240 /* modify edit and notify control that it lost focus */
4241 r
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
4243 g_editbox_disp_info
.item
.pszText
= NULL
;
4244 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
4246 ok(g_editbox_disp_info
.item
.pszText
!= NULL
, "expected notification with not null text\n");
4248 memset(&item
, 0, sizeof(item
));
4249 item
.pszText
= buffer
;
4250 item
.cchTextMax
= sizeof(buffer
);
4253 r
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
4254 expect(lstrlenA(item
.pszText
), r
);
4255 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
4256 ok(!IsWindow(hwndedit
), "Expected Edit window to be freed\n");
4258 /* change item name to differ in casing only */
4260 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4261 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4262 /* modify edit and notify control that it lost focus */
4263 r
= SendMessageA(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem2A
);
4265 g_editbox_disp_info
.item
.pszText
= NULL
;
4266 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
4268 ok(g_editbox_disp_info
.item
.pszText
!= NULL
, "got %p\n", g_editbox_disp_info
.item
.pszText
);
4270 memset(&item
, 0, sizeof(item
));
4271 item
.pszText
= buffer
;
4272 item
.cchTextMax
= sizeof(buffer
);
4275 r
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
4276 expect(lstrlenA(item
.pszText
), r
);
4277 ok(strcmp(buffer
, testitem2A
) == 0, "got %s, expected %s\n", buffer
, testitem2A
);
4278 ok(!IsWindow(hwndedit
), "Expected Edit window to be freed\n");
4280 /* end edit without saving */
4282 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4283 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4284 r
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_ESCAPE
, 0);
4286 ok_sequence(sequences
, PARENT_SEQ_INDEX
, edit_end_nochange
,
4287 "edit box - end edit, no change, escape", TRUE
);
4288 /* end edit with saving */
4290 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4291 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4292 r
= SendMessageA(hwndedit
, WM_KEYDOWN
, VK_RETURN
, 0);
4294 ok_sequence(sequences
, PARENT_SEQ_INDEX
, edit_end_nochange
,
4295 "edit box - end edit, no change, return", TRUE
);
4297 memset(&item
, 0, sizeof(item
));
4298 item
.pszText
= buffer
;
4299 item
.cchTextMax
= sizeof(buffer
);
4302 r
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
4303 expect(lstrlenA(item
.pszText
), r
);
4304 ok(strcmp(buffer
, testitem2A
) == 0, "Expected item text to change\n");
4306 /* LVM_EDITLABEL with -1 destroys current edit */
4307 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_GETEDITCONTROL
, 0, 0);
4308 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
4309 /* no edit present */
4310 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, -1, 0);
4311 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
4312 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4313 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4315 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
4316 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, -1, 0);
4317 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
4318 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
4319 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
4320 /* check another negative value */
4321 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4322 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4323 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
4324 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, -2, 0);
4325 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
4326 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
4327 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
4328 /* and value greater than max item index */
4329 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4330 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4331 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
4332 r
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
4333 hwndedit2
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, r
, 0);
4334 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
4335 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
4336 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
4338 /* messaging tests */
4340 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4342 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4343 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4344 /* testing only sizing messages */
4345 ok_sequence(sequences
, EDITBOX_SEQ_INDEX
, editbox_create_pos
,
4346 "edit box create - sizing", FALSE
);
4348 /* WM_COMMAND with EN_KILLFOCUS isn't forwarded to parent */
4350 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4351 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
4352 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4353 r
= SendMessageA(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
4355 ok_sequence(sequences
, PARENT_SEQ_INDEX
, edit_end_nochange
,
4356 "edit box WM_COMMAND (EN_KILLFOCUS)", TRUE
);
4358 DestroyWindow(hwnd
);
4361 static void test_notifyformat(void)
4366 hwnd
= create_listview_control(LVS_REPORT
);
4367 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4369 /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
4370 CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
4371 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4373 SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
4375 r
= SendMessageA(hwnd
, LVM_SETUNICODEFORMAT
, 1, 0);
4377 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4380 r
= SendMessageA(hwnd
, LVM_SETUNICODEFORMAT
, 0, 0);
4382 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4387 win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
4388 DestroyWindow(hwnd
);
4392 DestroyWindow(hwnd
);
4394 /* test failure in parent WM_NOTIFYFORMAT */
4396 hwnd
= create_listview_control(LVS_REPORT
);
4397 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4398 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4399 ok(IsWindow(header
), "expected header to be created\n");
4400 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4402 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4403 ok( r
== 1, "Expected 1, got %d\n", r
);
4404 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
4405 ok(r
!= 0, "Expected valid format\n");
4407 notifyFormat
= NFR_UNICODE
;
4408 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
4409 expect(NFR_UNICODE
, r
);
4410 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4412 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4413 ok( r
== 1, "Expected 1, got %d\n", r
);
4415 notifyFormat
= NFR_ANSI
;
4416 r
= SendMessageA(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
4417 expect(NFR_ANSI
, r
);
4418 r
= SendMessageA(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4420 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4421 ok( r
== 1, "Expected 1, got %d\n", r
);
4423 DestroyWindow(hwnd
);
4425 hwndparentW
= create_parent_window(TRUE
);
4426 ok(IsWindow(hwndparentW
), "Unicode parent creation failed\n");
4427 if (!IsWindow(hwndparentW
)) return;
4430 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparentW
);
4431 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4432 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4433 ok(IsWindow(header
), "expected header to be created\n");
4434 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4436 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4438 DestroyWindow(hwnd
);
4439 /* receiving error code defaulting to ansi */
4441 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparentW
);
4442 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4443 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4444 ok(IsWindow(header
), "expected header to be created\n");
4445 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4447 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4449 DestroyWindow(hwnd
);
4450 /* receiving ansi code from unicode window, use it */
4451 notifyFormat
= NFR_ANSI
;
4452 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparentW
);
4453 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4454 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4455 ok(IsWindow(header
), "expected header to be created\n");
4456 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4458 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4460 DestroyWindow(hwnd
);
4461 /* unicode listview with ansi parent window */
4463 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparent
);
4464 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4465 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4466 ok(IsWindow(header
), "expected header to be created\n");
4467 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4469 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4471 DestroyWindow(hwnd
);
4472 /* unicode listview with ansi parent window, return error code */
4474 hwnd
= create_listview_controlW(LVS_REPORT
, hwndparent
);
4475 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4476 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
4477 ok(IsWindow(header
), "expected header to be created\n");
4478 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
4480 r
= SendMessageA(header
, HDM_GETUNICODEFORMAT
, 0, 0);
4482 DestroyWindow(hwnd
);
4484 DestroyWindow(hwndparentW
);
4487 static void test_indentation(void)
4493 hwnd
= create_listview_control(LVS_REPORT
);
4494 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4496 memset(&item
, 0, sizeof(item
));
4497 item
.mask
= LVIF_INDENT
;
4499 item
.iIndent
= I_INDENTCALLBACK
;
4500 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
4503 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4506 item
.mask
= LVIF_INDENT
;
4507 r
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
4510 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
4511 "get indent dispinfo", FALSE
);
4513 DestroyWindow(hwnd
);
4516 static INT CALLBACK
DummyCompareEx(LPARAM first
, LPARAM second
, LPARAM param
)
4521 static BOOL
is_below_comctl_5(void)
4526 hwnd
= create_listview_control(LVS_REPORT
);
4527 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4528 insert_item(hwnd
, 0);
4530 ret
= SendMessageA(hwnd
, LVM_SORTITEMSEX
, 0, (LPARAM
)&DummyCompareEx
);
4532 DestroyWindow(hwnd
);
4537 static void test_get_set_view(void)
4543 /* test style->view mapping */
4544 hwnd
= create_listview_control(LVS_REPORT
);
4545 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4547 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4548 expect(LV_VIEW_DETAILS
, ret
);
4550 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4552 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_REPORT
);
4553 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4554 expect(LV_VIEW_ICON
, ret
);
4556 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4557 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SMALLICON
);
4558 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4559 expect(LV_VIEW_SMALLICON
, ret
);
4561 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4562 SetWindowLongPtrA(hwnd
, GWL_STYLE
, (style
& ~LVS_SMALLICON
) | LVS_LIST
);
4563 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4564 expect(LV_VIEW_LIST
, ret
);
4566 /* switching view doesn't touch window style */
4567 ret
= SendMessageA(hwnd
, LVM_SETVIEW
, LV_VIEW_DETAILS
, 0);
4569 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4570 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
4571 ret
= SendMessageA(hwnd
, LVM_SETVIEW
, LV_VIEW_ICON
, 0);
4573 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4574 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
4575 ret
= SendMessageA(hwnd
, LVM_SETVIEW
, LV_VIEW_SMALLICON
, 0);
4577 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4578 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
4580 /* now change window style to see if view is remapped */
4581 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
4582 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SHOWSELALWAYS
);
4583 ret
= SendMessageA(hwnd
, LVM_GETVIEW
, 0, 0);
4584 expect(LV_VIEW_SMALLICON
, ret
);
4586 DestroyWindow(hwnd
);
4589 static void test_canceleditlabel(void)
4591 HWND hwnd
, hwndedit
;
4595 static CHAR test
[] = "test";
4596 static const CHAR test1
[] = "test1";
4598 hwnd
= create_listview_control(LVS_EDITLABELS
| LVS_REPORT
);
4599 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4601 insert_item(hwnd
, 0);
4603 /* try without edit created */
4604 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4605 ret
= SendMessageA(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
4607 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
4608 "cancel edit label without edit", FALSE
);
4610 /* cancel without data change */
4612 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4613 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
4614 ret
= SendMessageA(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
4616 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
4618 /* cancel after data change */
4619 memset(&itema
, 0, sizeof(itema
));
4620 itema
.pszText
= test
;
4621 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&itema
);
4624 hwndedit
= (HWND
)SendMessageA(hwnd
, LVM_EDITLABELA
, 0, 0);
4625 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
4626 ret
= SetWindowTextA(hwndedit
, test1
);
4628 ret
= SendMessageA(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
4630 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
4631 memset(&itema
, 0, sizeof(itema
));
4632 itema
.pszText
= buff
;
4633 itema
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
4634 ret
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&itema
);
4636 ok(strcmp(buff
, test1
) == 0, "Expected label text not to change\n");
4638 DestroyWindow(hwnd
);
4641 static void test_mapidindex(void)
4646 /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
4647 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_REPORT
);
4648 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4649 insert_item(hwnd
, 0);
4650 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4652 DestroyWindow(hwnd
);
4654 hwnd
= create_listview_control(LVS_REPORT
);
4655 ok(hwnd
!= NULL
, "failed to create a listview window\n");
4657 /* LVM_MAPINDEXTOID with invalid index */
4658 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4661 insert_item(hwnd
, 0);
4662 insert_item(hwnd
, 1);
4664 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, -1, 0);
4666 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 2, 0);
4669 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4671 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
4673 /* remove 0 indexed item, id retained */
4674 SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
4675 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
4677 /* new id starts from previous value */
4678 insert_item(hwnd
, 1);
4679 ret
= SendMessageA(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
4682 /* get index by id */
4683 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, -1, 0);
4685 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, 0, 0);
4687 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, 1, 0);
4689 ret
= SendMessageA(hwnd
, LVM_MAPIDTOINDEX
, 2, 0);
4692 DestroyWindow(hwnd
);
4695 static void test_getitemspacing(void)
4700 HIMAGELIST himl40
, himl80
;
4702 cx
= GetSystemMetrics(SM_CXICONSPACING
) - GetSystemMetrics(SM_CXICON
);
4703 cy
= GetSystemMetrics(SM_CYICONSPACING
) - GetSystemMetrics(SM_CYICON
);
4706 hwnd
= create_listview_control(LVS_ICON
);
4707 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4708 expect(cx
, LOWORD(ret
));
4709 expect(cy
, HIWORD(ret
));
4711 /* now try with icons */
4712 himl40
= ImageList_Create(40, 40, 0, 4, 4);
4713 ok(himl40
!= NULL
, "failed to create imagelist\n");
4714 himl80
= ImageList_Create(80, 80, 0, 4, 4);
4715 ok(himl80
!= NULL
, "failed to create imagelist\n");
4716 ret
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl40
);
4719 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4720 /* spacing + icon size returned */
4721 expect(cx
+ 40, LOWORD(ret
));
4722 expect(cy
+ 40, HIWORD(ret
));
4723 /* try changing icon size */
4724 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl80
);
4726 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4727 /* spacing + icon size returned */
4728 expect(cx
+ 80, LOWORD(ret
));
4729 expect(cy
+ 80, HIWORD(ret
));
4731 /* set own icon spacing */
4732 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(100, 100));
4733 expect(cx
+ 80, LOWORD(ret
));
4734 expect(cy
+ 80, HIWORD(ret
));
4736 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4737 /* set size returned */
4738 expect(100, LOWORD(ret
));
4739 expect(100, HIWORD(ret
));
4741 /* now change image list - icon spacing should be unaffected */
4742 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl40
);
4744 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4745 /* set size returned */
4746 expect(100, LOWORD(ret
));
4747 expect(100, HIWORD(ret
));
4749 /* spacing = 0 - keep previous value */
4750 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(0, -1));
4751 expect(100, LOWORD(ret
));
4752 expect(100, HIWORD(ret
));
4754 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4755 expect(100, LOWORD(ret
));
4757 expect(0xFFFF, HIWORD(ret
));
4759 if (sizeof(void*) == 8)
4761 /* NOTE: -1 is not treated the same as (DWORD)-1 by 64bit listview */
4762 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, (DWORD
)-1);
4763 expect(100, LOWORD(ret
));
4764 expect(0xFFFF, HIWORD(ret
));
4766 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, -1);
4767 expect(0xFFFF, LOWORD(ret
));
4768 expect(0xFFFF, HIWORD(ret
));
4772 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, -1);
4773 expect(100, LOWORD(ret
));
4774 expect(0xFFFF, HIWORD(ret
));
4776 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4777 /* spacing + icon size returned */
4778 expect(cx
+ 40, LOWORD(ret
));
4779 expect(cy
+ 40, HIWORD(ret
));
4781 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, 0);
4782 ImageList_Destroy(himl80
);
4783 DestroyWindow(hwnd
);
4785 hwnd
= create_listview_control(LVS_SMALLICON
);
4786 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4787 expect(cx
, LOWORD(ret
));
4788 expect(cy
, HIWORD(ret
));
4790 /* spacing does not depend on selected view type */
4791 ret
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl40
);
4794 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4795 /* spacing + icon size returned */
4796 expect(cx
+ 40, LOWORD(ret
));
4797 expect(cy
+ 40, HIWORD(ret
));
4799 SendMessageA(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, 0);
4800 ImageList_Destroy(himl40
);
4801 DestroyWindow(hwnd
);
4803 hwnd
= create_listview_control(LVS_REPORT
);
4804 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4805 expect(cx
, LOWORD(ret
));
4806 expect(cy
, HIWORD(ret
));
4808 DestroyWindow(hwnd
);
4810 hwnd
= create_listview_control(LVS_LIST
);
4811 ret
= SendMessageA(hwnd
, LVM_GETITEMSPACING
, FALSE
, 0);
4812 expect(cx
, LOWORD(ret
));
4813 expect(cy
, HIWORD(ret
));
4815 DestroyWindow(hwnd
);
4818 static INT
get_current_font_height(HWND listview
)
4825 hwnd
= (HWND
)SendMessageA(listview
, LVM_GETHEADER
, 0, 0);
4829 hfont
= (HFONT
)SendMessageA(hwnd
, WM_GETFONT
, 0, 0);
4832 GetTextMetricsA(hdc
, &tm
);
4833 ReleaseDC(hwnd
, hdc
);
4839 oldfont
= SelectObject(hdc
, hfont
);
4840 GetTextMetricsA(hdc
, &tm
);
4841 SelectObject(hdc
, oldfont
);
4848 static void test_getcolumnwidth(void)
4857 /* default column width */
4858 hwnd
= create_listview_control(LVS_ICON
);
4859 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
4861 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
4862 SetWindowLongA(hwnd
, GWL_STYLE
, style
| LVS_LIST
);
4863 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
4864 todo_wine
expect(8, ret
);
4865 style
= GetWindowLongA(hwnd
, GWL_STYLE
) & ~LVS_LIST
;
4866 SetWindowLongA(hwnd
, GWL_STYLE
, style
| LVS_REPORT
);
4868 ret
= SendMessageA(hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
4870 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
4872 DestroyWindow(hwnd
);
4874 /* default column width with item added */
4875 hwnd
= create_listview_control(LVS_LIST
);
4876 memset(&itema
, 0, sizeof(itema
));
4877 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&itema
);
4878 ok(!ret
, "got %d\n", ret
);
4879 ret
= SendMessageA(hwnd
, LVM_GETCOLUMNWIDTH
, 0, 0);
4880 height
= get_current_font_height(hwnd
);
4881 ok((ret
/ height
) >= 6, "got width %d, height %d\n", ret
, height
);
4882 DestroyWindow(hwnd
);
4885 static void test_scrollnotify(void)
4890 hwnd
= create_listview_control(LVS_REPORT
);
4892 insert_column(hwnd
, 0);
4893 insert_column(hwnd
, 1);
4894 insert_item(hwnd
, 0);
4896 /* make it scrollable - resize */
4897 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
4899 ret
= SendMessageA(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
4902 /* try with dummy call */
4903 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4904 ret
= SendMessageA(hwnd
, LVM_SCROLL
, 0, 0);
4906 ok_sequence(sequences
, PARENT_SEQ_INDEX
, scroll_parent_seq
,
4907 "scroll notify 1", TRUE
);
4909 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4910 ret
= SendMessageA(hwnd
, LVM_SCROLL
, 1, 0);
4912 ok_sequence(sequences
, PARENT_SEQ_INDEX
, scroll_parent_seq
,
4913 "scroll notify 2", TRUE
);
4915 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4916 ret
= SendMessageA(hwnd
, LVM_SCROLL
, 1, 1);
4918 ok_sequence(sequences
, PARENT_SEQ_INDEX
, scroll_parent_seq
,
4919 "scroll notify 3", TRUE
);
4921 DestroyWindow(hwnd
);
4924 static void test_LVS_EX_TRANSPARENTBKGND(void)
4930 hwnd
= create_listview_control(LVS_REPORT
);
4932 ret
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, RGB(0, 0, 0));
4935 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_TRANSPARENTBKGND
,
4936 LVS_EX_TRANSPARENTBKGND
);
4938 ret
= SendMessageA(hwnd
, LVM_GETBKCOLOR
, 0, 0);
4939 if (ret
!= CLR_NONE
)
4941 win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n");
4942 DestroyWindow(hwnd
);
4946 /* try to set some back color and check this style bit */
4947 ret
= SendMessageA(hwnd
, LVM_SETBKCOLOR
, 0, RGB(0, 0, 0));
4949 ret
= SendMessageA(hwnd
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
4950 ok(!(ret
& LVS_EX_TRANSPARENTBKGND
), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
4952 /* now test what this style actually does */
4953 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_TRANSPARENTBKGND
,
4954 LVS_EX_TRANSPARENTBKGND
);
4956 hdc
= GetWindowDC(hwndparent
);
4958 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
4959 SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
4960 ok_sequence(sequences
, PARENT_SEQ_INDEX
, lvs_ex_transparentbkgnd_seq
,
4961 "LVS_EX_TRANSPARENTBKGND parent", FALSE
);
4963 ReleaseDC(hwndparent
, hdc
);
4965 DestroyWindow(hwnd
);
4968 static void test_approximate_viewrect(void)
4975 static CHAR test
[] = "abracadabra, a very long item label";
4977 hwnd
= create_listview_control(LVS_ICON
);
4978 himl
= ImageList_Create(40, 40, 0, 4, 4);
4979 ok(himl
!= NULL
, "failed to create imagelist\n");
4980 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
4981 ok(hbmp
!= NULL
, "failed to create bitmap\n");
4982 ret
= ImageList_Add(himl
, hbmp
, 0);
4984 ret
= SendMessageA(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
4987 itema
.mask
= LVIF_IMAGE
;
4991 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&itema
);
4994 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(75, 75));
4998 win_skip("LVM_SETICONSPACING unimplemented. Skipping.\n");
5002 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 11, MAKELPARAM(100,100));
5003 expect(MAKELONG(77,827), ret
);
5005 ret
= SendMessageA(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(50, 50));
5006 ok(ret
!= 0, "got 0\n");
5008 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 11, MAKELPARAM(100,100));
5009 expect(MAKELONG(102,302), ret
);
5011 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, MAKELPARAM(100,100));
5012 expect(MAKELONG(52,52), ret
);
5014 itema
.pszText
= test
;
5015 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&itema
);
5017 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, -1, MAKELPARAM(100,100));
5018 expect(MAKELONG(52,52), ret
);
5020 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 0, MAKELPARAM(100,100));
5021 expect(MAKELONG(52,2), ret
);
5022 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 1, MAKELPARAM(100,100));
5023 expect(MAKELONG(52,52), ret
);
5024 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 2, MAKELPARAM(100,100));
5025 expect(MAKELONG(102,52), ret
);
5026 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 3, MAKELPARAM(100,100));
5027 expect(MAKELONG(102,102), ret
);
5028 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 4, MAKELPARAM(100,100));
5029 expect(MAKELONG(102,102), ret
);
5030 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 5, MAKELPARAM(100,100));
5031 expect(MAKELONG(102,152), ret
);
5032 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 6, MAKELPARAM(100,100));
5033 expect(MAKELONG(102,152), ret
);
5034 ret
= SendMessageA(hwnd
, LVM_APPROXIMATEVIEWRECT
, 7, MAKELPARAM(160,100));
5035 expect(MAKELONG(152,152), ret
);
5037 DestroyWindow(hwnd
);
5040 static void test_finditem(void)
5047 hwnd
= create_listview_control(LVS_REPORT
);
5048 insert_item(hwnd
, 0);
5050 memset(&fi
, 0, sizeof(fi
));
5052 /* full string search, inserted text was "foo" */
5054 fi
.flags
= LVFI_STRING
;
5056 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5058 /* partial string search, inserted text was "foo" */
5060 fi
.flags
= LVFI_STRING
| LVFI_PARTIAL
;
5062 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5064 /* partial string search, part after start char */
5066 fi
.flags
= LVFI_STRING
| LVFI_PARTIAL
;
5068 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5071 /* try with LVFI_SUBSTRING */
5073 fi
.flags
= LVFI_SUBSTRING
;
5075 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5078 win_skip("LVFI_SUBSTRING not supported\n");
5079 DestroyWindow(hwnd
);
5084 fi
.flags
= LVFI_SUBSTRING
;
5086 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5089 fi
.flags
= LVFI_SUBSTRING
;
5091 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5095 fi
.flags
= LVFI_SUBSTRING
| LVFI_STRING
;
5097 r
= SendMessageA(hwnd
, LVM_FINDITEMA
, -1, (LPARAM
)&fi
);
5100 DestroyWindow(hwnd
);
5103 static void test_LVS_EX_HEADERINALLVIEWS(void)
5108 hwnd
= create_listview_control(LVS_ICON
);
5110 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5111 LVS_EX_HEADERINALLVIEWS
);
5113 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5114 if (!IsWindow(header
))
5116 win_skip("LVS_EX_HEADERINALLVIEWS unsupported\n");
5117 DestroyWindow(hwnd
);
5121 /* LVS_NOCOLUMNHEADER works as before */
5122 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5123 SetWindowLongW(hwnd
, GWL_STYLE
, style
| LVS_NOCOLUMNHEADER
);
5124 style
= GetWindowLongA(header
, GWL_STYLE
);
5125 ok(style
& HDS_HIDDEN
, "Expected HDS_HIDDEN\n");
5126 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
5127 SetWindowLongW(hwnd
, GWL_STYLE
, style
& ~LVS_NOCOLUMNHEADER
);
5128 style
= GetWindowLongA(header
, GWL_STYLE
);
5129 ok(!(style
& HDS_HIDDEN
), "Expected HDS_HIDDEN to be unset\n");
5131 /* try to remove style */
5132 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
, 0);
5133 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5134 ok(IsWindow(header
), "Expected header to be created\n");
5135 style
= GetWindowLongA(header
, GWL_STYLE
);
5136 ok(!(style
& HDS_HIDDEN
), "HDS_HIDDEN not expected\n");
5138 DestroyWindow(hwnd
);
5140 /* check other styles */
5141 hwnd
= create_listview_control(LVS_LIST
);
5142 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5143 LVS_EX_HEADERINALLVIEWS
);
5144 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5145 ok(IsWindow(header
), "Expected header to be created\n");
5146 DestroyWindow(hwnd
);
5148 hwnd
= create_listview_control(LVS_SMALLICON
);
5149 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5150 LVS_EX_HEADERINALLVIEWS
);
5151 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5152 ok(IsWindow(header
), "Expected header to be created\n");
5153 DestroyWindow(hwnd
);
5155 hwnd
= create_listview_control(LVS_REPORT
);
5156 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_HEADERINALLVIEWS
,
5157 LVS_EX_HEADERINALLVIEWS
);
5158 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5159 ok(IsWindow(header
), "Expected header to be created\n");
5160 DestroyWindow(hwnd
);
5163 static void test_hover(void)
5168 hwnd
= create_listview_control(LVS_ICON
);
5169 SetForegroundWindow(hwndparent
);
5170 fg
= GetForegroundWindow();
5171 if (fg
!= hwndparent
)
5173 skip("Window is not in the foreground. Skipping hover tests.\n");
5174 DestroyWindow(hwnd
);
5178 /* test WM_MOUSEHOVER forwarding */
5179 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5180 r
= SendMessageA(hwnd
, WM_MOUSEHOVER
, 0, 0);
5182 ok_sequence(sequences
, PARENT_SEQ_INDEX
, hover_parent
, "NM_HOVER allow test", TRUE
);
5183 g_block_hover
= TRUE
;
5184 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5185 r
= SendMessageA(hwnd
, WM_MOUSEHOVER
, 0, 0);
5187 ok_sequence(sequences
, PARENT_SEQ_INDEX
, hover_parent
, "NM_HOVER block test", TRUE
);
5188 g_block_hover
= FALSE
;
5190 r
= SendMessageA(hwnd
, LVM_SETHOVERTIME
, 0, 500);
5191 expect(HOVER_DEFAULT
, r
);
5192 r
= SendMessageA(hwnd
, LVM_GETHOVERTIME
, 0, 0);
5195 DestroyWindow(hwnd
);
5198 static void test_destroynotify(void)
5203 hwnd
= create_listview_control(LVS_REPORT
);
5204 ok(hwnd
!= NULL
, "failed to create listview window\n");
5206 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5207 DestroyWindow(hwnd
);
5208 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, listview_destroy
, "check destroy order", FALSE
);
5210 /* same for ownerdata list */
5211 hwnd
= create_listview_control(LVS_REPORT
|LVS_OWNERDATA
);
5212 ok(hwnd
!= NULL
, "failed to create listview window\n");
5214 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5215 DestroyWindow(hwnd
);
5216 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, listview_ownerdata_destroy
, "check destroy order, ownerdata", FALSE
);
5218 hwnd
= create_listview_control(LVS_REPORT
|LVS_OWNERDATA
);
5219 ok(hwnd
!= NULL
, "failed to create listview window\n");
5221 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5222 ret
= SendMessageA(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
5223 ok(ret
== TRUE
, "got %d\n", ret
);
5224 ok_sequence(sequences
, COMBINED_SEQ_INDEX
, listview_ownerdata_deleteall
, "deleteall ownerdata", FALSE
);
5225 DestroyWindow(hwnd
);
5228 static void test_header_notification(void)
5230 static char textA
[] = "newtext";
5238 list
= create_listview_control(LVS_REPORT
);
5239 ok(list
!= NULL
, "failed to create listview window\n");
5241 memset(&col
, 0, sizeof(col
));
5242 col
.mask
= LVCF_WIDTH
;
5244 ret
= SendMessageA(list
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5247 /* check list parent notification after header item changed,
5248 this test should be placed before header subclassing to avoid
5249 Listview -> Header messages to be logged */
5250 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5252 col
.mask
= LVCF_TEXT
;
5253 col
.pszText
= textA
;
5254 r
= SendMessageA(list
, LVM_SETCOLUMNA
, 0, (LPARAM
)&col
);
5257 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_header_changed_seq
,
5258 "header notify, listview", FALSE
);
5259 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5260 "header notify, parent", FALSE
);
5262 header
= subclass_header(list
);
5264 ret
= SendMessageA(header
, HDM_GETITEMCOUNT
, 0, 0);
5267 memset(&item
, 0, sizeof(item
));
5268 item
.mask
= HDI_WIDTH
;
5269 ret
= SendMessageA(header
, HDM_GETITEMA
, 0, (LPARAM
)&item
);
5271 expect(100, item
.cxy
);
5273 nmh
.hdr
.hwndFrom
= header
;
5274 nmh
.hdr
.idFrom
= GetWindowLongPtrA(header
, GWLP_ID
);
5275 nmh
.hdr
.code
= HDN_ITEMCHANGEDA
;
5278 item
.mask
= HDI_WIDTH
;
5281 ret
= SendMessageA(list
, WM_NOTIFY
, 0, (LPARAM
)&nmh
);
5284 DestroyWindow(list
);
5287 static void test_header_notification2(void)
5289 static char textA
[] = "newtext";
5296 struct message parent_header_notify_seq
[] = {
5297 { WM_NOTIFY
, sent
|id
, 0, 0, 0 },
5301 list
= create_listview_control(LVS_REPORT
);
5302 ok(list
!= NULL
, "failed to create listview window\n");
5304 memset(&col
, 0, sizeof(col
));
5305 col
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
5307 col
.pszText
= textA
;
5308 ret
= SendMessageA(list
, LVM_INSERTCOLUMNA
, 0, (LPARAM
)&col
);
5311 header
= (HWND
)SendMessageA(list
, LVM_GETHEADER
, 0, 0);
5312 ok(header
!= 0, "No header\n");
5313 memset(&itemW
, 0, sizeof(itemW
));
5314 itemW
.mask
= HDI_WIDTH
| HDI_ORDER
| HDI_TEXT
;
5315 itemW
.pszText
= buffer
;
5316 itemW
.cchTextMax
= sizeof(buffer
);
5317 ret
= SendMessageW(header
, HDM_GETITEMW
, 0, (LPARAM
)&itemW
);
5320 nmhdr
.hdr
.hwndFrom
= header
;
5321 nmhdr
.hdr
.idFrom
= GetWindowLongPtrW(header
, GWLP_ID
);
5324 nmhdr
.pitem
= &itemW
;
5326 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5327 nmhdr
.hdr
.code
= HDN_ITEMCHANGINGW
;
5328 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5329 ok(ret
== 0, "got %d\n", ret
);
5330 parent_header_notify_seq
[0].id
= HDN_ITEMCHANGINGA
;
5331 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5332 "header notify, parent", TRUE
);
5334 ok(nmhdr
.hdr
.code
== HDN_ITEMCHANGINGA
, "Expected ANSI notification code\n");
5335 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5336 nmhdr
.hdr
.code
= HDN_ITEMCHANGEDW
;
5337 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5338 ok(ret
== 0, "got %d\n", ret
);
5339 parent_header_notify_seq
[0].id
= HDN_ITEMCHANGEDA
;
5340 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5341 "header notify, parent", TRUE
);
5343 ok(nmhdr
.hdr
.code
== HDN_ITEMCHANGEDA
, "Expected ANSI notification code\n");
5344 /* HDN_ITEMCLICK sets focus to list, which generates messages we don't want to check */
5346 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5347 nmhdr
.hdr
.code
= HDN_ITEMCLICKW
;
5348 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5349 ok(ret
== 0, "got %d\n", ret
);
5350 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_click_seq
,
5351 "header notify, parent", FALSE
);
5352 ok(nmhdr
.hdr
.code
== HDN_ITEMCLICKA
, "Expected ANSI notification code\n");
5353 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5354 nmhdr
.hdr
.code
= HDN_ITEMDBLCLICKW
;
5355 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5356 ok(ret
== 0, "got %d\n", ret
);
5357 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5358 "header notify, parent", FALSE
);
5359 ok(nmhdr
.hdr
.code
== HDN_ITEMDBLCLICKW
, "Expected Unicode notification code\n");
5360 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5361 nmhdr
.hdr
.code
= HDN_DIVIDERDBLCLICKW
;
5362 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5363 ok(ret
== 0, "got %d\n", ret
);
5364 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_divider_dclick_seq
,
5365 "header notify, parent", TRUE
);
5366 ok(nmhdr
.hdr
.code
== HDN_DIVIDERDBLCLICKA
, "Expected ANSI notification code\n");
5367 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5368 nmhdr
.hdr
.code
= HDN_BEGINTRACKW
;
5369 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5370 ok(ret
== 0, "got %d\n", ret
);
5371 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5372 "header notify, parent", FALSE
);
5373 ok(nmhdr
.hdr
.code
== HDN_BEGINTRACKW
, "Expected Unicode notification code\n");
5374 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5375 nmhdr
.hdr
.code
= HDN_ENDTRACKW
;
5376 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5377 ok(ret
== 0, "got %d\n", ret
);
5378 parent_header_notify_seq
[0].id
= HDN_ENDTRACKA
;
5379 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5380 "header notify, parent", FALSE
);
5381 ok(nmhdr
.hdr
.code
== HDN_ENDTRACKA
, "Expected ANSI notification code\n");
5382 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5383 nmhdr
.hdr
.code
= HDN_TRACKW
;
5384 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5385 ok(ret
== 0, "got %d\n", ret
);
5386 parent_header_notify_seq
[0].id
= HDN_TRACKA
;
5387 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5388 "header notify, parent", FALSE
);
5389 ok(nmhdr
.hdr
.code
== HDN_TRACKA
, "Expected ANSI notification code\n");
5390 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5391 nmhdr
.hdr
.code
= HDN_BEGINDRAG
;
5392 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5393 ok(ret
== 1, "got %d\n", ret
);
5394 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5395 "header notify, parent", FALSE
);
5396 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5397 nmhdr
.hdr
.code
= HDN_ENDDRAG
;
5398 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5399 ok(ret
== 0, "got %d\n", ret
);
5400 parent_header_notify_seq
[0].id
= HDN_ENDDRAG
;
5401 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5402 "header notify, parent", FALSE
);
5403 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5404 nmhdr
.hdr
.code
= HDN_FILTERCHANGE
;
5405 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5406 ok(ret
== 0, "got %d\n", ret
);
5407 parent_header_notify_seq
[0].id
= HDN_FILTERCHANGE
;
5408 parent_header_notify_seq
[0].flags
|= optional
; /* NT4 does not send this message */
5409 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_header_notify_seq
,
5410 "header notify, parent", FALSE
);
5411 parent_header_notify_seq
[0].flags
&= ~optional
;
5412 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5413 nmhdr
.hdr
.code
= HDN_BEGINFILTEREDIT
;
5414 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5415 ok(ret
== 0, "got %d\n", ret
);
5416 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5417 "header notify, parent", FALSE
);
5418 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5419 nmhdr
.hdr
.code
= HDN_ENDFILTEREDIT
;
5420 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5421 ok(ret
== 0, "got %d\n", ret
);
5422 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5423 "header notify, parent", FALSE
);
5424 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5425 nmhdr
.hdr
.code
= HDN_ITEMSTATEICONCLICK
;
5426 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5427 ok(ret
== 0, "got %d\n", ret
);
5428 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5429 "header notify, parent", FALSE
);
5430 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5431 nmhdr
.hdr
.code
= HDN_ITEMKEYDOWN
;
5432 ret
= SendMessageW(list
, WM_NOTIFY
, 0, (LPARAM
)&nmhdr
);
5433 ok(ret
== 0, "got %d\n", ret
);
5434 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
5435 "header notify, parent", FALSE
);
5437 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5439 DestroyWindow(list
);
5442 static void test_createdragimage(void)
5448 list
= create_listview_control(LVS_ICON
);
5449 ok(list
!= NULL
, "failed to create listview window\n");
5451 insert_item(list
, 0);
5454 himl
= (HIMAGELIST
)SendMessageA(list
, LVM_CREATEDRAGIMAGE
, 0, 0);
5455 ok(himl
== NULL
, "got %p\n", himl
);
5457 himl
= (HIMAGELIST
)SendMessageA(list
, LVM_CREATEDRAGIMAGE
, 0, (LPARAM
)&pt
);
5458 ok(himl
!= NULL
, "got %p\n", himl
);
5459 ImageList_Destroy(himl
);
5461 DestroyWindow(list
);
5464 static void test_dispinfo(void)
5466 static const char testA
[] = "TEST";
5472 hwnd
= create_listview_control(LVS_ICON
);
5473 ok(hwnd
!= NULL
, "failed to create listview window\n");
5475 insert_item(hwnd
, 0);
5477 memset(&item
, 0, sizeof(item
));
5478 item
.pszText
= LPSTR_TEXTCALLBACKA
;
5479 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
5482 g_disp_A_to_W
= TRUE
;
5483 item
.pszText
= (char*)buff
;
5484 item
.cchTextMax
= sizeof(buff
)/sizeof(WCHAR
);
5485 ret
= SendMessageA(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
5486 ok(ret
== sizeof(testA
)-1, "got %d, expected 4\n", ret
);
5487 g_disp_A_to_W
= FALSE
;
5489 ok(memcmp(item
.pszText
, testA
, sizeof(testA
)) == 0,
5490 "got %s, expected %s\n", item
.pszText
, testA
);
5492 DestroyWindow(hwnd
);
5495 static void test_LVM_SETITEMTEXT(void)
5497 static char testA
[] = "TEST";
5502 hwnd
= create_listview_control(LVS_ICON
);
5503 ok(hwnd
!= NULL
, "failed to create listview window\n");
5505 insert_item(hwnd
, 0);
5507 /* null item pointer */
5508 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, 0);
5511 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTW
, 0, 0);
5514 /* index out of bounds */
5515 item
.pszText
= testA
;
5516 item
.cchTextMax
= 0; /* ignored */
5519 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 1, (LPARAM
)&item
);
5522 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, -1, (LPARAM
)&item
);
5525 ret
= SendMessageA(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
5528 DestroyWindow(hwnd
);
5531 static void test_LVM_REDRAWITEMS(void)
5536 list
= create_listview_control(LVS_ICON
);
5537 ok(list
!= NULL
, "failed to create listview window\n");
5539 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 0);
5542 insert_item(list
, 0);
5544 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, -1, 0);
5547 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, -1);
5550 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 0);
5553 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 1);
5556 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 0, 2);
5559 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 1, 0);
5562 ret
= SendMessageA(list
, LVM_REDRAWITEMS
, 2, 3);
5565 DestroyWindow(list
);
5568 static void test_imagelists(void)
5571 HIMAGELIST himl1
, himl2
, himl3
;
5574 himl1
= ImageList_Create(40, 40, 0, 4, 4);
5575 himl2
= ImageList_Create(40, 40, 0, 4, 4);
5576 himl3
= ImageList_Create(40, 40, 0, 4, 4);
5577 ok(himl1
!= NULL
, "Failed to create imagelist\n");
5578 ok(himl2
!= NULL
, "Failed to create imagelist\n");
5579 ok(himl3
!= NULL
, "Failed to create imagelist\n");
5581 hwnd
= create_listview_control(LVS_REPORT
| LVS_SHAREIMAGELISTS
);
5582 header
= subclass_header(hwnd
);
5584 ok(header
!= NULL
, "Expected header\n");
5585 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
5586 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
5588 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5590 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl1
);
5591 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
5592 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
5593 "set normal image list", FALSE
);
5595 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5597 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl2
);
5598 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
5599 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
5600 "set state image list", TRUE
);
5602 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
5603 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
5605 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5607 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl3
);
5608 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
5609 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_header_set_imagelist
,
5610 "set small image list", FALSE
);
5612 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
5613 ok((HIMAGELIST
)ret
== himl3
, "Expected imagelist %p, got %p\n", himl3
, (HIMAGELIST
)ret
);
5614 DestroyWindow(hwnd
);
5616 hwnd
= create_listview_control(WS_VISIBLE
| LVS_ICON
);
5618 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5620 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)himl1
);
5621 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
5622 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
5623 "set normal image list", FALSE
);
5625 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5627 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl2
);
5628 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
5629 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
5630 "set state image list", FALSE
);
5632 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5634 ret
= SendMessageW(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl3
);
5635 ok(ret
== 0, "Expected no imagelist, got %p\n", (HIMAGELIST
)ret
);
5636 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_set_imagelist
,
5637 "set small image list", FALSE
);
5639 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5640 ok(header
== NULL
, "Expected no header, got %p\n", header
);
5642 SetWindowLongPtrA(hwnd
, GWL_STYLE
, GetWindowLongPtrA(hwnd
, GWL_STYLE
) | LVS_REPORT
);
5644 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5645 ok(header
!= NULL
, "Expected header, got NULL\n");
5647 ret
= SendMessageA(header
, HDM_GETIMAGELIST
, 0, 0);
5648 ok((HIMAGELIST
)ret
== himl3
, "Expected imagelist %p, got %p\n", himl3
, (HIMAGELIST
)ret
);
5650 DestroyWindow(hwnd
);
5653 static void test_deleteitem(void)
5660 hwnd
= create_listview_control(LVS_REPORT
);
5662 insert_item(hwnd
, 0);
5663 insert_item(hwnd
, 0);
5664 insert_item(hwnd
, 0);
5665 insert_item(hwnd
, 0);
5666 insert_item(hwnd
, 0);
5668 g_focus_test_LVN_DELETEITEM
= TRUE
;
5670 /* delete focused item (not the last index) */
5671 item
.stateMask
= LVIS_FOCUSED
;
5672 item
.state
= LVIS_FOCUSED
;
5673 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 2, (LPARAM
)&item
);
5674 ok(ret
== TRUE
, "got %d\n", ret
);
5675 ret
= SendMessageA(hwnd
, LVM_DELETEITEM
, 2, 0);
5676 ok(ret
== TRUE
, "got %d\n", ret
);
5677 /* next item gets focus */
5678 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_FOCUSED
);
5679 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
5681 /* focus last item and delete it */
5682 item
.stateMask
= LVIS_FOCUSED
;
5683 item
.state
= LVIS_FOCUSED
;
5684 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 3, (LPARAM
)&item
);
5685 ok(ret
== TRUE
, "got %d\n", ret
);
5686 ret
= SendMessageA(hwnd
, LVM_DELETEITEM
, 3, 0);
5687 ok(ret
== TRUE
, "got %d\n", ret
);
5688 /* new last item gets focus */
5689 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_FOCUSED
);
5690 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
5692 /* focus first item and delete it */
5693 item
.stateMask
= LVIS_FOCUSED
;
5694 item
.state
= LVIS_FOCUSED
;
5695 ret
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
5696 ok(ret
== TRUE
, "got %d\n", ret
);
5697 ret
= SendMessageA(hwnd
, LVM_DELETEITEM
, 0, 0);
5698 ok(ret
== TRUE
, "got %d\n", ret
);
5699 /* new first item gets focus */
5700 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_FOCUSED
);
5701 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
5703 g_focus_test_LVN_DELETEITEM
= FALSE
;
5705 DestroyWindow(hwnd
);
5708 static void test_insertitem(void)
5715 hwnd
= create_listview_control(LVS_REPORT
);
5717 /* insert item 0 focused */
5718 item
.mask
= LVIF_STATE
;
5719 item
.state
= LVIS_FOCUSED
;
5720 item
.stateMask
= LVIS_FOCUSED
;
5723 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
5724 ok(ret
== 0, "got %d\n", ret
);
5726 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_FOCUSED
);
5727 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
5729 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5731 /* insert item 1, focus shift */
5732 item
.mask
= LVIF_STATE
;
5733 item
.state
= LVIS_FOCUSED
;
5734 item
.stateMask
= LVIS_FOCUSED
;
5737 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
5738 ok(ret
== 1, "got %d\n", ret
);
5740 ok_sequence(sequences
, PARENT_SEQ_INDEX
, parent_insert_focused_seq
, "insert focused", TRUE
);
5742 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_FOCUSED
);
5743 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
5745 /* insert item 2, no focus shift */
5746 item
.mask
= LVIF_STATE
;
5748 item
.stateMask
= LVIS_FOCUSED
;
5751 ret
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
5752 ok(ret
== 2, "got %d\n", ret
);
5754 state
= SendMessageA(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_FOCUSED
);
5755 ok(state
== LVIS_FOCUSED
, "got %x\n", state
);
5757 DestroyWindow(hwnd
);
5760 static void test_header_proc(void)
5762 HWND hwnd
, header
, hdr
;
5763 WNDPROC proc1
, proc2
;
5765 hwnd
= create_listview_control(LVS_REPORT
);
5767 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
5768 ok(header
!= NULL
, "got %p\n", header
);
5770 hdr
= CreateWindowExA(0, WC_HEADERA
, NULL
,
5771 WS_BORDER
|WS_VISIBLE
|HDS_BUTTONS
|HDS_HORZ
,
5773 NULL
, NULL
, NULL
, NULL
);
5774 ok(hdr
!= NULL
, "got %p\n", hdr
);
5776 proc1
= (WNDPROC
)GetWindowLongPtrW(header
, GWLP_WNDPROC
);
5777 proc2
= (WNDPROC
)GetWindowLongPtrW(hdr
, GWLP_WNDPROC
);
5778 ok(proc1
== proc2
, "got %p, expected %p\n", proc1
, proc2
);
5781 DestroyWindow(hwnd
);
5784 static void flush_events(void)
5788 int min_timeout
= 100;
5789 DWORD time
= GetTickCount() + diff
;
5793 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min_timeout
, QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
5794 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
5795 diff
= time
- GetTickCount();
5799 static void test_oneclickactivate(void)
5801 TRACKMOUSEEVENT track
;
5802 char item1
[] = "item1";
5809 hwnd
= CreateWindowExA(0, "SysListView32", "foo", WS_VISIBLE
|WS_CHILD
|LVS_LIST
,
5810 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
5811 ok(hwnd
!= NULL
, "failed to create listview window\n");
5812 r
= SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_ONECLICKACTIVATE
);
5813 ok(r
== 0, "should return zero\n");
5815 SetForegroundWindow(hwndparent
);
5817 fg
= GetForegroundWindow();
5818 if (fg
!= hwndparent
)
5820 skip("Window is not in the foreground. Skipping oneclickactivate tests.\n");
5821 DestroyWindow(hwnd
);
5825 item
.mask
= LVIF_TEXT
;
5829 item
.pszText
= item1
;
5830 r
= SendMessageA(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
5831 ok(r
== 0, "should not fail\n");
5833 GetWindowRect(hwnd
, &rect
);
5834 GetCursorPos(&orig_pos
);
5835 SetCursorPos(rect
.left
+5, rect
.top
+5);
5837 r
= SendMessageA(hwnd
, WM_MOUSEMOVE
, MAKELONG(1, 1), 0);
5840 track
.cbSize
= sizeof(track
);
5841 track
.dwFlags
= TME_QUERY
;
5842 _TrackMouseEvent(&track
);
5843 ok(track
.hwndTrack
== hwnd
, "hwndTrack != hwnd\n");
5844 ok(track
.dwFlags
== TME_LEAVE
, "dwFlags = %x\n", track
.dwFlags
);
5846 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
5848 r
= SendMessageA(hwnd
, WM_MOUSEHOVER
, MAKELONG(1, 1), 0);
5850 r
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
5853 DestroyWindow(hwnd
);
5854 SetCursorPos(orig_pos
.x
, orig_pos
.y
);
5857 static void test_callback_mask(void)
5863 hwnd
= create_listview_control(LVS_REPORT
);
5865 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, ~0u, 0);
5866 ok(ret
, "got %d\n", ret
);
5868 ret
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, ~0u, 1);
5869 ok(ret
, "got %d\n", ret
);
5871 mask
= SendMessageA(hwnd
, LVM_GETCALLBACKMASK
, 0, 0);
5872 ok(mask
== ~0u, "got 0x%08x\n", mask
);
5874 DestroyWindow(hwnd
);
5877 START_TEST(listview
)
5880 BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
5882 ULONG_PTR ctx_cookie
;
5885 hComctl32
= GetModuleHandleA("comctl32.dll");
5886 pInitCommonControlsEx
= (void*)GetProcAddress(hComctl32
, "InitCommonControlsEx");
5887 if (pInitCommonControlsEx
)
5889 INITCOMMONCONTROLSEX iccex
;
5890 iccex
.dwSize
= sizeof(iccex
);
5891 iccex
.dwICC
= ICC_LISTVIEW_CLASSES
;
5892 pInitCommonControlsEx(&iccex
);
5895 InitCommonControls();
5897 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
5899 hwndparent
= create_parent_window(FALSE
);
5900 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
5902 g_is_below_5
= is_below_comctl_5();
5904 test_header_notification();
5905 test_header_notification2();
5912 test_icon_spacing();
5915 test_item_position();
5920 test_subitem_rect();
5924 test_nosortheader();
5928 test_getitemposition();
5929 test_columnscreation();
5931 test_notifyformat();
5933 test_getitemspacing();
5934 test_getcolumnwidth();
5935 test_approximate_viewrect();
5938 test_destroynotify();
5939 test_createdragimage();
5941 test_LVM_SETITEMTEXT();
5942 test_LVM_REDRAWITEMS();
5947 test_oneclickactivate();
5948 test_callback_mask();
5950 if (!load_v6_module(&ctx_cookie
, &hCtx
))
5952 DestroyWindow(hwndparent
);
5956 /* comctl32 version 6 tests start here */
5957 test_get_set_view();
5958 test_canceleditlabel();
5960 test_scrollnotify();
5961 test_LVS_EX_TRANSPARENTBKGND();
5962 test_LVS_EX_HEADERINALLVIEWS();
5968 unload_v6_module(ctx_cookie
, hCtx
);
5970 DestroyWindow(hwndparent
);