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 LISTVIEW_SEQ_INDEX 1
31 #define NUM_MSG_SEQUENCES 2
36 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
37 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
38 "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
42 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
44 static const struct message create_parent_wnd_seq
[] = {
45 { WM_GETMINMAXINFO
, sent
},
46 { WM_NCCREATE
, sent
},
47 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
49 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
50 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
51 { WM_QUERYNEWPALETTE
, sent
|optional
},
52 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
53 { WM_WINDOWPOSCHANGED
, sent
|optional
},
54 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
55 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
56 { WM_NCACTIVATE
, sent
|wparam
, 1 },
57 { WM_ACTIVATE
, sent
|wparam
, 1 },
58 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
59 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
60 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
61 /* Win9x adds SWP_NOZORDER below */
62 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
63 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
69 static const struct message redraw_listview_seq
[] = {
70 { WM_PAINT
, sent
|id
, 0, 0, LISTVIEW_ID
},
71 { WM_PAINT
, sent
|id
, 0, 0, HEADER_ID
},
72 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
73 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
74 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
75 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
76 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
80 static const struct message listview_icon_spacing_seq
[] = {
81 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(20, 30) },
82 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(25, 35) },
83 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(-1, -1) },
87 static const struct message listview_color_seq
[] = {
88 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
89 { LVM_GETBKCOLOR
, sent
},
90 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
91 { LVM_GETTEXTCOLOR
, sent
},
92 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
93 { LVM_GETTEXTBKCOLOR
, sent
},
95 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
96 { LVM_GETBKCOLOR
, sent
},
97 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
98 { LVM_GETTEXTCOLOR
, sent
},
99 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
100 { LVM_GETTEXTBKCOLOR
, sent
},
102 { LVM_SETBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
103 { LVM_GETBKCOLOR
, sent
},
104 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, CLR_NONE
},
105 { LVM_GETTEXTCOLOR
, sent
},
106 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
107 { LVM_GETTEXTBKCOLOR
, sent
},
109 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
110 { LVM_GETBKCOLOR
, sent
},
111 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
112 { LVM_GETTEXTCOLOR
, sent
},
113 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
114 { LVM_GETTEXTBKCOLOR
, sent
},
118 static const struct message listview_item_count_seq
[] = {
119 { LVM_GETITEMCOUNT
, sent
},
120 { LVM_INSERTITEM
, sent
},
121 { LVM_INSERTITEM
, sent
},
122 { LVM_INSERTITEM
, sent
},
123 { LVM_GETITEMCOUNT
, sent
},
124 { LVM_DELETEITEM
, sent
|wparam
, 2 },
125 { LVM_GETITEMCOUNT
, sent
},
126 { LVM_DELETEALLITEMS
, sent
},
127 { LVM_GETITEMCOUNT
, sent
},
128 { LVM_INSERTITEM
, sent
},
129 { LVM_INSERTITEM
, sent
},
130 { LVM_GETITEMCOUNT
, sent
},
131 { LVM_INSERTITEM
, sent
},
132 { LVM_GETITEMCOUNT
, sent
},
136 static const struct message listview_itempos_seq
[] = {
137 { LVM_INSERTITEM
, sent
},
138 { LVM_INSERTITEM
, sent
},
139 { LVM_INSERTITEM
, sent
},
140 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 1, MAKELPARAM(10,5) },
141 { LVM_GETITEMPOSITION
, sent
|wparam
, 1 },
142 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 2, MAKELPARAM(0,0) },
143 { LVM_GETITEMPOSITION
, sent
|wparam
, 2 },
144 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 0, MAKELPARAM(20,20) },
145 { LVM_GETITEMPOSITION
, sent
|wparam
, 0 },
149 static const struct message listview_ownerdata_switchto_seq
[] = {
150 { WM_STYLECHANGING
, sent
},
151 { WM_STYLECHANGED
, sent
},
155 static const struct message listview_getorderarray_seq
[] = {
156 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
157 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
166 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
168 static LONG defwndproc_counter
= 0;
172 /* log system messages, except for painting */
173 if (message
< WM_USER
&&
174 message
!= WM_PAINT
&&
175 message
!= WM_ERASEBKGND
&&
176 message
!= WM_NCPAINT
&&
177 message
!= WM_NCHITTEST
&&
178 message
!= WM_GETTEXT
&&
179 message
!= WM_GETICON
&&
180 message
!= WM_DEVICECHANGE
)
182 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
184 msg
.message
= message
;
185 msg
.flags
= sent
|wparam
|lparam
;
186 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
189 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
192 defwndproc_counter
++;
193 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
194 defwndproc_counter
--;
199 static BOOL
register_parent_wnd_class(void)
204 cls
.lpfnWndProc
= parent_wnd_proc
;
207 cls
.hInstance
= GetModuleHandleA(NULL
);
209 cls
.hCursor
= LoadCursorA(0, IDC_ARROW
);
210 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
211 cls
.lpszMenuName
= NULL
;
212 cls
.lpszClassName
= "Listview test parent class";
213 return RegisterClassA(&cls
);
216 static HWND
create_parent_window(void)
218 if (!register_parent_wnd_class())
221 return CreateWindowEx(0, "Listview test parent class",
222 "Listview test parent window",
223 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
224 WS_MAXIMIZEBOX
| WS_VISIBLE
,
226 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
229 static LRESULT WINAPI
listview_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
231 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
232 static LONG defwndproc_counter
= 0;
236 trace("listview: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
238 /* some debug output for style changing */
239 if ((message
== WM_STYLECHANGING
||
240 message
== WM_STYLECHANGED
) && lParam
)
242 STYLESTRUCT
*style
= (STYLESTRUCT
*)lParam
;
243 trace("\told style: 0x%08x, new style: 0x%08x\n", style
->styleOld
, style
->styleNew
);
246 msg
.message
= message
;
247 msg
.flags
= sent
|wparam
|lparam
;
248 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
251 msg
.id
= LISTVIEW_ID
;
252 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
254 defwndproc_counter
++;
255 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
256 defwndproc_counter
--;
260 static HWND
create_listview_control(DWORD style
)
262 struct subclass_info
*info
;
266 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
270 GetClientRect(hwndparent
, &rect
);
271 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
272 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
| style
,
273 0, 0, rect
.right
, rect
.bottom
,
274 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
275 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
279 HeapFree(GetProcessHeap(), 0, info
);
283 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
284 (LONG_PTR
)listview_subclass_proc
);
285 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
290 static HWND
create_custom_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
| 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 LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
322 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
323 static LONG defwndproc_counter
= 0;
327 trace("header: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
329 msg
.message
= message
;
330 msg
.flags
= sent
|wparam
|lparam
;
331 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
335 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
337 defwndproc_counter
++;
338 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
339 defwndproc_counter
--;
343 static HWND
subclass_header(HWND hwndListview
)
345 struct subclass_info
*info
;
348 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
352 hwnd
= ListView_GetHeader(hwndListview
);
353 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
354 (LONG_PTR
)header_subclass_proc
);
355 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
360 static void test_images(void)
368 static CHAR hello
[] = "hello";
370 himl
= ImageList_Create(40, 40, 0, 4, 4);
371 ok(himl
!= NULL
, "failed to create imagelist\n");
373 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
374 ok(hbmp
!= NULL
, "failed to create bitmap\n");
376 r
= ImageList_Add(himl
, hbmp
, 0);
377 ok(r
== 0, "should be zero\n");
379 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED
,
380 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
381 ok(hwnd
!= NULL
, "failed to create listview window\n");
383 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, 0x940);
384 ok(r
== 0, "should return zero\n");
386 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
387 ok(r
== 0, "should return zero\n");
389 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELONG(100,50));
390 /* returns dimensions */
392 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
393 ok(r
== 0, "should be zero items\n");
395 item
.mask
= LVIF_IMAGE
| LVIF_TEXT
;
400 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
401 ok(r
== -1, "should fail\n");
404 item
.pszText
= hello
;
405 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
406 ok(r
== 0, "should not fail\n");
408 memset(&r1
, 0, sizeof r1
);
410 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r1
);
412 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
413 ok(r
== TRUE
, "should not fail\n");
416 item
.pszText
= hello
;
417 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
418 ok(r
== 0, "should not fail\n");
420 memset(&r2
, 0, sizeof r2
);
422 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r2
);
424 ok(!memcmp(&r1
, &r2
, sizeof r1
), "rectangle should be the same\n");
429 static void test_checkboxes(void)
434 static CHAR text
[] = "Text",
438 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
439 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
440 ok(hwnd
!= NULL
, "failed to create listview window\n");
442 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
443 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
444 item
.stateMask
= 0xffff;
449 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
450 ok(r
== 0, "ret %d\n", r
);
453 item
.mask
= LVIF_STATE
;
454 item
.stateMask
= 0xffff;
455 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
456 ok(item
.state
== 0xfccc, "state %x\n", item
.state
);
458 /* Don't set LVIF_STATE */
459 item
.mask
= LVIF_TEXT
;
460 item
.stateMask
= 0xffff;
465 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
466 ok(r
== 1, "ret %d\n", r
);
469 item
.mask
= LVIF_STATE
;
470 item
.stateMask
= 0xffff;
471 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
472 ok(item
.state
== 0, "state %x\n", item
.state
);
474 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
475 ok(r
== 0, "should return zero\n");
477 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
479 item
.mask
= LVIF_STATE
;
480 item
.stateMask
= 0xffff;
481 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
482 ok(item
.state
== 0x1ccc, "state %x\n", item
.state
);
484 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
486 item
.mask
= LVIF_TEXT
;
488 item
.pszText
= text2
;
489 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
490 ok(r
== 2, "ret %d\n", r
);
493 item
.mask
= LVIF_STATE
;
494 item
.stateMask
= 0xffff;
495 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
496 ok(item
.state
== 0x1000, "state %x\n", item
.state
);
498 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
500 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
501 item
.stateMask
= 0xffff;
503 item
.pszText
= text3
;
504 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
505 ok(r
== 3, "ret %d\n", r
);
508 item
.mask
= LVIF_STATE
;
509 item
.stateMask
= 0xffff;
510 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
511 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
513 /* Set an item's state to checked */
515 item
.mask
= LVIF_STATE
;
516 item
.stateMask
= 0xf000;
518 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
521 item
.mask
= LVIF_STATE
;
522 item
.stateMask
= 0xffff;
523 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
524 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
526 /* Check that only the bits we asked for are returned,
527 * and that all the others are set to zero
530 item
.mask
= LVIF_STATE
;
531 item
.stateMask
= 0xf000;
533 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
534 ok(item
.state
== 0x2000, "state %x\n", item
.state
);
536 /* Set the style again and check that doesn't change an item's state */
537 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
538 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
541 item
.mask
= LVIF_STATE
;
542 item
.stateMask
= 0xffff;
543 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
544 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
546 /* Unsetting the checkbox extended style doesn't change an item's state */
547 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
548 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
551 item
.mask
= LVIF_STATE
;
552 item
.stateMask
= 0xffff;
553 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
554 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
556 /* Now setting the style again will change an item's state */
557 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
558 ok(r
== 0, "ret %x\n", r
);
561 item
.mask
= LVIF_STATE
;
562 item
.stateMask
= 0xffff;
563 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
564 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
566 /* Toggle checkbox tests (bug 9934) */
567 memset (&item
, 0xcc, sizeof(item
));
568 item
.mask
= LVIF_STATE
;
571 item
.state
= LVIS_FOCUSED
;
572 item
.stateMask
= LVIS_FOCUSED
;
573 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
577 item
.mask
= LVIF_STATE
;
578 item
.stateMask
= 0xffff;
579 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
580 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
582 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
584 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
588 item
.mask
= LVIF_STATE
;
589 item
.stateMask
= 0xffff;
590 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
591 ok(item
.state
== 0x2aab, "state %x\n", item
.state
);
593 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
595 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
599 item
.mask
= LVIF_STATE
;
600 item
.stateMask
= 0xffff;
601 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
602 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
607 static void insert_column(HWND hwnd
, int idx
)
612 memset(&column
, 0xcc, sizeof(column
));
613 column
.mask
= LVCF_SUBITEM
;
614 column
.iSubItem
= idx
;
616 rc
= ListView_InsertColumn(hwnd
, idx
, &column
);
620 static void insert_item(HWND hwnd
, int idx
)
622 static CHAR text
[] = "foo";
627 memset(&item
, 0xcc, sizeof (item
));
628 item
.mask
= LVIF_TEXT
;
633 rc
= ListView_InsertItem(hwnd
, &item
);
637 static void test_items(void)
639 const LPARAM lparamTest
= 0x42;
643 static CHAR text
[] = "Text";
645 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
646 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
647 ok(hwnd
!= NULL
, "failed to create listview window\n");
650 * Test setting/getting item params
653 /* Set up two columns */
654 insert_column(hwnd
, 0);
655 insert_column(hwnd
, 1);
657 /* LVIS_SELECTED with zero stateMask */
659 memset (&item
, 0, sizeof (item
));
660 item
.mask
= LVIF_STATE
;
661 item
.state
= LVIS_SELECTED
;
665 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
666 ok(r
== 0, "ret %d\n", r
);
668 memset (&item
, 0xcc, sizeof (item
));
669 item
.mask
= LVIF_STATE
;
670 item
.stateMask
= LVIS_SELECTED
;
674 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
675 ok(r
!= 0, "ret %d\n", r
);
676 ok(item
.state
& LVIS_SELECTED
, "Expected LVIS_SELECTED\n");
677 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
679 /* LVIS_SELECTED with zero stateMask */
681 memset (&item
, 0, sizeof (item
));
682 item
.mask
= LVIF_STATE
;
683 item
.state
= LVIS_FOCUSED
;
687 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
688 ok(r
== 0, "ret %d\n", r
);
690 memset (&item
, 0xcc, sizeof (item
));
691 item
.mask
= LVIF_STATE
;
692 item
.stateMask
= LVIS_FOCUSED
;
696 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
697 ok(r
!= 0, "ret %d\n", r
);
698 ok(item
.state
& LVIS_FOCUSED
, "Expected LVIS_FOCUSED\n");
699 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
701 /* LVIS_CUT with LVIS_FOCUSED stateMask */
703 memset (&item
, 0, sizeof (item
));
704 item
.mask
= LVIF_STATE
;
705 item
.state
= LVIS_CUT
;
706 item
.stateMask
= LVIS_FOCUSED
;
709 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
710 ok(r
== 0, "ret %d\n", r
);
712 memset (&item
, 0xcc, sizeof (item
));
713 item
.mask
= LVIF_STATE
;
714 item
.stateMask
= LVIS_CUT
;
718 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
719 ok(r
!= 0, "ret %d\n", r
);
720 ok(item
.state
& LVIS_CUT
, "Expected LVIS_CUT\n");
721 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
723 /* Insert an item with just a param */
724 memset (&item
, 0xcc, sizeof (item
));
725 item
.mask
= LVIF_PARAM
;
728 item
.lParam
= lparamTest
;
729 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
730 ok(r
== 0, "ret %d\n", r
);
732 /* Test getting of the param */
733 memset (&item
, 0xcc, sizeof (item
));
734 item
.mask
= LVIF_PARAM
;
737 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
738 ok(r
!= 0, "ret %d\n", r
);
739 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
741 /* Set up a subitem */
742 memset (&item
, 0xcc, sizeof (item
));
743 item
.mask
= LVIF_TEXT
;
747 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
748 ok(r
!= 0, "ret %d\n", r
);
750 /* Query param from subitem: returns main item param */
751 memset (&item
, 0xcc, sizeof (item
));
752 item
.mask
= LVIF_PARAM
;
755 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
756 ok(r
!= 0, "ret %d\n", r
);
757 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
759 /* Set up param on first subitem: no effect */
760 memset (&item
, 0xcc, sizeof (item
));
761 item
.mask
= LVIF_PARAM
;
764 item
.lParam
= lparamTest
+1;
765 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
766 ok(r
== 0, "ret %d\n", r
);
768 /* Query param from subitem again: should still return main item param */
769 memset (&item
, 0xcc, sizeof (item
));
770 item
.mask
= LVIF_PARAM
;
773 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
774 ok(r
!= 0, "ret %d\n", r
);
775 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
777 /**** Some tests of state highlighting ****/
778 memset (&item
, 0xcc, sizeof (item
));
779 item
.mask
= LVIF_STATE
;
782 item
.state
= LVIS_SELECTED
;
783 item
.stateMask
= LVIS_SELECTED
| LVIS_DROPHILITED
;
784 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
785 ok(r
!= 0, "ret %d\n", r
);
787 item
.state
= LVIS_DROPHILITED
;
788 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
789 ok(r
!= 0, "ret %d\n", r
);
791 memset (&item
, 0xcc, sizeof (item
));
792 item
.mask
= LVIF_STATE
;
796 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
797 ok(r
!= 0, "ret %d\n", r
);
798 ok(item
.state
== LVIS_SELECTED
, "got state %x, expected %x\n", item
.state
, LVIS_SELECTED
);
800 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
801 ok(r
!= 0, "ret %d\n", r
);
802 todo_wine
ok(item
.state
== LVIS_DROPHILITED
, "got state %x, expected %x\n", item
.state
, LVIS_DROPHILITED
);
807 static void test_columns(void)
809 HWND hwnd
, hwndheader
;
814 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
815 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
816 ok(hwnd
!= NULL
, "failed to create listview window\n");
818 /* Add a column with no mask */
819 memset(&column
, 0xcc, sizeof(column
));
821 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
822 ok(rc
==0, "Inserting column with no mask failed with %d\n", rc
);
824 /* Check its width */
825 rc
= ListView_GetColumnWidth(hwnd
, 0);
827 broken(rc
==0), /* win9x */
828 "Inserting column with no mask failed to set width to 10 with %d\n", rc
);
832 /* LVM_GETCOLUMNORDERARRAY */
833 hwnd
= create_listview_control(0);
834 hwndheader
= subclass_header(hwnd
);
836 memset(&column
, 0, sizeof(column
));
837 column
.mask
= LVCF_WIDTH
;
839 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
840 ok(rc
== 0, "Inserting column failed with %d\n", rc
);
843 rc
= ListView_InsertColumn(hwnd
, 1, &column
);
844 ok(rc
== 1, "Inserting column failed with %d\n", rc
);
846 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
848 rc
= SendMessage(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
849 ok(rc
!= 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
850 ok(order
[0] == 0, "Expected order 0, got %d\n", order
[0]);
851 ok(order
[1] == 1, "Expected order 1, got %d\n", order
[1]);
853 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_getorderarray_seq
, "get order array", FALSE
);
857 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
858 static WNDPROC listviewWndProc
;
859 static HIMAGELIST test_create_imagelist
;
861 static LRESULT CALLBACK
create_test_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
865 if (uMsg
== WM_CREATE
)
867 LPCREATESTRUCT lpcs
= (LPCREATESTRUCT
)lParam
;
868 lpcs
->style
|= LVS_REPORT
;
870 ret
= CallWindowProc(listviewWndProc
, hwnd
, uMsg
, wParam
, lParam
);
871 if (uMsg
== WM_CREATE
) SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)test_create_imagelist
);
875 static void test_create(void)
884 cls
.cbSize
= sizeof(WNDCLASSEX
);
885 ok(GetClassInfoEx(GetModuleHandle(NULL
), "SysListView32", &cls
), "GetClassInfoEx failed\n");
886 listviewWndProc
= cls
.lpfnWndProc
;
887 cls
.lpfnWndProc
= create_test_wndproc
;
888 cls
.lpszClassName
= "MyListView32";
889 ok(RegisterClassEx(&cls
), "RegisterClassEx failed\n");
891 test_create_imagelist
= ImageList_Create(16, 16, 0, 5, 10);
892 hList
= CreateWindow("MyListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
893 ok((HIMAGELIST
)SendMessage(hList
, LVM_GETIMAGELIST
, 0, 0) == test_create_imagelist
, "Image list not obtained\n");
894 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
895 ok(IsWindow(hHeader
) && IsWindowVisible(hHeader
), "Listview not in report mode\n");
896 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
897 DestroyWindow(hList
);
899 /* header isn't created on LVS_ICON and LVS_LIST styles */
900 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
901 GetModuleHandle(NULL
), 0);
902 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
903 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
904 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
906 memset(&col
, 0, sizeof(LVCOLUMNA
));
907 col
.mask
= LVCF_WIDTH
;
909 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
910 ok(r
== 0, "Expected 0 column's inserted\n");
911 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
912 ok(IsWindow(hHeader
), "Header should be created\n");
913 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
914 DestroyWindow(hList
);
916 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
917 GetModuleHandle(NULL
), 0);
918 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
919 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
920 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
922 memset(&col
, 0, sizeof(LVCOLUMNA
));
923 col
.mask
= LVCF_WIDTH
;
925 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
926 ok(r
== 0, "Expected 0 column's inserted\n");
927 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
928 ok(IsWindow(hHeader
), "Header should be created\n");
929 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
930 DestroyWindow(hList
);
932 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
933 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
934 GetModuleHandle(NULL
), 0);
935 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLongPtr(hList
, GWL_STYLE
) | LVS_REPORT
);
936 ok(ret
& WS_VISIBLE
, "Style wrong, should have WS_VISIBLE\n");
937 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
938 ok(IsWindow(hHeader
), "Header should be created\n");
939 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLong(hList
, GWL_STYLE
) & ~LVS_REPORT
);
940 ok((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
941 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
942 ok(IsWindow(hHeader
), "Header should be created\n");
943 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
944 DestroyWindow(hList
);
946 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
947 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
948 GetModuleHandle(NULL
), 0);
949 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
950 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_LIST
) | LVS_REPORT
);
951 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_LIST
)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
952 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
953 ok(IsWindow(hHeader
), "Header should be created\n");
954 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
955 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
956 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_REPORT
) | LVS_LIST
);
957 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
958 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
959 ok(IsWindow(hHeader
), "Header should be created\n");
960 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
961 DestroyWindow(hList
);
963 /* LVS_REPORT without WS_VISIBLE */
964 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
965 GetModuleHandle(NULL
), 0);
966 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
967 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
968 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
970 memset(&col
, 0, sizeof(LVCOLUMNA
));
971 col
.mask
= LVCF_WIDTH
;
973 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
974 ok(r
== 0, "Expected 0 column's inserted\n");
975 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
976 ok(IsWindow(hHeader
), "Header should be created\n");
977 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
978 DestroyWindow(hList
);
980 /* LVS_REPORT without WS_VISIBLE, try to show it */
981 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
982 GetModuleHandle(NULL
), 0);
983 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
984 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
985 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
986 ShowWindow(hList
, SW_SHOW
);
987 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
988 ok(IsWindow(hHeader
), "Header should be created\n");
989 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
990 DestroyWindow(hList
);
992 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
993 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
|LVS_NOCOLUMNHEADER
|WS_VISIBLE
,
994 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
995 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
996 ok(IsWindow(hHeader
), "Header should be created\n");
997 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
998 /* HDS_DRAGDROP set by default */
999 ok(GetWindowLongPtr(hHeader
, GWL_STYLE
) & HDS_DRAGDROP
, "Expected header to have HDS_DRAGDROP\n");
1000 DestroyWindow(hList
);
1002 /* setting LVS_EX_HEADERDRAGDROP creates header */
1003 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1004 GetModuleHandle(NULL
), 0);
1005 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1006 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1007 SendMessage(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1008 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1009 ok(IsWindow(hHeader
), "Header should be created\n");
1010 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1011 DestroyWindow(hList
);
1013 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1014 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1015 GetModuleHandle(NULL
), 0);
1016 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1017 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1019 rect
.left
= LVIR_BOUNDS
;
1021 rect
.right
= rect
.bottom
= -10;
1022 r
= SendMessage(hList
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1023 ok(r
!= 0, "Expected not-null LRESULT\n");
1025 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1026 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1027 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1029 DestroyWindow(hList
);
1032 static void test_redraw(void)
1034 HWND hwnd
, hwndheader
;
1036 hwnd
= create_listview_control(0);
1037 hwndheader
= subclass_header(hwnd
);
1039 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1041 trace("invalidate & update\n");
1042 InvalidateRect(hwnd
, NULL
, TRUE
);
1044 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, redraw_listview_seq
, "redraw listview", FALSE
);
1046 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1048 DestroyWindow(hwnd
);
1051 static LRESULT WINAPI
cd_wndproc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1053 COLORREF clr
, c0ffee
= RGB(0xc0, 0xff, 0xee);
1055 if(msg
== WM_NOTIFY
) {
1056 NMHDR
*nmhdr
= (PVOID
)lp
;
1057 if(nmhdr
->code
== NM_CUSTOMDRAW
) {
1058 NMLVCUSTOMDRAW
*nmlvcd
= (PVOID
)nmhdr
;
1059 trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd
->nmcd
.dwDrawStage
);
1060 switch(nmlvcd
->nmcd
.dwDrawStage
) {
1062 SetBkColor(nmlvcd
->nmcd
.hdc
, c0ffee
);
1063 return CDRF_NOTIFYITEMDRAW
;
1064 case CDDS_ITEMPREPAINT
:
1065 nmlvcd
->clrTextBk
= CLR_DEFAULT
;
1066 return CDRF_NOTIFYSUBITEMDRAW
;
1067 case CDDS_ITEMPREPAINT
| CDDS_SUBITEM
:
1068 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1069 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1070 return CDRF_NOTIFYPOSTPAINT
;
1071 case CDDS_ITEMPOSTPAINT
| CDDS_SUBITEM
:
1072 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1073 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1074 return CDRF_DODEFAULT
;
1076 return CDRF_DODEFAULT
;
1080 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
1083 static void test_customdraw(void)
1088 hwnd
= create_listview_control(0);
1090 insert_column(hwnd
, 0);
1091 insert_column(hwnd
, 1);
1092 insert_item(hwnd
, 0);
1094 oldwndproc
= (WNDPROC
)SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
,
1095 (LONG_PTR
)cd_wndproc
);
1097 InvalidateRect(hwnd
, NULL
, TRUE
);
1100 SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
, (LONG_PTR
)oldwndproc
);
1102 DestroyWindow(hwnd
);
1105 static void test_icon_spacing(void)
1107 /* LVM_SETICONSPACING */
1108 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1114 hwnd
= create_custom_listview_control(LVS_ICON
);
1115 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1117 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, (WPARAM
)hwndparent
, (LPARAM
)NF_REQUERY
);
1118 expect(NFR_ANSI
, r
);
1120 /* reset the icon spacing to defaults */
1121 SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1123 /* now we can request what the defaults are */
1124 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1128 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1130 trace("test icon spacing\n");
1132 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(20, 30));
1133 ok(r
== MAKELONG(w
, h
) ||
1134 broken(r
== MAKELONG(w
, w
)), /* win98 */
1135 "Expected %d, got %d\n", MAKELONG(w
, h
), r
);
1137 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(25, 35));
1138 expect(MAKELONG(20,30), r
);
1140 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1,-1));
1141 expect(MAKELONG(25,35), r
);
1143 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_icon_spacing_seq
, "test icon spacing seq", FALSE
);
1145 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1146 DestroyWindow(hwnd
);
1149 static void test_color(void)
1151 /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1158 COLORREF colors
[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE
, RGB(255,255,255)};
1160 hwnd
= create_listview_control(0);
1161 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1163 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1165 trace("test color seq\n");
1166 for (i
= 0; i
< 4; i
++)
1170 r
= SendMessage(hwnd
, LVM_SETBKCOLOR
, 0, color
);
1172 r
= SendMessage(hwnd
, LVM_GETBKCOLOR
, 0, color
);
1175 r
= SendMessage(hwnd
, LVM_SETTEXTCOLOR
, 0, color
);
1177 r
= SendMessage(hwnd
, LVM_GETTEXTCOLOR
, 0, color
);
1180 r
= SendMessage(hwnd
, LVM_SETTEXTBKCOLOR
, 0, color
);
1182 r
= SendMessage(hwnd
, LVM_GETTEXTBKCOLOR
, 0, color
);
1186 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_color_seq
, "test color seq", FALSE
);
1188 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1189 DestroyWindow(hwnd
);
1192 static void test_item_count(void)
1194 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1202 static CHAR item0text
[] = "item0";
1203 static CHAR item1text
[] = "item1";
1204 static CHAR item2text
[] = "item2";
1206 hwnd
= create_listview_control(0);
1207 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1209 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1211 trace("test item count\n");
1213 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1217 item0
.mask
= LVIF_TEXT
;
1220 item0
.pszText
= item0text
;
1221 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1224 /* [item0, item1] */
1225 item1
.mask
= LVIF_TEXT
;
1228 item1
.pszText
= item1text
;
1229 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1232 /* [item0, item1, item2] */
1233 item2
.mask
= LVIF_TEXT
;
1236 item2
.pszText
= item2text
;
1237 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1240 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1243 /* [item0, item1] */
1244 r
= SendMessage(hwnd
, LVM_DELETEITEM
, 2, 0);
1247 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1251 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1254 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1258 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1261 /* [item0, item1] */
1262 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1265 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1268 /* [item0, item1, item2] */
1269 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1272 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1275 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_item_count_seq
, "test item count seq", FALSE
);
1277 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1278 DestroyWindow(hwnd
);
1281 static void test_item_position(void)
1283 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1292 static CHAR item0text
[] = "item0";
1293 static CHAR item1text
[] = "item1";
1294 static CHAR item2text
[] = "item2";
1296 hwnd
= create_custom_listview_control(LVS_ICON
);
1297 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1299 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1301 trace("test item position\n");
1304 item0
.mask
= LVIF_TEXT
;
1307 item0
.pszText
= item0text
;
1308 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1311 /* [item0, item1] */
1312 item1
.mask
= LVIF_TEXT
;
1315 item1
.pszText
= item1text
;
1316 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1319 /* [item0, item1, item2] */
1320 item2
.mask
= LVIF_TEXT
;
1323 item2
.pszText
= item2text
;
1324 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1327 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 1, MAKELPARAM(10,5));
1329 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 1, (LPARAM
) &position
);
1331 expect2(10, 5, position
.x
, position
.y
);
1333 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 2, MAKELPARAM(0,0));
1335 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 2, (LPARAM
) &position
);
1337 expect2(0, 0, position
.x
, position
.y
);
1339 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 0, MAKELPARAM(20,20));
1341 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
) &position
);
1343 expect2(20, 20, position
.x
, position
.y
);
1345 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_itempos_seq
, "test item position seq", TRUE
);
1347 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1348 DestroyWindow(hwnd
);
1351 static void test_getorigin(void)
1359 position
.x
= position
.y
= 0;
1361 hwnd
= create_custom_listview_control(LVS_ICON
);
1362 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1363 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1364 trace("test get origin results\n");
1365 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1367 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1368 DestroyWindow(hwnd
);
1370 hwnd
= create_custom_listview_control(LVS_SMALLICON
);
1371 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1372 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1373 trace("test get origin results\n");
1374 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1376 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1377 DestroyWindow(hwnd
);
1379 hwnd
= create_custom_listview_control(LVS_LIST
);
1380 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1381 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1382 trace("test get origin results\n");
1383 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1385 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1386 DestroyWindow(hwnd
);
1388 hwnd
= create_custom_listview_control(LVS_REPORT
);
1389 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1390 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1391 trace("test get origin results\n");
1392 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1394 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1395 DestroyWindow(hwnd
);
1399 static void test_multiselect(void)
1401 typedef struct t_select_task
1412 int i
,j
,item_count
,selected_count
;
1413 static const int items
=5;
1418 static struct t_select_task task_list
[] = {
1419 { "using VK_DOWN", 0, VK_DOWN
, -1, -1 },
1420 { "using VK_UP", -1, VK_UP
, -1, -1 },
1421 { "using VK_END", 0, VK_END
, 1, -1 },
1422 { "using VK_HOME", -1, VK_HOME
, 1, -1 }
1426 hwnd
= create_listview_control(0);
1428 for (i
=0;i
<items
;i
++) {
1429 insert_item(hwnd
, 0);
1432 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1434 expect(items
,item_count
);
1437 task
= task_list
[i
];
1439 /* deselect all items */
1440 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1441 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1443 /* set initial position */
1444 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, (task
.initPos
== -1 ? item_count
-1 : task
.initPos
));
1445 ListView_SetItemState(hwnd
,(task
.initPos
== -1 ? item_count
-1 : task
.initPos
),LVIS_SELECTED
,LVIS_SELECTED
);
1447 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1449 ok(selected_count
== 1, "There should be only one selected item at the beginning (is %d)\n",selected_count
);
1451 /* Set SHIFT key pressed */
1452 GetKeyboardState(kstate
);
1453 kstate
[VK_SHIFT
]=0x80;
1454 SetKeyboardState(kstate
);
1456 for (j
=1;j
<=(task
.count
== -1 ? item_count
: task
.count
);j
++) {
1457 r
= SendMessage(hwnd
, WM_KEYDOWN
, task
.loopVK
, 0);
1459 r
= SendMessage(hwnd
, WM_KEYUP
, task
.loopVK
, 0);
1463 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1465 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
);
1467 /* Set SHIFT key released */
1468 GetKeyboardState(kstate
);
1469 kstate
[VK_SHIFT
]=0x00;
1470 SetKeyboardState(kstate
);
1472 DestroyWindow(hwnd
);
1474 /* make multiple selection, then switch to LVS_SINGLESEL */
1475 hwnd
= create_listview_control(0);
1476 for (i
=0;i
<items
;i
++) {
1477 insert_item(hwnd
, 0);
1479 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1480 expect(items
,item_count
);
1481 /* deselect all items */
1482 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1483 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1485 ListView_SetItemState(hwnd
, i
, LVIS_SELECTED
, LVIS_SELECTED
);
1488 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1490 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1494 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1495 ok(!(style
& LVS_SINGLESEL
), "LVS_SINGLESEL isn't expected\n");
1496 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SINGLESEL
);
1497 /* check that style is accepted */
1498 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1499 ok(style
& LVS_SINGLESEL
, "LVS_SINGLESEL expected\n");
1502 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1503 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1505 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1507 SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1510 /* select one more */
1511 ListView_SetItemState(hwnd
, 3, LVIS_SELECTED
, LVIS_SELECTED
);
1514 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1515 ok(!(r
& LVIS_SELECTED
), "Expected item %d to be unselected\n", i
);
1517 r
= ListView_GetItemState(hwnd
, 3, LVIS_SELECTED
);
1518 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1520 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1522 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1526 DestroyWindow(hwnd
);
1529 static void test_subitem_rect(void)
1536 /* test LVM_GETSUBITEMRECT for header */
1537 hwnd
= create_listview_control(0);
1538 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1539 /* add some columns */
1540 memset(&col
, 0, sizeof(LVCOLUMN
));
1541 col
.mask
= LVCF_WIDTH
;
1544 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1548 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 1, (LPARAM
)&col
);
1552 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 2, (LPARAM
)&col
);
1554 /* item = -1 means header, subitem index is 1 based */
1555 rect
.left
= LVIR_BOUNDS
;
1557 rect
.right
= rect
.bottom
= 0;
1558 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1561 rect
.left
= LVIR_BOUNDS
;
1563 rect
.right
= rect
.bottom
= 0;
1564 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1566 ok(r
!= 0, "Expected not-null LRESULT\n");
1567 expect(100, rect
.left
);
1568 expect(250, rect
.right
);
1570 expect(3, rect
.top
);
1572 rect
.left
= LVIR_BOUNDS
;
1574 rect
.right
= rect
.bottom
= 0;
1575 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1577 ok(r
!= 0, "Expected not-null LRESULT\n");
1578 expect(250, rect
.left
);
1579 expect(450, rect
.right
);
1581 expect(3, rect
.top
);
1583 DestroyWindow(hwnd
);
1585 /* try it for non LVS_REPORT style */
1586 hwnd
= CreateWindow("SysListView32", "Test", LVS_ICON
, 0, 0, 100, 100, NULL
, NULL
,
1587 GetModuleHandle(NULL
), 0);
1588 rect
.left
= LVIR_BOUNDS
;
1590 rect
.right
= rect
.bottom
= -10;
1591 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1592 ok(r
== 0, "Expected not-null LRESULT\n");
1593 /* rect is unchanged */
1594 expect(0, rect
.left
);
1595 expect(-10, rect
.right
);
1596 expect(1, rect
.top
);
1597 expect(-10, rect
.bottom
);
1598 DestroyWindow(hwnd
);
1601 /* comparison callback for test_sorting */
1602 static INT WINAPI
test_CallBackCompare(LPARAM first
, LPARAM second
, LPARAM lParam
)
1604 if (first
== second
) return 0;
1605 return (first
> second
? 1 : -1);
1608 static void test_sorting(void)
1614 static CHAR names
[][4] = {"A", "B", "C", "D"};
1617 hwnd
= create_listview_control(0);
1618 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1620 /* insert some items */
1621 item
.mask
= LVIF_PARAM
| LVIF_STATE
;
1622 item
.state
= LVIS_SELECTED
;
1626 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1629 item
.mask
= LVIF_PARAM
;
1633 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1636 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
1637 item
.state
= LVIS_SELECTED
;
1641 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1644 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1647 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1650 r
= SendMessage(hwnd
, LVM_SORTITEMS
, 0, (LPARAM
)test_CallBackCompare
);
1653 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1655 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1657 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_SELECTED
);
1659 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_SELECTED
);
1660 expect(LVIS_SELECTED
, r
);
1661 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_SELECTED
);
1662 expect(LVIS_SELECTED
, r
);
1664 DestroyWindow(hwnd
);
1666 /* switch to LVS_SORTASCENDING when some items added */
1667 hwnd
= create_listview_control(0);
1668 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1670 item
.mask
= LVIF_TEXT
;
1673 item
.pszText
= names
[1];
1674 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1677 item
.mask
= LVIF_TEXT
;
1680 item
.pszText
= names
[2];
1681 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1684 item
.mask
= LVIF_TEXT
;
1687 item
.pszText
= names
[0];
1688 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1691 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1692 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
1693 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1694 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
1696 /* no sorting performed when switched to LVS_SORTASCENDING */
1697 item
.mask
= LVIF_TEXT
;
1699 item
.pszText
= buff
;
1700 item
.cchTextMax
= sizeof(buff
);
1701 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1703 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
1706 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1708 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
1711 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1713 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
1715 /* adding new item doesn't resort list */
1716 item
.mask
= LVIF_TEXT
;
1719 item
.pszText
= names
[3];
1720 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
1723 item
.mask
= LVIF_TEXT
;
1725 item
.pszText
= buff
;
1726 item
.cchTextMax
= sizeof(buff
);
1727 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1729 todo_wine
ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
1732 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1734 todo_wine
ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
1737 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1739 todo_wine
ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
1742 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1744 ok(lstrcmp(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
1746 DestroyWindow(hwnd
);
1749 static void test_ownerdata(void)
1752 LONG_PTR style
, ret
;
1756 /* it isn't possible to set LVS_OWNERDATA after creation */
1757 hwnd
= create_listview_control(0);
1758 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1759 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1760 ok(!(style
& LVS_OWNERDATA
) && style
, "LVS_OWNERDATA isn't expected\n");
1762 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1764 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
1765 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
1766 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
1767 "try to switch to LVS_OWNERDATA seq", FALSE
);
1769 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1770 ok(!(style
& LVS_OWNERDATA
), "LVS_OWNERDATA isn't expected\n");
1771 DestroyWindow(hwnd
);
1773 /* try to set LVS_OWNERDATA after creation just having it */
1774 hwnd
= create_listview_control(LVS_OWNERDATA
);
1775 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1776 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1777 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
1779 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1781 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
1782 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
1783 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
1784 "try to switch to LVS_OWNERDATA seq", FALSE
);
1785 DestroyWindow(hwnd
);
1787 /* try to remove LVS_OWNERDATA after creation just having it */
1788 hwnd
= create_listview_control(LVS_OWNERDATA
);
1789 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1790 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1791 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
1793 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1795 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_OWNERDATA
);
1796 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
1797 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
1798 "try to switch to LVS_OWNERDATA seq", FALSE
);
1799 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1800 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
1801 DestroyWindow(hwnd
);
1803 /* try select an item */
1804 hwnd
= create_listview_control(LVS_OWNERDATA
);
1805 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1806 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
1807 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
1808 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1810 memset(&item
, 0, sizeof(item
));
1811 item
.stateMask
= LVIS_SELECTED
;
1812 item
.state
= LVIS_SELECTED
;
1813 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
1815 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1817 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1819 DestroyWindow(hwnd
);
1821 /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
1822 hwnd
= create_listview_control(LVS_OWNERDATA
);
1823 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1824 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
1825 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
1826 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1828 memset(&item
, 0, sizeof(item
));
1829 item
.mask
= LVIF_STATE
;
1831 item
.stateMask
= LVIS_SELECTED
;
1832 item
.state
= LVIS_SELECTED
;
1833 res
= SendMessageA(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
1835 DestroyWindow(hwnd
);
1838 START_TEST(listview
)
1841 BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
1843 hComctl32
= GetModuleHandleA("comctl32.dll");
1844 pInitCommonControlsEx
= (void*)GetProcAddress(hComctl32
, "InitCommonControlsEx");
1845 if (pInitCommonControlsEx
)
1847 INITCOMMONCONTROLSEX iccex
;
1848 iccex
.dwSize
= sizeof(iccex
);
1849 iccex
.dwICC
= ICC_LISTVIEW_CLASSES
;
1850 pInitCommonControlsEx(&iccex
);
1853 InitCommonControls();
1855 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
1857 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1858 hwndparent
= create_parent_window();
1859 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_parent_wnd_seq
, "create parent window", TRUE
);
1860 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1868 test_icon_spacing();
1871 test_item_position();
1875 test_subitem_rect();