4 * Copyright 2006 Mike McCormack for CodeWeavers
5 * Copyright 2007 George Gov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wine/test.h"
29 #define PARENT_SEQ_INDEX 0
30 #define PARENT_FULL_SEQ_INDEX 1
31 #define LISTVIEW_SEQ_INDEX 2
32 #define NUM_MSG_SEQUENCES 3
37 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
38 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
39 "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
43 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
45 static const struct message create_parent_wnd_seq
[] = {
46 { WM_GETMINMAXINFO
, sent
},
47 { WM_NCCREATE
, sent
},
48 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
50 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
51 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
52 { WM_QUERYNEWPALETTE
, sent
|optional
},
53 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
54 { WM_WINDOWPOSCHANGED
, sent
|optional
},
55 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
56 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
57 { WM_NCACTIVATE
, sent
|wparam
, 1 },
58 { WM_ACTIVATE
, sent
|wparam
, 1 },
59 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
60 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
61 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
62 /* Win9x adds SWP_NOZORDER below */
63 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
64 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
70 static const struct message redraw_listview_seq
[] = {
71 { WM_PAINT
, sent
|id
, 0, 0, LISTVIEW_ID
},
72 { WM_PAINT
, sent
|id
, 0, 0, HEADER_ID
},
73 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
74 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
75 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
76 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
77 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
81 static const struct message listview_icon_spacing_seq
[] = {
82 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(20, 30) },
83 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(25, 35) },
84 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(-1, -1) },
88 static const struct message listview_color_seq
[] = {
89 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
90 { LVM_GETBKCOLOR
, sent
},
91 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
92 { LVM_GETTEXTCOLOR
, sent
},
93 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
94 { LVM_GETTEXTBKCOLOR
, sent
},
96 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
97 { LVM_GETBKCOLOR
, sent
},
98 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
99 { LVM_GETTEXTCOLOR
, sent
},
100 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
101 { LVM_GETTEXTBKCOLOR
, sent
},
103 { LVM_SETBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
104 { LVM_GETBKCOLOR
, sent
},
105 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, CLR_NONE
},
106 { LVM_GETTEXTCOLOR
, sent
},
107 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
108 { LVM_GETTEXTBKCOLOR
, sent
},
110 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
111 { LVM_GETBKCOLOR
, sent
},
112 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
113 { LVM_GETTEXTCOLOR
, sent
},
114 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
115 { LVM_GETTEXTBKCOLOR
, sent
},
119 static const struct message listview_item_count_seq
[] = {
120 { LVM_GETITEMCOUNT
, sent
},
121 { LVM_INSERTITEM
, sent
},
122 { LVM_INSERTITEM
, sent
},
123 { LVM_INSERTITEM
, sent
},
124 { LVM_GETITEMCOUNT
, sent
},
125 { LVM_DELETEITEM
, sent
|wparam
, 2 },
126 { LVM_GETITEMCOUNT
, sent
},
127 { LVM_DELETEALLITEMS
, sent
},
128 { LVM_GETITEMCOUNT
, sent
},
129 { LVM_INSERTITEM
, sent
},
130 { LVM_INSERTITEM
, sent
},
131 { LVM_GETITEMCOUNT
, sent
},
132 { LVM_INSERTITEM
, sent
},
133 { LVM_GETITEMCOUNT
, sent
},
137 static const struct message listview_itempos_seq
[] = {
138 { LVM_INSERTITEM
, sent
},
139 { LVM_INSERTITEM
, sent
},
140 { LVM_INSERTITEM
, sent
},
141 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 1, MAKELPARAM(10,5) },
142 { LVM_GETITEMPOSITION
, sent
|wparam
, 1 },
143 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 2, MAKELPARAM(0,0) },
144 { LVM_GETITEMPOSITION
, sent
|wparam
, 2 },
145 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 0, MAKELPARAM(20,20) },
146 { LVM_GETITEMPOSITION
, sent
|wparam
, 0 },
150 static const struct message listview_ownerdata_switchto_seq
[] = {
151 { WM_STYLECHANGING
, sent
},
152 { WM_STYLECHANGED
, sent
},
156 static const struct message listview_getorderarray_seq
[] = {
157 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
158 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
162 static const struct message empty_seq
[] = {
166 static const struct message forward_erasebkgnd_parent_seq
[] = {
167 { WM_ERASEBKGND
, sent
},
171 static const struct message ownderdata_select_focus_parent_seq
[] = {
172 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
173 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
177 static const struct message textcallback_set_again_parent_seq
[] = {
178 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
179 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
183 static const struct message single_getdispinfo_parent_seq
[] = {
184 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
193 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
195 static LONG defwndproc_counter
= 0;
199 msg
.message
= message
;
200 msg
.flags
= sent
|wparam
|lparam
;
201 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
204 if (message
== WM_NOTIFY
&& lParam
) msg
.id
= ((NMHDR
*)lParam
)->code
;
206 /* log system messages, except for painting */
207 if (message
< WM_USER
&&
208 message
!= WM_PAINT
&&
209 message
!= WM_ERASEBKGND
&&
210 message
!= WM_NCPAINT
&&
211 message
!= WM_NCHITTEST
&&
212 message
!= WM_GETTEXT
&&
213 message
!= WM_GETICON
&&
214 message
!= WM_DEVICECHANGE
)
216 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
218 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
220 add_message(sequences
, PARENT_FULL_SEQ_INDEX
, &msg
);
222 defwndproc_counter
++;
223 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
224 defwndproc_counter
--;
229 static BOOL
register_parent_wnd_class(void)
234 cls
.lpfnWndProc
= parent_wnd_proc
;
237 cls
.hInstance
= GetModuleHandleA(NULL
);
239 cls
.hCursor
= LoadCursorA(0, IDC_ARROW
);
240 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
241 cls
.lpszMenuName
= NULL
;
242 cls
.lpszClassName
= "Listview test parent class";
243 return RegisterClassA(&cls
);
246 static HWND
create_parent_window(void)
248 if (!register_parent_wnd_class())
251 return CreateWindowEx(0, "Listview test parent class",
252 "Listview test parent window",
253 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
254 WS_MAXIMIZEBOX
| WS_VISIBLE
,
256 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
259 static LRESULT WINAPI
listview_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
261 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
262 static LONG defwndproc_counter
= 0;
266 trace("listview: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
268 /* some debug output for style changing */
269 if ((message
== WM_STYLECHANGING
||
270 message
== WM_STYLECHANGED
) && lParam
)
272 STYLESTRUCT
*style
= (STYLESTRUCT
*)lParam
;
273 trace("\told style: 0x%08x, new style: 0x%08x\n", style
->styleOld
, style
->styleNew
);
276 msg
.message
= message
;
277 msg
.flags
= sent
|wparam
|lparam
;
278 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
281 msg
.id
= LISTVIEW_ID
;
282 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
284 defwndproc_counter
++;
285 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
286 defwndproc_counter
--;
290 static HWND
create_listview_control(DWORD style
)
292 struct subclass_info
*info
;
296 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
300 GetClientRect(hwndparent
, &rect
);
301 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
302 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
| style
,
303 0, 0, rect
.right
, rect
.bottom
,
304 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
305 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
309 HeapFree(GetProcessHeap(), 0, info
);
313 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
314 (LONG_PTR
)listview_subclass_proc
);
315 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
320 static HWND
create_custom_listview_control(DWORD style
)
322 struct subclass_info
*info
;
326 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
330 GetClientRect(hwndparent
, &rect
);
331 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
332 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
333 0, 0, rect
.right
, rect
.bottom
,
334 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
335 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
339 HeapFree(GetProcessHeap(), 0, info
);
343 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
344 (LONG_PTR
)listview_subclass_proc
);
345 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
350 static LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
352 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
353 static LONG defwndproc_counter
= 0;
357 trace("header: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
359 msg
.message
= message
;
360 msg
.flags
= sent
|wparam
|lparam
;
361 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
365 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
367 defwndproc_counter
++;
368 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
369 defwndproc_counter
--;
373 static HWND
subclass_header(HWND hwndListview
)
375 struct subclass_info
*info
;
378 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
382 hwnd
= ListView_GetHeader(hwndListview
);
383 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
384 (LONG_PTR
)header_subclass_proc
);
385 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
390 /* Performs a single LVM_HITTEST test */
391 static void test_lvm_hittest(HWND hwnd
, INT x
, INT y
, INT item
, UINT flags
,
392 BOOL todo_item
, BOOL todo_flags
, int line
)
401 trace("hittesting pt=(%d,%d)\n", lpht
.pt
.x
, lpht
.pt
.y
);
402 ret
= SendMessage(hwnd
, LVM_HITTEST
, 0, (LPARAM
)&lpht
);
408 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
409 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
410 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
415 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
416 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
417 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
423 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
426 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
429 /* Performs a single LVM_SUBITEMHITTEST test */
430 static void test_lvm_subitemhittest(HWND hwnd
, INT x
, INT y
, INT item
, INT subitem
, UINT flags
,
431 BOOL todo_item
, BOOL todo_subitem
, BOOL todo_flags
, int line
)
439 trace("subhittesting pt=(%d,%d)\n", lpht
.pt
.x
, lpht
.pt
.y
);
440 ret
= SendMessage(hwnd
, LVM_SUBITEMHITTEST
, 0, (LPARAM
)&lpht
);
446 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
447 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
452 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
453 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
459 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
462 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
467 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
470 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
473 static void test_images(void)
481 static CHAR hello
[] = "hello";
483 himl
= ImageList_Create(40, 40, 0, 4, 4);
484 ok(himl
!= NULL
, "failed to create imagelist\n");
486 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
487 ok(hbmp
!= NULL
, "failed to create bitmap\n");
489 r
= ImageList_Add(himl
, hbmp
, 0);
490 ok(r
== 0, "should be zero\n");
492 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED
,
493 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
494 ok(hwnd
!= NULL
, "failed to create listview window\n");
496 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0,
497 LVS_EX_UNDERLINEHOT
| LVS_EX_FLATSB
| LVS_EX_ONECLICKACTIVATE
);
499 ok(r
== 0, "should return zero\n");
501 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
502 ok(r
== 0, "should return zero\n");
504 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELONG(100,50));
505 /* returns dimensions */
507 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
508 ok(r
== 0, "should be zero items\n");
510 item
.mask
= LVIF_IMAGE
| LVIF_TEXT
;
515 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
516 ok(r
== -1, "should fail\n");
519 item
.pszText
= hello
;
520 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
521 ok(r
== 0, "should not fail\n");
523 memset(&r1
, 0, sizeof r1
);
525 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r1
);
527 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
528 ok(r
== TRUE
, "should not fail\n");
531 item
.pszText
= hello
;
532 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
533 ok(r
== 0, "should not fail\n");
535 memset(&r2
, 0, sizeof r2
);
537 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r2
);
539 ok(!memcmp(&r1
, &r2
, sizeof r1
), "rectangle should be the same\n");
544 static void test_checkboxes(void)
549 static CHAR text
[] = "Text",
553 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
554 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
555 ok(hwnd
!= NULL
, "failed to create listview window\n");
557 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
558 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
559 item
.stateMask
= 0xffff;
564 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
565 ok(r
== 0, "ret %d\n", r
);
568 item
.mask
= LVIF_STATE
;
569 item
.stateMask
= 0xffff;
570 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
571 ok(item
.state
== 0xfccc, "state %x\n", item
.state
);
573 /* Don't set LVIF_STATE */
574 item
.mask
= LVIF_TEXT
;
575 item
.stateMask
= 0xffff;
580 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
581 ok(r
== 1, "ret %d\n", r
);
584 item
.mask
= LVIF_STATE
;
585 item
.stateMask
= 0xffff;
586 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
587 ok(item
.state
== 0, "state %x\n", item
.state
);
589 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
590 ok(r
== 0, "should return zero\n");
592 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
594 item
.mask
= LVIF_STATE
;
595 item
.stateMask
= 0xffff;
596 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
597 ok(item
.state
== 0x1ccc, "state %x\n", item
.state
);
599 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
601 item
.mask
= LVIF_TEXT
;
603 item
.pszText
= text2
;
604 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
605 ok(r
== 2, "ret %d\n", r
);
608 item
.mask
= LVIF_STATE
;
609 item
.stateMask
= 0xffff;
610 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
611 ok(item
.state
== 0x1000, "state %x\n", item
.state
);
613 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
615 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
616 item
.stateMask
= 0xffff;
618 item
.pszText
= text3
;
619 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
620 ok(r
== 3, "ret %d\n", r
);
623 item
.mask
= LVIF_STATE
;
624 item
.stateMask
= 0xffff;
625 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
626 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
628 /* Set an item's state to checked */
630 item
.mask
= LVIF_STATE
;
631 item
.stateMask
= 0xf000;
633 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
636 item
.mask
= LVIF_STATE
;
637 item
.stateMask
= 0xffff;
638 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
639 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
641 /* Check that only the bits we asked for are returned,
642 * and that all the others are set to zero
645 item
.mask
= LVIF_STATE
;
646 item
.stateMask
= 0xf000;
648 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
649 ok(item
.state
== 0x2000, "state %x\n", item
.state
);
651 /* Set the style again and check that doesn't change an item's state */
652 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
653 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
656 item
.mask
= LVIF_STATE
;
657 item
.stateMask
= 0xffff;
658 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
659 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
661 /* Unsetting the checkbox extended style doesn't change an item's state */
662 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
663 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
666 item
.mask
= LVIF_STATE
;
667 item
.stateMask
= 0xffff;
668 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
669 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
671 /* Now setting the style again will change an item's state */
672 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
673 ok(r
== 0, "ret %x\n", r
);
676 item
.mask
= LVIF_STATE
;
677 item
.stateMask
= 0xffff;
678 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
679 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
681 /* Toggle checkbox tests (bug 9934) */
682 memset (&item
, 0xcc, sizeof(item
));
683 item
.mask
= LVIF_STATE
;
686 item
.state
= LVIS_FOCUSED
;
687 item
.stateMask
= LVIS_FOCUSED
;
688 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
692 item
.mask
= LVIF_STATE
;
693 item
.stateMask
= 0xffff;
694 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
695 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
697 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
699 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
703 item
.mask
= LVIF_STATE
;
704 item
.stateMask
= 0xffff;
705 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
706 ok(item
.state
== 0x2aab, "state %x\n", item
.state
);
708 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
710 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
714 item
.mask
= LVIF_STATE
;
715 item
.stateMask
= 0xffff;
716 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
717 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
722 static void insert_column(HWND hwnd
, int idx
)
727 memset(&column
, 0xcc, sizeof(column
));
728 column
.mask
= LVCF_SUBITEM
;
729 column
.iSubItem
= idx
;
731 rc
= ListView_InsertColumn(hwnd
, idx
, &column
);
735 static void insert_item(HWND hwnd
, int idx
)
737 static CHAR text
[] = "foo";
742 memset(&item
, 0xcc, sizeof (item
));
743 item
.mask
= LVIF_TEXT
;
748 rc
= ListView_InsertItem(hwnd
, &item
);
752 static void test_items(void)
754 const LPARAM lparamTest
= 0x42;
758 static CHAR text
[] = "Text";
760 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
761 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
762 ok(hwnd
!= NULL
, "failed to create listview window\n");
765 * Test setting/getting item params
768 /* Set up two columns */
769 insert_column(hwnd
, 0);
770 insert_column(hwnd
, 1);
772 /* LVIS_SELECTED with zero stateMask */
774 memset (&item
, 0, sizeof (item
));
775 item
.mask
= LVIF_STATE
;
776 item
.state
= LVIS_SELECTED
;
780 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
781 ok(r
== 0, "ret %d\n", r
);
783 memset (&item
, 0xcc, sizeof (item
));
784 item
.mask
= LVIF_STATE
;
785 item
.stateMask
= LVIS_SELECTED
;
789 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
790 ok(r
!= 0, "ret %d\n", r
);
791 ok(item
.state
& LVIS_SELECTED
, "Expected LVIS_SELECTED\n");
792 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
794 /* LVIS_SELECTED with zero stateMask */
796 memset (&item
, 0, sizeof (item
));
797 item
.mask
= LVIF_STATE
;
798 item
.state
= LVIS_FOCUSED
;
802 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
803 ok(r
== 0, "ret %d\n", r
);
805 memset (&item
, 0xcc, sizeof (item
));
806 item
.mask
= LVIF_STATE
;
807 item
.stateMask
= LVIS_FOCUSED
;
811 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
812 ok(r
!= 0, "ret %d\n", r
);
813 ok(item
.state
& LVIS_FOCUSED
, "Expected LVIS_FOCUSED\n");
814 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
816 /* LVIS_CUT with LVIS_FOCUSED stateMask */
818 memset (&item
, 0, sizeof (item
));
819 item
.mask
= LVIF_STATE
;
820 item
.state
= LVIS_CUT
;
821 item
.stateMask
= LVIS_FOCUSED
;
824 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
825 ok(r
== 0, "ret %d\n", r
);
827 memset (&item
, 0xcc, sizeof (item
));
828 item
.mask
= LVIF_STATE
;
829 item
.stateMask
= LVIS_CUT
;
833 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
834 ok(r
!= 0, "ret %d\n", r
);
835 ok(item
.state
& LVIS_CUT
, "Expected LVIS_CUT\n");
836 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
838 /* Insert an item with just a param */
839 memset (&item
, 0xcc, sizeof (item
));
840 item
.mask
= LVIF_PARAM
;
843 item
.lParam
= lparamTest
;
844 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
845 ok(r
== 0, "ret %d\n", r
);
847 /* Test getting of the param */
848 memset (&item
, 0xcc, sizeof (item
));
849 item
.mask
= LVIF_PARAM
;
852 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
853 ok(r
!= 0, "ret %d\n", r
);
854 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
856 /* Set up a subitem */
857 memset (&item
, 0xcc, sizeof (item
));
858 item
.mask
= LVIF_TEXT
;
862 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
863 ok(r
!= 0, "ret %d\n", r
);
865 /* Query param from subitem: returns main item param */
866 memset (&item
, 0xcc, sizeof (item
));
867 item
.mask
= LVIF_PARAM
;
870 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
871 ok(r
!= 0, "ret %d\n", r
);
872 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
874 /* Set up param on first subitem: no effect */
875 memset (&item
, 0xcc, sizeof (item
));
876 item
.mask
= LVIF_PARAM
;
879 item
.lParam
= lparamTest
+1;
880 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
881 ok(r
== 0, "ret %d\n", r
);
883 /* Query param from subitem again: should still return main item param */
884 memset (&item
, 0xcc, sizeof (item
));
885 item
.mask
= LVIF_PARAM
;
888 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
889 ok(r
!= 0, "ret %d\n", r
);
890 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
892 /**** Some tests of state highlighting ****/
893 memset (&item
, 0xcc, sizeof (item
));
894 item
.mask
= LVIF_STATE
;
897 item
.state
= LVIS_SELECTED
;
898 item
.stateMask
= LVIS_SELECTED
| LVIS_DROPHILITED
;
899 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
900 ok(r
!= 0, "ret %d\n", r
);
902 item
.state
= LVIS_DROPHILITED
;
903 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
904 ok(r
!= 0, "ret %d\n", r
);
906 memset (&item
, 0xcc, sizeof (item
));
907 item
.mask
= LVIF_STATE
;
911 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
912 ok(r
!= 0, "ret %d\n", r
);
913 ok(item
.state
== LVIS_SELECTED
, "got state %x, expected %x\n", item
.state
, LVIS_SELECTED
);
915 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
916 ok(r
!= 0, "ret %d\n", r
);
917 todo_wine
ok(item
.state
== LVIS_DROPHILITED
, "got state %x, expected %x\n", item
.state
, LVIS_DROPHILITED
);
919 /* some notnull but meaningless masks */
920 memset (&item
, 0, sizeof(item
));
921 item
.mask
= LVIF_NORECOMPUTE
;
924 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
925 ok(r
!= 0, "ret %d\n", r
);
926 memset (&item
, 0, sizeof(item
));
927 item
.mask
= LVIF_DI_SETITEM
;
930 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
931 ok(r
!= 0, "ret %d\n", r
);
933 /* set text to callback value already having it */
934 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
936 memset (&item
, 0, sizeof (item
));
937 item
.mask
= LVIF_TEXT
;
938 item
.pszText
= LPSTR_TEXTCALLBACK
;
940 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
941 ok(r
== 0, "ret %d\n", r
);
942 memset (&item
, 0, sizeof (item
));
944 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
946 item
.pszText
= LPSTR_TEXTCALLBACK
;
947 r
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0 , (LPARAM
) &item
);
950 ok_sequence(sequences
, PARENT_SEQ_INDEX
, textcallback_set_again_parent_seq
,
951 "check callback text comparison rule", TRUE
);
956 static void test_columns(void)
958 HWND hwnd
, hwndheader
;
963 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
964 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
965 ok(hwnd
!= NULL
, "failed to create listview window\n");
967 /* Add a column with no mask */
968 memset(&column
, 0xcc, sizeof(column
));
970 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
971 ok(rc
==0, "Inserting column with no mask failed with %d\n", rc
);
973 /* Check its width */
974 rc
= ListView_GetColumnWidth(hwnd
, 0);
976 broken(rc
==0), /* win9x */
977 "Inserting column with no mask failed to set width to 10 with %d\n", rc
);
981 /* LVM_GETCOLUMNORDERARRAY */
982 hwnd
= create_listview_control(0);
983 hwndheader
= subclass_header(hwnd
);
985 memset(&column
, 0, sizeof(column
));
986 column
.mask
= LVCF_WIDTH
;
988 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
989 ok(rc
== 0, "Inserting column failed with %d\n", rc
);
992 rc
= ListView_InsertColumn(hwnd
, 1, &column
);
993 ok(rc
== 1, "Inserting column failed with %d\n", rc
);
995 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
997 rc
= SendMessage(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
998 ok(rc
!= 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
999 ok(order
[0] == 0, "Expected order 0, got %d\n", order
[0]);
1000 ok(order
[1] == 1, "Expected order 1, got %d\n", order
[1]);
1002 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_getorderarray_seq
, "get order array", FALSE
);
1004 DestroyWindow(hwnd
);
1006 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1007 static WNDPROC listviewWndProc
;
1008 static HIMAGELIST test_create_imagelist
;
1010 static LRESULT CALLBACK
create_test_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1014 if (uMsg
== WM_CREATE
)
1016 LPCREATESTRUCT lpcs
= (LPCREATESTRUCT
)lParam
;
1017 lpcs
->style
|= LVS_REPORT
;
1019 ret
= CallWindowProc(listviewWndProc
, hwnd
, uMsg
, wParam
, lParam
);
1020 if (uMsg
== WM_CREATE
) SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)test_create_imagelist
);
1024 static void test_create(void)
1033 cls
.cbSize
= sizeof(WNDCLASSEX
);
1034 ok(GetClassInfoEx(GetModuleHandle(NULL
), "SysListView32", &cls
), "GetClassInfoEx failed\n");
1035 listviewWndProc
= cls
.lpfnWndProc
;
1036 cls
.lpfnWndProc
= create_test_wndproc
;
1037 cls
.lpszClassName
= "MyListView32";
1038 ok(RegisterClassEx(&cls
), "RegisterClassEx failed\n");
1040 test_create_imagelist
= ImageList_Create(16, 16, 0, 5, 10);
1041 hList
= CreateWindow("MyListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
1042 ok((HIMAGELIST
)SendMessage(hList
, LVM_GETIMAGELIST
, 0, 0) == test_create_imagelist
, "Image list not obtained\n");
1043 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1044 ok(IsWindow(hHeader
) && IsWindowVisible(hHeader
), "Listview not in report mode\n");
1045 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1046 DestroyWindow(hList
);
1048 /* header isn't created on LVS_ICON and LVS_LIST styles */
1049 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1050 GetModuleHandle(NULL
), 0);
1051 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1052 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1053 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1055 memset(&col
, 0, sizeof(LVCOLUMNA
));
1056 col
.mask
= LVCF_WIDTH
;
1058 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1059 ok(r
== 0, "Expected 0 column's inserted\n");
1060 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1061 ok(IsWindow(hHeader
), "Header should be created\n");
1062 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1063 DestroyWindow(hList
);
1065 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1066 GetModuleHandle(NULL
), 0);
1067 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1068 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1069 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1071 memset(&col
, 0, sizeof(LVCOLUMNA
));
1072 col
.mask
= LVCF_WIDTH
;
1074 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1075 ok(r
== 0, "Expected 0 column's inserted\n");
1076 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1077 ok(IsWindow(hHeader
), "Header should be created\n");
1078 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1079 DestroyWindow(hList
);
1081 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1082 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1083 GetModuleHandle(NULL
), 0);
1084 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLongPtr(hList
, GWL_STYLE
) | LVS_REPORT
);
1085 ok(ret
& WS_VISIBLE
, "Style wrong, should have WS_VISIBLE\n");
1086 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1087 ok(IsWindow(hHeader
), "Header should be created\n");
1088 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLong(hList
, GWL_STYLE
) & ~LVS_REPORT
);
1089 ok((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1090 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1091 ok(IsWindow(hHeader
), "Header should be created\n");
1092 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1093 DestroyWindow(hList
);
1095 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1096 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1097 GetModuleHandle(NULL
), 0);
1098 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
1099 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_LIST
) | LVS_REPORT
);
1100 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_LIST
)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1101 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1102 ok(IsWindow(hHeader
), "Header should be created\n");
1103 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1104 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
1105 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_REPORT
) | LVS_LIST
);
1106 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1107 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1108 ok(IsWindow(hHeader
), "Header should be created\n");
1109 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1110 DestroyWindow(hList
);
1112 /* LVS_REPORT without WS_VISIBLE */
1113 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1114 GetModuleHandle(NULL
), 0);
1115 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1116 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1117 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1119 memset(&col
, 0, sizeof(LVCOLUMNA
));
1120 col
.mask
= LVCF_WIDTH
;
1122 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1123 ok(r
== 0, "Expected 0 column's inserted\n");
1124 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1125 ok(IsWindow(hHeader
), "Header should be created\n");
1126 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1127 DestroyWindow(hList
);
1129 /* LVS_REPORT without WS_VISIBLE, try to show it */
1130 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1131 GetModuleHandle(NULL
), 0);
1132 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1133 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1134 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1135 ShowWindow(hList
, SW_SHOW
);
1136 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1137 ok(IsWindow(hHeader
), "Header should be created\n");
1138 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1139 DestroyWindow(hList
);
1141 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1142 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
|LVS_NOCOLUMNHEADER
|WS_VISIBLE
,
1143 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
1144 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1145 ok(IsWindow(hHeader
), "Header should be created\n");
1146 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1147 /* HDS_DRAGDROP set by default */
1148 ok(GetWindowLongPtr(hHeader
, GWL_STYLE
) & HDS_DRAGDROP
, "Expected header to have HDS_DRAGDROP\n");
1149 DestroyWindow(hList
);
1151 /* setting LVS_EX_HEADERDRAGDROP creates header */
1152 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1153 GetModuleHandle(NULL
), 0);
1154 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1155 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1156 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1157 SendMessage(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1158 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1159 ok(IsWindow(hHeader
), "Header should be created\n");
1160 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1161 DestroyWindow(hList
);
1163 /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1164 hList
= create_custom_listview_control(0);
1165 SendMessage(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1166 r
= SendMessage(hList
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1167 ok(r
& LVS_EX_HEADERDRAGDROP
, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1168 DestroyWindow(hList
);
1170 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1171 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1172 GetModuleHandle(NULL
), 0);
1173 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1174 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1176 rect
.left
= LVIR_BOUNDS
;
1178 rect
.right
= rect
.bottom
= -10;
1179 r
= SendMessage(hList
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1180 ok(r
!= 0, "Expected not-null LRESULT\n");
1182 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1183 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1184 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1186 DestroyWindow(hList
);
1189 static void test_redraw(void)
1191 HWND hwnd
, hwndheader
;
1196 hwnd
= create_listview_control(0);
1197 hwndheader
= subclass_header(hwnd
);
1199 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1201 trace("invalidate & update\n");
1202 InvalidateRect(hwnd
, NULL
, TRUE
);
1204 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, redraw_listview_seq
, "redraw listview", FALSE
);
1206 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1208 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1209 /* 1. Without backbuffer */
1210 res
= ListView_SetBkColor(hwnd
, CLR_NONE
);
1213 hdc
= GetWindowDC(hwndparent
);
1215 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1216 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1217 ok(r
!= 0, "Expected not zero result\n");
1218 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1219 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1221 res
= ListView_SetBkColor(hwnd
, CLR_DEFAULT
);
1224 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1225 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1226 ok(r
!= 0, "Expected not zero result\n");
1227 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1228 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1230 /* 2. With backbuffer */
1231 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_DOUBLEBUFFER
,
1232 LVS_EX_DOUBLEBUFFER
);
1233 res
= ListView_SetBkColor(hwnd
, CLR_NONE
);
1236 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1237 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1238 ok(r
!= 0, "Expected not zero result\n");
1239 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1240 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1242 res
= ListView_SetBkColor(hwnd
, CLR_DEFAULT
);
1245 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1246 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1247 todo_wine
ok(r
!= 0, "Expected not zero result\n");
1248 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1249 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1251 ReleaseDC(hwndparent
, hdc
);
1253 DestroyWindow(hwnd
);
1256 static LRESULT WINAPI
cd_wndproc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1258 COLORREF clr
, c0ffee
= RGB(0xc0, 0xff, 0xee);
1260 if(msg
== WM_NOTIFY
) {
1261 NMHDR
*nmhdr
= (PVOID
)lp
;
1262 if(nmhdr
->code
== NM_CUSTOMDRAW
) {
1263 NMLVCUSTOMDRAW
*nmlvcd
= (PVOID
)nmhdr
;
1264 trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd
->nmcd
.dwDrawStage
);
1265 switch(nmlvcd
->nmcd
.dwDrawStage
) {
1267 SetBkColor(nmlvcd
->nmcd
.hdc
, c0ffee
);
1268 return CDRF_NOTIFYITEMDRAW
;
1269 case CDDS_ITEMPREPAINT
:
1270 nmlvcd
->clrTextBk
= CLR_DEFAULT
;
1271 return CDRF_NOTIFYSUBITEMDRAW
;
1272 case CDDS_ITEMPREPAINT
| CDDS_SUBITEM
:
1273 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1274 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1275 return CDRF_NOTIFYPOSTPAINT
;
1276 case CDDS_ITEMPOSTPAINT
| CDDS_SUBITEM
:
1277 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1278 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1279 return CDRF_DODEFAULT
;
1281 return CDRF_DODEFAULT
;
1285 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
1288 static void test_customdraw(void)
1293 hwnd
= create_listview_control(0);
1295 insert_column(hwnd
, 0);
1296 insert_column(hwnd
, 1);
1297 insert_item(hwnd
, 0);
1299 oldwndproc
= (WNDPROC
)SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
,
1300 (LONG_PTR
)cd_wndproc
);
1302 InvalidateRect(hwnd
, NULL
, TRUE
);
1305 SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
, (LONG_PTR
)oldwndproc
);
1307 DestroyWindow(hwnd
);
1310 static void test_icon_spacing(void)
1312 /* LVM_SETICONSPACING */
1313 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1319 hwnd
= create_custom_listview_control(LVS_ICON
);
1320 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1322 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, (WPARAM
)hwndparent
, (LPARAM
)NF_REQUERY
);
1323 expect(NFR_ANSI
, r
);
1325 /* reset the icon spacing to defaults */
1326 SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1328 /* now we can request what the defaults are */
1329 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1333 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1335 trace("test icon spacing\n");
1337 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(20, 30));
1338 ok(r
== MAKELONG(w
, h
) ||
1339 broken(r
== MAKELONG(w
, w
)), /* win98 */
1340 "Expected %d, got %d\n", MAKELONG(w
, h
), r
);
1342 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(25, 35));
1343 expect(MAKELONG(20,30), r
);
1345 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1,-1));
1346 expect(MAKELONG(25,35), r
);
1348 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_icon_spacing_seq
, "test icon spacing seq", FALSE
);
1350 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1351 DestroyWindow(hwnd
);
1354 static void test_color(void)
1356 /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1363 COLORREF colors
[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE
, RGB(255,255,255)};
1365 hwnd
= create_listview_control(0);
1366 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1368 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1370 trace("test color seq\n");
1371 for (i
= 0; i
< 4; i
++)
1375 r
= SendMessage(hwnd
, LVM_SETBKCOLOR
, 0, color
);
1377 r
= SendMessage(hwnd
, LVM_GETBKCOLOR
, 0, color
);
1380 r
= SendMessage(hwnd
, LVM_SETTEXTCOLOR
, 0, color
);
1382 r
= SendMessage(hwnd
, LVM_GETTEXTCOLOR
, 0, color
);
1385 r
= SendMessage(hwnd
, LVM_SETTEXTBKCOLOR
, 0, color
);
1387 r
= SendMessage(hwnd
, LVM_GETTEXTBKCOLOR
, 0, color
);
1391 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_color_seq
, "test color seq", FALSE
);
1393 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1394 DestroyWindow(hwnd
);
1397 static void test_item_count(void)
1399 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1407 static CHAR item0text
[] = "item0";
1408 static CHAR item1text
[] = "item1";
1409 static CHAR item2text
[] = "item2";
1411 hwnd
= create_listview_control(0);
1412 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1414 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1416 trace("test item count\n");
1418 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1422 item0
.mask
= LVIF_TEXT
;
1425 item0
.pszText
= item0text
;
1426 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1429 /* [item0, item1] */
1430 item1
.mask
= LVIF_TEXT
;
1433 item1
.pszText
= item1text
;
1434 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1437 /* [item0, item1, item2] */
1438 item2
.mask
= LVIF_TEXT
;
1441 item2
.pszText
= item2text
;
1442 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1445 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1448 /* [item0, item1] */
1449 r
= SendMessage(hwnd
, LVM_DELETEITEM
, 2, 0);
1452 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1456 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1459 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1463 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1466 /* [item0, item1] */
1467 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1470 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1473 /* [item0, item1, item2] */
1474 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1477 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1480 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_item_count_seq
, "test item count seq", FALSE
);
1482 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1483 DestroyWindow(hwnd
);
1486 static void test_item_position(void)
1488 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1497 static CHAR item0text
[] = "item0";
1498 static CHAR item1text
[] = "item1";
1499 static CHAR item2text
[] = "item2";
1501 hwnd
= create_custom_listview_control(LVS_ICON
);
1502 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1504 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1506 trace("test item position\n");
1509 item0
.mask
= LVIF_TEXT
;
1512 item0
.pszText
= item0text
;
1513 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1516 /* [item0, item1] */
1517 item1
.mask
= LVIF_TEXT
;
1520 item1
.pszText
= item1text
;
1521 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1524 /* [item0, item1, item2] */
1525 item2
.mask
= LVIF_TEXT
;
1528 item2
.pszText
= item2text
;
1529 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1532 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 1, MAKELPARAM(10,5));
1534 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 1, (LPARAM
) &position
);
1536 expect2(10, 5, position
.x
, position
.y
);
1538 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 2, MAKELPARAM(0,0));
1540 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 2, (LPARAM
) &position
);
1542 expect2(0, 0, position
.x
, position
.y
);
1544 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 0, MAKELPARAM(20,20));
1546 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
) &position
);
1548 expect2(20, 20, position
.x
, position
.y
);
1550 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_itempos_seq
, "test item position seq", TRUE
);
1552 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1553 DestroyWindow(hwnd
);
1556 static void test_getorigin(void)
1564 position
.x
= position
.y
= 0;
1566 hwnd
= create_custom_listview_control(LVS_ICON
);
1567 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1568 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1569 trace("test get origin results\n");
1570 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1572 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1573 DestroyWindow(hwnd
);
1575 hwnd
= create_custom_listview_control(LVS_SMALLICON
);
1576 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1577 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1578 trace("test get origin results\n");
1579 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1581 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1582 DestroyWindow(hwnd
);
1584 hwnd
= create_custom_listview_control(LVS_LIST
);
1585 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1586 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1587 trace("test get origin results\n");
1588 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1590 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1591 DestroyWindow(hwnd
);
1593 hwnd
= create_custom_listview_control(LVS_REPORT
);
1594 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1595 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1596 trace("test get origin results\n");
1597 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1599 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1600 DestroyWindow(hwnd
);
1604 static void test_multiselect(void)
1606 typedef struct t_select_task
1617 int i
,j
,item_count
,selected_count
;
1618 static const int items
=5;
1624 static struct t_select_task task_list
[] = {
1625 { "using VK_DOWN", 0, VK_DOWN
, -1, -1 },
1626 { "using VK_UP", -1, VK_UP
, -1, -1 },
1627 { "using VK_END", 0, VK_END
, 1, -1 },
1628 { "using VK_HOME", -1, VK_HOME
, 1, -1 }
1632 hwnd
= create_listview_control(0);
1634 for (i
=0;i
<items
;i
++) {
1635 insert_item(hwnd
, 0);
1638 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1640 expect(items
,item_count
);
1643 task
= task_list
[i
];
1645 /* deselect all items */
1646 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1647 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1649 /* set initial position */
1650 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, (task
.initPos
== -1 ? item_count
-1 : task
.initPos
));
1651 ListView_SetItemState(hwnd
,(task
.initPos
== -1 ? item_count
-1 : task
.initPos
),LVIS_SELECTED
,LVIS_SELECTED
);
1653 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1655 ok(selected_count
== 1, "There should be only one selected item at the beginning (is %d)\n",selected_count
);
1657 /* Set SHIFT key pressed */
1658 GetKeyboardState(kstate
);
1659 kstate
[VK_SHIFT
]=0x80;
1660 SetKeyboardState(kstate
);
1662 for (j
=1;j
<=(task
.count
== -1 ? item_count
: task
.count
);j
++) {
1663 r
= SendMessage(hwnd
, WM_KEYDOWN
, task
.loopVK
, 0);
1665 r
= SendMessage(hwnd
, WM_KEYUP
, task
.loopVK
, 0);
1669 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1671 ok((task
.result
== -1 ? item_count
: task
.result
) == selected_count
, "Failed multiple selection %s. There should be %d selected items (is %d)\n", task
.descr
, item_count
, selected_count
);
1673 /* Set SHIFT key released */
1674 GetKeyboardState(kstate
);
1675 kstate
[VK_SHIFT
]=0x00;
1676 SetKeyboardState(kstate
);
1678 DestroyWindow(hwnd
);
1680 /* make multiple selection, then switch to LVS_SINGLESEL */
1681 hwnd
= create_listview_control(0);
1682 for (i
=0;i
<items
;i
++) {
1683 insert_item(hwnd
, 0);
1685 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1686 expect(items
,item_count
);
1687 /* deselect all items */
1688 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1689 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1691 ListView_SetItemState(hwnd
, i
, LVIS_SELECTED
, LVIS_SELECTED
);
1694 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1696 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1700 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1701 ok(!(style
& LVS_SINGLESEL
), "LVS_SINGLESEL isn't expected\n");
1702 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SINGLESEL
);
1703 /* check that style is accepted */
1704 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1705 ok(style
& LVS_SINGLESEL
, "LVS_SINGLESEL expected\n");
1708 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1709 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1711 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1713 SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1716 /* select one more */
1717 ListView_SetItemState(hwnd
, 3, LVIS_SELECTED
, LVIS_SELECTED
);
1720 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1721 ok(!(r
& LVIS_SELECTED
), "Expected item %d to be unselected\n", i
);
1723 r
= ListView_GetItemState(hwnd
, 3, LVIS_SELECTED
);
1724 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1726 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1728 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1732 /* try to select all on LVS_SINGLESEL */
1733 memset(&item
, 0, sizeof(item
));
1734 item
.stateMask
= LVIS_SELECTED
;
1735 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1737 ListView_SetSelectionMark(hwnd
, -1);
1739 item
.stateMask
= LVIS_SELECTED
;
1740 item
.state
= LVIS_SELECTED
;
1741 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1744 r
= ListView_GetSelectedCount(hwnd
);
1746 r
= ListView_GetSelectionMark(hwnd
);
1749 /* try to deselect all on LVS_SINGLESEL */
1750 item
.stateMask
= LVIS_SELECTED
;
1751 item
.state
= LVIS_SELECTED
;
1752 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
1755 item
.stateMask
= LVIS_SELECTED
;
1757 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1759 r
= ListView_GetSelectedCount(hwnd
);
1762 DestroyWindow(hwnd
);
1765 static void test_subitem_rect(void)
1772 /* test LVM_GETSUBITEMRECT for header */
1773 hwnd
= create_listview_control(0);
1774 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1775 /* add some columns */
1776 memset(&col
, 0, sizeof(LVCOLUMN
));
1777 col
.mask
= LVCF_WIDTH
;
1780 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1784 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 1, (LPARAM
)&col
);
1788 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 2, (LPARAM
)&col
);
1790 /* item = -1 means header, subitem index is 1 based */
1791 rect
.left
= LVIR_BOUNDS
;
1793 rect
.right
= rect
.bottom
= 0;
1794 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1797 rect
.left
= LVIR_BOUNDS
;
1799 rect
.right
= rect
.bottom
= 0;
1800 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1802 ok(r
!= 0, "Expected not-null LRESULT\n");
1803 expect(100, rect
.left
);
1804 expect(250, rect
.right
);
1806 expect(3, rect
.top
);
1808 rect
.left
= LVIR_BOUNDS
;
1810 rect
.right
= rect
.bottom
= 0;
1811 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1813 ok(r
!= 0, "Expected not-null LRESULT\n");
1814 expect(250, rect
.left
);
1815 expect(450, rect
.right
);
1817 expect(3, rect
.top
);
1819 DestroyWindow(hwnd
);
1821 /* try it for non LVS_REPORT style */
1822 hwnd
= CreateWindow("SysListView32", "Test", LVS_ICON
, 0, 0, 100, 100, NULL
, NULL
,
1823 GetModuleHandle(NULL
), 0);
1824 rect
.left
= LVIR_BOUNDS
;
1826 rect
.right
= rect
.bottom
= -10;
1827 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1828 ok(r
== 0, "Expected not-null LRESULT\n");
1829 /* rect is unchanged */
1830 expect(0, rect
.left
);
1831 expect(-10, rect
.right
);
1832 expect(1, rect
.top
);
1833 expect(-10, rect
.bottom
);
1834 DestroyWindow(hwnd
);
1837 /* comparison callback for test_sorting */
1838 static INT WINAPI
test_CallBackCompare(LPARAM first
, LPARAM second
, LPARAM lParam
)
1840 if (first
== second
) return 0;
1841 return (first
> second
? 1 : -1);
1844 static void test_sorting(void)
1850 static CHAR names
[][5] = {"A", "B", "C", "D", "0"};
1853 hwnd
= create_listview_control(0);
1854 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1856 /* insert some items */
1857 item
.mask
= LVIF_PARAM
| LVIF_STATE
;
1858 item
.state
= LVIS_SELECTED
;
1862 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1865 item
.mask
= LVIF_PARAM
;
1869 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1872 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
1873 item
.state
= LVIS_SELECTED
;
1877 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1880 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1883 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1886 r
= SendMessage(hwnd
, LVM_SORTITEMS
, 0, (LPARAM
)test_CallBackCompare
);
1889 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1891 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1893 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_SELECTED
);
1895 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_SELECTED
);
1896 expect(LVIS_SELECTED
, r
);
1897 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_SELECTED
);
1898 expect(LVIS_SELECTED
, r
);
1900 DestroyWindow(hwnd
);
1902 /* switch to LVS_SORTASCENDING when some items added */
1903 hwnd
= create_listview_control(0);
1904 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1906 item
.mask
= LVIF_TEXT
;
1909 item
.pszText
= names
[1];
1910 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1913 item
.mask
= LVIF_TEXT
;
1916 item
.pszText
= names
[2];
1917 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1920 item
.mask
= LVIF_TEXT
;
1923 item
.pszText
= names
[0];
1924 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1927 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1928 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
1929 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1930 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
1932 /* no sorting performed when switched to LVS_SORTASCENDING */
1933 item
.mask
= LVIF_TEXT
;
1935 item
.pszText
= buff
;
1936 item
.cchTextMax
= sizeof(buff
);
1937 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1939 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
1942 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1944 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
1947 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1949 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
1951 /* adding new item doesn't resort list */
1952 item
.mask
= LVIF_TEXT
;
1955 item
.pszText
= names
[3];
1956 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1959 item
.mask
= LVIF_TEXT
;
1961 item
.pszText
= buff
;
1962 item
.cchTextMax
= sizeof(buff
);
1963 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1965 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
1968 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1970 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
1973 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1975 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
1978 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1980 ok(lstrcmp(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
1982 /* corner case - item should be placed at first position */
1983 item
.mask
= LVIF_TEXT
;
1986 item
.pszText
= names
[4];
1987 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1991 item
.pszText
= buff
;
1992 item
.cchTextMax
= sizeof(buff
);
1993 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1995 ok(lstrcmp(buff
, names
[4]) == 0, "Expected '%s', got '%s'\n", names
[4], buff
);
1998 item
.pszText
= buff
;
1999 item
.cchTextMax
= sizeof(buff
);
2000 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2002 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2005 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2007 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2010 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2012 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2015 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2017 ok(lstrcmp(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
2019 DestroyWindow(hwnd
);
2022 static void test_ownerdata(void)
2025 LONG_PTR style
, ret
;
2029 /* it isn't possible to set LVS_OWNERDATA after creation */
2030 hwnd
= create_listview_control(0);
2031 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2032 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2033 ok(!(style
& LVS_OWNERDATA
) && style
, "LVS_OWNERDATA isn't expected\n");
2035 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2037 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
2038 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2039 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2040 "try to switch to LVS_OWNERDATA seq", FALSE
);
2042 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2043 ok(!(style
& LVS_OWNERDATA
), "LVS_OWNERDATA isn't expected\n");
2044 DestroyWindow(hwnd
);
2046 /* try to set LVS_OWNERDATA after creation just having it */
2047 hwnd
= create_listview_control(LVS_OWNERDATA
);
2048 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2049 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2050 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2052 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2054 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
2055 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2056 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2057 "try to switch to LVS_OWNERDATA seq", FALSE
);
2058 DestroyWindow(hwnd
);
2060 /* try to remove LVS_OWNERDATA after creation just having it */
2061 hwnd
= create_listview_control(LVS_OWNERDATA
);
2062 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2063 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2064 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2066 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2068 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_OWNERDATA
);
2069 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2070 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2071 "try to switch to LVS_OWNERDATA seq", FALSE
);
2072 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2073 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2074 DestroyWindow(hwnd
);
2076 /* try select an item */
2077 hwnd
= create_listview_control(LVS_OWNERDATA
);
2078 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2079 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2080 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2081 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2083 memset(&item
, 0, sizeof(item
));
2084 item
.stateMask
= LVIS_SELECTED
;
2085 item
.state
= LVIS_SELECTED
;
2086 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2088 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2090 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2092 DestroyWindow(hwnd
);
2094 /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2095 hwnd
= create_listview_control(LVS_OWNERDATA
);
2096 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2097 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2098 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2099 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2101 memset(&item
, 0, sizeof(item
));
2102 item
.mask
= LVIF_STATE
;
2104 item
.stateMask
= LVIS_SELECTED
;
2105 item
.state
= LVIS_SELECTED
;
2106 res
= SendMessageA(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2108 DestroyWindow(hwnd
);
2110 /* check notifications after focused/selected changed */
2111 hwnd
= create_listview_control(LVS_OWNERDATA
);
2112 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2113 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2114 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2116 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2118 memset(&item
, 0, sizeof(item
));
2119 item
.stateMask
= LVIS_SELECTED
;
2120 item
.state
= LVIS_SELECTED
;
2121 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2124 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownderdata_select_focus_parent_seq
,
2125 "ownerdata select notification", TRUE
);
2127 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2129 memset(&item
, 0, sizeof(item
));
2130 item
.stateMask
= LVIS_FOCUSED
;
2131 item
.state
= LVIS_FOCUSED
;
2132 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2135 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownderdata_select_focus_parent_seq
,
2136 "ownerdata focus notification", TRUE
);
2137 DestroyWindow(hwnd
);
2139 /* check notifications on LVM_GETITEM */
2140 /* zero callback mask */
2141 hwnd
= create_listview_control(LVS_OWNERDATA
);
2142 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2143 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2144 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2146 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2148 memset(&item
, 0, sizeof(item
));
2149 item
.stateMask
= LVIS_SELECTED
;
2150 item
.mask
= LVIF_STATE
;
2151 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2154 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
2155 "ownerdata getitem selected state 1", FALSE
);
2157 /* non zero callback mask but not we asking for */
2158 res
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_OVERLAYMASK
, 0);
2161 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2163 memset(&item
, 0, sizeof(item
));
2164 item
.stateMask
= LVIS_SELECTED
;
2165 item
.mask
= LVIF_STATE
;
2166 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2169 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
2170 "ownerdata getitem selected state 2", FALSE
);
2172 /* LVIS_OVERLAYMASK callback mask, asking for index */
2173 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2175 memset(&item
, 0, sizeof(item
));
2176 item
.stateMask
= LVIS_OVERLAYMASK
;
2177 item
.mask
= LVIF_STATE
;
2178 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2181 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
2182 "ownerdata getitem selected state 2", FALSE
);
2184 DestroyWindow(hwnd
);
2187 static void test_norecompute(void)
2189 static CHAR testA
[] = "test";
2195 /* self containing control */
2196 hwnd
= create_listview_control(0);
2197 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2198 memset(&item
, 0, sizeof(item
));
2199 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
2201 item
.stateMask
= LVIS_SELECTED
;
2202 item
.state
= LVIS_SELECTED
;
2203 item
.pszText
= testA
;
2204 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2206 /* retrieve with LVIF_NORECOMPUTE */
2207 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2209 item
.pszText
= buff
;
2210 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2211 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2213 ok(lstrcmp(buff
, testA
) == 0, "Expected (%s), got (%s)\n", testA
, buff
);
2215 item
.mask
= LVIF_TEXT
;
2217 item
.pszText
= LPSTR_TEXTCALLBACK
;
2218 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2221 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2223 item
.pszText
= buff
;
2224 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2226 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2227 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2229 ok(item
.pszText
== LPSTR_TEXTCALLBACK
, "Expected (%p), got (%p)\n",
2230 LPSTR_TEXTCALLBACK
, (VOID
*)item
.pszText
);
2231 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq", FALSE
);
2233 DestroyWindow(hwnd
);
2236 hwnd
= create_listview_control(LVS_OWNERDATA
);
2237 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2239 item
.mask
= LVIF_STATE
;
2240 item
.stateMask
= LVIS_SELECTED
;
2241 item
.state
= LVIS_SELECTED
;
2243 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2246 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2248 item
.pszText
= buff
;
2249 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2250 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2251 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2253 ok(item
.pszText
== LPSTR_TEXTCALLBACK
, "Expected (%p), got (%p)\n",
2254 LPSTR_TEXTCALLBACK
, (VOID
*)item
.pszText
);
2255 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE
);
2257 DestroyWindow(hwnd
);
2260 static void test_nosortheader(void)
2265 hwnd
= create_listview_control(0);
2266 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2268 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
2269 ok(IsWindow(header
), "header expected\n");
2271 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2272 ok(style
& HDS_BUTTONS
, "expected header to have HDS_BUTTONS\n");
2274 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2275 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
| LVS_NOSORTHEADER
);
2276 /* HDS_BUTTONS retained */
2277 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2278 ok(style
& HDS_BUTTONS
, "expected header to retain HDS_BUTTONS\n");
2280 DestroyWindow(hwnd
);
2282 /* create with LVS_NOSORTHEADER */
2283 hwnd
= create_listview_control(LVS_NOSORTHEADER
);
2284 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2286 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
2287 ok(IsWindow(header
), "header expected\n");
2289 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2290 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
2292 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2293 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
& ~LVS_NOSORTHEADER
);
2294 /* not changed here */
2295 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2296 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
2298 DestroyWindow(hwnd
);
2301 static void test_setredraw(void)
2307 hwnd
= create_listview_control(0);
2308 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2310 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2311 ListView seems to handle it internally without DefWinProc */
2313 /* default value first */
2314 ret
= SendMessage(hwnd
, WM_SETREDRAW
, TRUE
, 0);
2317 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2318 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
2319 ret
= SendMessage(hwnd
, WM_SETREDRAW
, FALSE
, 0);
2321 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2322 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
2324 DestroyWindow(hwnd
);
2327 static void test_hittest(void)
2333 static CHAR text
[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2336 HIMAGELIST himl
, himl2
;
2339 hwnd
= create_listview_control(0);
2340 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2342 /* LVS_REPORT with a single subitem (2 columns) */
2343 insert_column(hwnd
, 0);
2344 insert_column(hwnd
, 1);
2345 insert_item(hwnd
, 0);
2348 /* the only purpose of that line is to be as long as a half item rect */
2349 item
.pszText
= text
;
2350 r
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0, (LPARAM
)&item
);
2353 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
2355 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
2358 memset(&bounds
, 0, sizeof(bounds
));
2359 bounds
.left
= LVIR_BOUNDS
;
2360 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&bounds
);
2361 ok(bounds
.bottom
- bounds
.top
> 0, "Expected non zero item height\n");
2362 ok(bounds
.right
- bounds
.left
> 0, "Expected non zero item width\n");
2363 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pos
);
2366 /* LVS_EX_FULLROWSELECT not set, no icons attached */
2367 x
= pos
.x
+ 50; /* column half width */
2368 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2369 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, __LINE__
);
2370 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2371 x
= pos
.x
+ 150; /* outside column */
2372 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2373 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2374 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, TRUE
, TRUE
, TRUE
, __LINE__
);
2375 /* parent client area is 100x100 by default */
2376 MoveWindow(hwnd
, 0, 0, 300, 100, FALSE
);
2377 x
= pos
.x
+ 150; /* outside column */
2378 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2379 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, FALSE
, FALSE
, __LINE__
);
2380 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2381 /* the same with LVS_EX_FULLROWSELECT */
2382 SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
2383 x
= pos
.x
+ 150; /* outside column */
2384 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2385 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEM
, FALSE
, FALSE
, __LINE__
);
2386 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2387 MoveWindow(hwnd
, 0, 0, 100, 100, FALSE
);
2388 x
= pos
.x
+ 150; /* outside column */
2389 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2390 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2391 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, TRUE
, TRUE
, TRUE
, __LINE__
);
2392 /* try with icons */
2393 himl
= ImageList_Create(16, 16, 0, 4, 4);
2394 ok(himl
!= NULL
, "failed to create imagelist\n");
2395 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
2396 ok(hbmp
!= NULL
, "failed to create bitmap\n");
2397 r
= ImageList_Add(himl
, hbmp
, 0);
2398 ok(r
== 0, "should be zero\n");
2400 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
2401 ok(r
== 0, "should return zero\n");
2403 item
.mask
= LVIF_IMAGE
;
2407 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2410 x
= pos
.x
+ 8; /* outside column */
2411 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2412 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, FALSE
, TRUE
, __LINE__
);
2413 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, TRUE
, __LINE__
);
2415 himl2
= (HIMAGELIST
)SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)NULL
);
2416 ok(himl2
== himl
, "should return handle\n");
2418 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
2419 ok(r
== 0, "should return zero\n");
2421 x
= pos
.x
+ 8; /* outside column */
2422 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2423 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, __LINE__
);
2424 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2426 DestroyWindow(hwnd
);
2429 START_TEST(listview
)
2432 BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
2434 hComctl32
= GetModuleHandleA("comctl32.dll");
2435 pInitCommonControlsEx
= (void*)GetProcAddress(hComctl32
, "InitCommonControlsEx");
2436 if (pInitCommonControlsEx
)
2438 INITCOMMONCONTROLSEX iccex
;
2439 iccex
.dwSize
= sizeof(iccex
);
2440 iccex
.dwICC
= ICC_LISTVIEW_CLASSES
;
2441 pInitCommonControlsEx(&iccex
);
2444 InitCommonControls();
2446 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
2448 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2449 hwndparent
= create_parent_window();
2450 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_parent_wnd_seq
, "create parent window", TRUE
);
2451 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2459 test_icon_spacing();
2462 test_item_position();
2466 test_subitem_rect();
2470 test_nosortheader();
2474 DestroyWindow(hwndparent
);