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 EDITBOX_SEQ_INDEX 3
33 #define NUM_MSG_SEQUENCES 4
38 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
39 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
40 "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
42 static const WCHAR testparentclassW
[] =
43 {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
45 HWND hwndparent
, hwndparentW
;
46 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
48 /* format reported to control:
49 -1 falls to defproc, anything else returned */
51 /* indicates we're running < 5.80 version */
54 static HWND
subclass_editbox(HWND hwndListview
);
56 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
58 static const struct message create_parent_wnd_seq
[] = {
59 { WM_GETMINMAXINFO
, sent
},
60 { WM_NCCREATE
, sent
},
61 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
63 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
64 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
65 { WM_QUERYNEWPALETTE
, sent
|optional
},
66 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
67 { WM_WINDOWPOSCHANGED
, sent
|optional
},
68 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
69 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
70 { WM_NCACTIVATE
, sent
|wparam
, 1 },
71 { WM_ACTIVATE
, sent
|wparam
, 1 },
72 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
73 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
74 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
75 /* Win9x adds SWP_NOZORDER below */
76 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
77 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
83 static const struct message redraw_listview_seq
[] = {
84 { WM_PAINT
, sent
|id
, 0, 0, LISTVIEW_ID
},
85 { WM_PAINT
, sent
|id
, 0, 0, HEADER_ID
},
86 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
87 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
88 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
89 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
90 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
94 static const struct message listview_icon_spacing_seq
[] = {
95 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(20, 30) },
96 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(25, 35) },
97 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(-1, -1) },
101 static const struct message listview_color_seq
[] = {
102 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
103 { LVM_GETBKCOLOR
, sent
},
104 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
105 { LVM_GETTEXTCOLOR
, sent
},
106 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
107 { LVM_GETTEXTBKCOLOR
, sent
},
109 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
110 { LVM_GETBKCOLOR
, sent
},
111 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
112 { LVM_GETTEXTCOLOR
, sent
},
113 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
114 { LVM_GETTEXTBKCOLOR
, sent
},
116 { LVM_SETBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
117 { LVM_GETBKCOLOR
, sent
},
118 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, CLR_NONE
},
119 { LVM_GETTEXTCOLOR
, sent
},
120 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
121 { LVM_GETTEXTBKCOLOR
, sent
},
123 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
124 { LVM_GETBKCOLOR
, sent
},
125 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
126 { LVM_GETTEXTCOLOR
, sent
},
127 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
128 { LVM_GETTEXTBKCOLOR
, sent
},
132 static const struct message listview_item_count_seq
[] = {
133 { LVM_GETITEMCOUNT
, sent
},
134 { LVM_INSERTITEM
, sent
},
135 { LVM_INSERTITEM
, sent
},
136 { LVM_INSERTITEM
, sent
},
137 { LVM_GETITEMCOUNT
, sent
},
138 { LVM_DELETEITEM
, sent
|wparam
, 2 },
139 { LVM_GETITEMCOUNT
, sent
},
140 { LVM_DELETEALLITEMS
, sent
},
141 { LVM_GETITEMCOUNT
, sent
},
142 { LVM_INSERTITEM
, sent
},
143 { LVM_INSERTITEM
, sent
},
144 { LVM_GETITEMCOUNT
, sent
},
145 { LVM_INSERTITEM
, sent
},
146 { LVM_GETITEMCOUNT
, sent
},
150 static const struct message listview_itempos_seq
[] = {
151 { LVM_INSERTITEM
, sent
},
152 { LVM_INSERTITEM
, sent
},
153 { LVM_INSERTITEM
, sent
},
154 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 1, MAKELPARAM(10,5) },
155 { LVM_GETITEMPOSITION
, sent
|wparam
, 1 },
156 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 2, MAKELPARAM(0,0) },
157 { LVM_GETITEMPOSITION
, sent
|wparam
, 2 },
158 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 0, MAKELPARAM(20,20) },
159 { LVM_GETITEMPOSITION
, sent
|wparam
, 0 },
163 static const struct message listview_ownerdata_switchto_seq
[] = {
164 { WM_STYLECHANGING
, sent
},
165 { WM_STYLECHANGED
, sent
},
169 static const struct message listview_getorderarray_seq
[] = {
170 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
171 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
175 static const struct message empty_seq
[] = {
179 static const struct message forward_erasebkgnd_parent_seq
[] = {
180 { WM_ERASEBKGND
, sent
},
184 static const struct message ownderdata_select_focus_parent_seq
[] = {
185 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
186 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
190 static const struct message textcallback_set_again_parent_seq
[] = {
191 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
192 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
196 static const struct message single_getdispinfo_parent_seq
[] = {
197 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
201 static const struct message getitemposition_seq1
[] = {
202 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
206 static const struct message getitemposition_seq2
[] = {
207 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
208 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
212 static const struct message editbox_create_pos
[] = {
213 /* sequence sent after LVN_BEGINLABELEDIT */
214 { WM_WINDOWPOSCHANGING
, sent
},
215 { WM_NCCALCSIZE
, sent
},
216 { WM_WINDOWPOSCHANGED
, sent
},
217 { WM_MOVE
, sent
|defwinproc
},
218 { WM_SIZE
, sent
|defwinproc
},
219 /* the rest is todo */
220 { WM_WINDOWPOSCHANGING
, sent
},
221 { WM_WINDOWPOSCHANGED
, sent
},
230 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
232 static LONG defwndproc_counter
= 0;
236 msg
.message
= message
;
237 msg
.flags
= sent
|wparam
|lparam
;
238 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
241 if (message
== WM_NOTIFY
&& lParam
) msg
.id
= ((NMHDR
*)lParam
)->code
;
243 /* log system messages, except for painting */
244 if (message
< WM_USER
&&
245 message
!= WM_PAINT
&&
246 message
!= WM_ERASEBKGND
&&
247 message
!= WM_NCPAINT
&&
248 message
!= WM_NCHITTEST
&&
249 message
!= WM_GETTEXT
&&
250 message
!= WM_GETICON
&&
251 message
!= WM_DEVICECHANGE
)
253 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
255 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
257 add_message(sequences
, PARENT_FULL_SEQ_INDEX
, &msg
);
263 switch (((NMHDR
*)lParam
)->code
)
265 case LVN_BEGINLABELEDIT
:
266 /* subclass edit box */
268 subclass_editbox(((NMHDR
*)lParam
)->hwndFrom
);
272 case LVN_ENDLABELEDIT
:
273 /* always accept new item text */
278 case WM_NOTIFYFORMAT
:
280 /* force to return format */
281 if (lParam
== NF_QUERY
&& notifyFormat
!= -1) return notifyFormat
;
286 defwndproc_counter
++;
287 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
288 defwndproc_counter
--;
293 static BOOL
register_parent_wnd_class(BOOL Unicode
)
301 clsW
.lpfnWndProc
= parent_wnd_proc
;
304 clsW
.hInstance
= GetModuleHandleW(NULL
);
306 clsW
.hCursor
= LoadCursorA(0, IDC_ARROW
);
307 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
308 clsW
.lpszMenuName
= NULL
;
309 clsW
.lpszClassName
= testparentclassW
;
314 clsA
.lpfnWndProc
= parent_wnd_proc
;
317 clsA
.hInstance
= GetModuleHandleA(NULL
);
319 clsA
.hCursor
= LoadCursorA(0, IDC_ARROW
);
320 clsA
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
321 clsA
.lpszMenuName
= NULL
;
322 clsA
.lpszClassName
= "Listview test parent class";
325 return Unicode
? RegisterClassW(&clsW
) : RegisterClassA(&clsA
);
328 static HWND
create_parent_window(BOOL Unicode
)
330 static const WCHAR nameW
[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W'};
332 if (!register_parent_wnd_class(Unicode
))
339 return CreateWindowExW(0, testparentclassW
, nameW
,
340 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
341 WS_MAXIMIZEBOX
| WS_VISIBLE
,
343 GetDesktopWindow(), NULL
, GetModuleHandleW(NULL
), NULL
);
345 return CreateWindowExA(0, "Listview test parent class",
346 "Listview test parent window",
347 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
348 WS_MAXIMIZEBOX
| WS_VISIBLE
,
350 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
353 static LRESULT WINAPI
listview_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
355 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
356 static LONG defwndproc_counter
= 0;
360 trace("listview: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
362 /* some debug output for style changing */
363 if ((message
== WM_STYLECHANGING
||
364 message
== WM_STYLECHANGED
) && lParam
)
366 STYLESTRUCT
*style
= (STYLESTRUCT
*)lParam
;
367 trace("\told style: 0x%08x, new style: 0x%08x\n", style
->styleOld
, style
->styleNew
);
370 msg
.message
= message
;
371 msg
.flags
= sent
|wparam
|lparam
;
372 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
375 msg
.id
= LISTVIEW_ID
;
376 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
378 defwndproc_counter
++;
379 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
380 defwndproc_counter
--;
384 static HWND
create_listview_control(DWORD style
)
386 struct subclass_info
*info
;
390 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
394 GetClientRect(hwndparent
, &rect
);
395 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
396 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
| style
,
397 0, 0, rect
.right
, rect
.bottom
,
398 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
399 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
403 HeapFree(GetProcessHeap(), 0, info
);
407 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
408 (LONG_PTR
)listview_subclass_proc
);
409 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
414 /* unicode listview window with specified parent */
415 static HWND
create_listview_controlW(DWORD style
, HWND parent
)
417 struct subclass_info
*info
;
420 static const WCHAR nameW
[] = {'f','o','o',0};
422 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
426 GetClientRect(parent
, &rect
);
427 hwnd
= CreateWindowExW(0, WC_LISTVIEWW
, nameW
,
428 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
| style
,
429 0, 0, rect
.right
, rect
.bottom
,
430 parent
, NULL
, GetModuleHandleW(NULL
), NULL
);
431 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
435 HeapFree(GetProcessHeap(), 0, info
);
439 info
->oldproc
= (WNDPROC
)SetWindowLongPtrW(hwnd
, GWLP_WNDPROC
,
440 (LONG_PTR
)listview_subclass_proc
);
441 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
446 static HWND
create_custom_listview_control(DWORD style
)
448 struct subclass_info
*info
;
452 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
456 GetClientRect(hwndparent
, &rect
);
457 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
458 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
459 0, 0, rect
.right
, rect
.bottom
,
460 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
461 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
465 HeapFree(GetProcessHeap(), 0, info
);
469 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
470 (LONG_PTR
)listview_subclass_proc
);
471 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
476 static LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
478 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
479 static LONG defwndproc_counter
= 0;
483 trace("header: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
485 msg
.message
= message
;
486 msg
.flags
= sent
|wparam
|lparam
;
487 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
491 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
493 defwndproc_counter
++;
494 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
495 defwndproc_counter
--;
499 static HWND
subclass_header(HWND hwndListview
)
501 struct subclass_info
*info
;
504 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
508 hwnd
= ListView_GetHeader(hwndListview
);
509 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
510 (LONG_PTR
)header_subclass_proc
);
511 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
516 static LRESULT WINAPI
editbox_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
518 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
519 static LONG defwndproc_counter
= 0;
523 msg
.message
= message
;
524 msg
.flags
= sent
|wparam
|lparam
;
525 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
529 /* all we need is sizing */
530 if (message
== WM_WINDOWPOSCHANGING
||
531 message
== WM_NCCALCSIZE
||
532 message
== WM_WINDOWPOSCHANGED
||
533 message
== WM_MOVE
||
536 add_message(sequences
, EDITBOX_SEQ_INDEX
, &msg
);
539 defwndproc_counter
++;
540 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
541 defwndproc_counter
--;
545 static HWND
subclass_editbox(HWND hwndListview
)
547 struct subclass_info
*info
;
550 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
554 hwnd
= (HWND
)SendMessage(hwndListview
, LVM_GETEDITCONTROL
, 0, 0);
555 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
556 (LONG_PTR
)editbox_subclass_proc
);
557 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
562 /* Performs a single LVM_HITTEST test */
563 static void test_lvm_hittest(HWND hwnd
, INT x
, INT y
, INT item
, UINT flags
,
564 BOOL todo_item
, BOOL todo_flags
, int line
)
573 trace("hittesting pt=(%d,%d)\n", lpht
.pt
.x
, lpht
.pt
.y
);
574 ret
= SendMessage(hwnd
, LVM_HITTEST
, 0, (LPARAM
)&lpht
);
580 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
581 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
582 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
587 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
588 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
589 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
595 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
598 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
601 /* Performs a single LVM_SUBITEMHITTEST test */
602 static void test_lvm_subitemhittest(HWND hwnd
, INT x
, INT y
, INT item
, INT subitem
, UINT flags
,
603 BOOL todo_item
, BOOL todo_subitem
, BOOL todo_flags
, int line
)
611 trace("subhittesting pt=(%d,%d)\n", lpht
.pt
.x
, lpht
.pt
.y
);
612 ret
= SendMessage(hwnd
, LVM_SUBITEMHITTEST
, 0, (LPARAM
)&lpht
);
618 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
619 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
624 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
625 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
631 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
634 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
639 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
642 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
645 static void test_images(void)
653 static CHAR hello
[] = "hello";
655 himl
= ImageList_Create(40, 40, 0, 4, 4);
656 ok(himl
!= NULL
, "failed to create imagelist\n");
658 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
659 ok(hbmp
!= NULL
, "failed to create bitmap\n");
661 r
= ImageList_Add(himl
, hbmp
, 0);
662 ok(r
== 0, "should be zero\n");
664 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED
,
665 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
666 ok(hwnd
!= NULL
, "failed to create listview window\n");
668 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0,
669 LVS_EX_UNDERLINEHOT
| LVS_EX_FLATSB
| LVS_EX_ONECLICKACTIVATE
);
671 ok(r
== 0, "should return zero\n");
673 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
674 ok(r
== 0, "should return zero\n");
676 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELONG(100,50));
677 /* returns dimensions */
679 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
680 ok(r
== 0, "should be zero items\n");
682 item
.mask
= LVIF_IMAGE
| LVIF_TEXT
;
687 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
688 ok(r
== -1, "should fail\n");
691 item
.pszText
= hello
;
692 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
693 ok(r
== 0, "should not fail\n");
695 memset(&r1
, 0, sizeof r1
);
697 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r1
);
699 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
700 ok(r
== TRUE
, "should not fail\n");
703 item
.pszText
= hello
;
704 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
705 ok(r
== 0, "should not fail\n");
707 memset(&r2
, 0, sizeof r2
);
709 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r2
);
711 ok(!memcmp(&r1
, &r2
, sizeof r1
), "rectangle should be the same\n");
716 static void test_checkboxes(void)
721 static CHAR text
[] = "Text",
725 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
726 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
727 ok(hwnd
!= NULL
, "failed to create listview window\n");
729 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
730 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
731 item
.stateMask
= 0xffff;
736 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
737 ok(r
== 0, "ret %d\n", r
);
740 item
.mask
= LVIF_STATE
;
741 item
.stateMask
= 0xffff;
742 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
743 ok(item
.state
== 0xfccc, "state %x\n", item
.state
);
745 /* Don't set LVIF_STATE */
746 item
.mask
= LVIF_TEXT
;
747 item
.stateMask
= 0xffff;
752 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
753 ok(r
== 1, "ret %d\n", r
);
756 item
.mask
= LVIF_STATE
;
757 item
.stateMask
= 0xffff;
758 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
759 ok(item
.state
== 0, "state %x\n", item
.state
);
761 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
762 ok(r
== 0, "should return zero\n");
764 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
766 item
.mask
= LVIF_STATE
;
767 item
.stateMask
= 0xffff;
768 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
769 ok(item
.state
== 0x1ccc, "state %x\n", item
.state
);
771 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
773 item
.mask
= LVIF_TEXT
;
775 item
.pszText
= text2
;
776 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
777 ok(r
== 2, "ret %d\n", r
);
780 item
.mask
= LVIF_STATE
;
781 item
.stateMask
= 0xffff;
782 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
783 ok(item
.state
== 0x1000, "state %x\n", item
.state
);
785 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
787 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
788 item
.stateMask
= 0xffff;
790 item
.pszText
= text3
;
791 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
792 ok(r
== 3, "ret %d\n", r
);
795 item
.mask
= LVIF_STATE
;
796 item
.stateMask
= 0xffff;
797 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
798 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
800 /* Set an item's state to checked */
802 item
.mask
= LVIF_STATE
;
803 item
.stateMask
= 0xf000;
805 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
808 item
.mask
= LVIF_STATE
;
809 item
.stateMask
= 0xffff;
810 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
811 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
813 /* Check that only the bits we asked for are returned,
814 * and that all the others are set to zero
817 item
.mask
= LVIF_STATE
;
818 item
.stateMask
= 0xf000;
820 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
821 ok(item
.state
== 0x2000, "state %x\n", item
.state
);
823 /* Set the style again and check that doesn't change an item's state */
824 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
825 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
828 item
.mask
= LVIF_STATE
;
829 item
.stateMask
= 0xffff;
830 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
831 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
833 /* Unsetting the checkbox extended style doesn't change an item's state */
834 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
835 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
838 item
.mask
= LVIF_STATE
;
839 item
.stateMask
= 0xffff;
840 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
841 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
843 /* Now setting the style again will change an item's state */
844 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
845 ok(r
== 0, "ret %x\n", r
);
848 item
.mask
= LVIF_STATE
;
849 item
.stateMask
= 0xffff;
850 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
851 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
853 /* Toggle checkbox tests (bug 9934) */
854 memset (&item
, 0xcc, sizeof(item
));
855 item
.mask
= LVIF_STATE
;
858 item
.state
= LVIS_FOCUSED
;
859 item
.stateMask
= LVIS_FOCUSED
;
860 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
864 item
.mask
= LVIF_STATE
;
865 item
.stateMask
= 0xffff;
866 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
867 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
869 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
871 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
875 item
.mask
= LVIF_STATE
;
876 item
.stateMask
= 0xffff;
877 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
878 ok(item
.state
== 0x2aab, "state %x\n", item
.state
);
880 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
882 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
886 item
.mask
= LVIF_STATE
;
887 item
.stateMask
= 0xffff;
888 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
889 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
894 static void insert_column(HWND hwnd
, int idx
)
899 memset(&column
, 0xcc, sizeof(column
));
900 column
.mask
= LVCF_SUBITEM
;
901 column
.iSubItem
= idx
;
903 rc
= ListView_InsertColumn(hwnd
, idx
, &column
);
907 static void insert_item(HWND hwnd
, int idx
)
909 static CHAR text
[] = "foo";
914 memset(&item
, 0xcc, sizeof (item
));
915 item
.mask
= LVIF_TEXT
;
920 rc
= ListView_InsertItem(hwnd
, &item
);
924 static void test_items(void)
926 const LPARAM lparamTest
= 0x42;
930 static CHAR text
[] = "Text";
932 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
933 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
934 ok(hwnd
!= NULL
, "failed to create listview window\n");
937 * Test setting/getting item params
940 /* Set up two columns */
941 insert_column(hwnd
, 0);
942 insert_column(hwnd
, 1);
944 /* LVIS_SELECTED with zero stateMask */
946 memset (&item
, 0, sizeof (item
));
947 item
.mask
= LVIF_STATE
;
948 item
.state
= LVIS_SELECTED
;
952 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
953 ok(r
== 0, "ret %d\n", r
);
955 memset (&item
, 0xcc, sizeof (item
));
956 item
.mask
= LVIF_STATE
;
957 item
.stateMask
= LVIS_SELECTED
;
961 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
962 ok(r
!= 0, "ret %d\n", r
);
963 ok(item
.state
& LVIS_SELECTED
, "Expected LVIS_SELECTED\n");
964 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
966 /* LVIS_SELECTED with zero stateMask */
968 memset (&item
, 0, sizeof (item
));
969 item
.mask
= LVIF_STATE
;
970 item
.state
= LVIS_FOCUSED
;
974 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
975 ok(r
== 0, "ret %d\n", r
);
977 memset (&item
, 0xcc, sizeof (item
));
978 item
.mask
= LVIF_STATE
;
979 item
.stateMask
= LVIS_FOCUSED
;
983 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
984 ok(r
!= 0, "ret %d\n", r
);
985 ok(item
.state
& LVIS_FOCUSED
, "Expected LVIS_FOCUSED\n");
986 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
988 /* LVIS_CUT with LVIS_FOCUSED stateMask */
990 memset (&item
, 0, sizeof (item
));
991 item
.mask
= LVIF_STATE
;
992 item
.state
= LVIS_CUT
;
993 item
.stateMask
= LVIS_FOCUSED
;
996 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
997 ok(r
== 0, "ret %d\n", r
);
999 memset (&item
, 0xcc, sizeof (item
));
1000 item
.mask
= LVIF_STATE
;
1001 item
.stateMask
= LVIS_CUT
;
1005 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1006 ok(r
!= 0, "ret %d\n", r
);
1007 ok(item
.state
& LVIS_CUT
, "Expected LVIS_CUT\n");
1008 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
1010 /* Insert an item with just a param */
1011 memset (&item
, 0xcc, sizeof (item
));
1012 item
.mask
= LVIF_PARAM
;
1015 item
.lParam
= lparamTest
;
1016 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1017 ok(r
== 0, "ret %d\n", r
);
1019 /* Test getting of the param */
1020 memset (&item
, 0xcc, sizeof (item
));
1021 item
.mask
= LVIF_PARAM
;
1024 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1025 ok(r
!= 0, "ret %d\n", r
);
1026 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1028 /* Set up a subitem */
1029 memset (&item
, 0xcc, sizeof (item
));
1030 item
.mask
= LVIF_TEXT
;
1033 item
.pszText
= text
;
1034 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1035 ok(r
!= 0, "ret %d\n", r
);
1037 /* Query param from subitem: returns main item param */
1038 memset (&item
, 0xcc, sizeof (item
));
1039 item
.mask
= LVIF_PARAM
;
1042 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1043 ok(r
!= 0, "ret %d\n", r
);
1044 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1046 /* Set up param on first subitem: no effect */
1047 memset (&item
, 0xcc, sizeof (item
));
1048 item
.mask
= LVIF_PARAM
;
1051 item
.lParam
= lparamTest
+1;
1052 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1053 ok(r
== 0, "ret %d\n", r
);
1055 /* Query param from subitem again: should still return main item param */
1056 memset (&item
, 0xcc, sizeof (item
));
1057 item
.mask
= LVIF_PARAM
;
1060 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1061 ok(r
!= 0, "ret %d\n", r
);
1062 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1064 /**** Some tests of state highlighting ****/
1065 memset (&item
, 0xcc, sizeof (item
));
1066 item
.mask
= LVIF_STATE
;
1069 item
.state
= LVIS_SELECTED
;
1070 item
.stateMask
= LVIS_SELECTED
| LVIS_DROPHILITED
;
1071 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
1072 ok(r
!= 0, "ret %d\n", r
);
1074 item
.state
= LVIS_DROPHILITED
;
1075 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
1076 ok(r
!= 0, "ret %d\n", r
);
1078 memset (&item
, 0xcc, sizeof (item
));
1079 item
.mask
= LVIF_STATE
;
1082 item
.stateMask
= -1;
1083 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1084 ok(r
!= 0, "ret %d\n", r
);
1085 ok(item
.state
== LVIS_SELECTED
, "got state %x, expected %x\n", item
.state
, LVIS_SELECTED
);
1087 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1088 ok(r
!= 0, "ret %d\n", r
);
1089 todo_wine
ok(item
.state
== LVIS_DROPHILITED
, "got state %x, expected %x\n", item
.state
, LVIS_DROPHILITED
);
1091 /* some notnull but meaningless masks */
1092 memset (&item
, 0, sizeof(item
));
1093 item
.mask
= LVIF_NORECOMPUTE
;
1096 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1097 ok(r
!= 0, "ret %d\n", r
);
1098 memset (&item
, 0, sizeof(item
));
1099 item
.mask
= LVIF_DI_SETITEM
;
1102 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1103 ok(r
!= 0, "ret %d\n", r
);
1105 /* set text to callback value already having it */
1106 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1108 memset (&item
, 0, sizeof (item
));
1109 item
.mask
= LVIF_TEXT
;
1110 item
.pszText
= LPSTR_TEXTCALLBACK
;
1112 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1113 ok(r
== 0, "ret %d\n", r
);
1114 memset (&item
, 0, sizeof (item
));
1116 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1118 item
.pszText
= LPSTR_TEXTCALLBACK
;
1119 r
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0 , (LPARAM
) &item
);
1122 ok_sequence(sequences
, PARENT_SEQ_INDEX
, textcallback_set_again_parent_seq
,
1123 "check callback text comparison rule", FALSE
);
1125 DestroyWindow(hwnd
);
1128 static void test_columns(void)
1130 HWND hwnd
, hwndheader
;
1135 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
1136 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1137 ok(hwnd
!= NULL
, "failed to create listview window\n");
1139 /* Add a column with no mask */
1140 memset(&column
, 0xcc, sizeof(column
));
1142 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
1143 ok(rc
==0, "Inserting column with no mask failed with %d\n", rc
);
1145 /* Check its width */
1146 rc
= ListView_GetColumnWidth(hwnd
, 0);
1148 broken(rc
==0), /* win9x */
1149 "Inserting column with no mask failed to set width to 10 with %d\n", rc
);
1151 DestroyWindow(hwnd
);
1153 /* LVM_GETCOLUMNORDERARRAY */
1154 hwnd
= create_listview_control(0);
1155 hwndheader
= subclass_header(hwnd
);
1157 memset(&column
, 0, sizeof(column
));
1158 column
.mask
= LVCF_WIDTH
;
1160 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
1161 ok(rc
== 0, "Inserting column failed with %d\n", rc
);
1164 rc
= ListView_InsertColumn(hwnd
, 1, &column
);
1165 ok(rc
== 1, "Inserting column failed with %d\n", rc
);
1167 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1169 rc
= SendMessage(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1170 ok(rc
!= 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
1171 ok(order
[0] == 0, "Expected order 0, got %d\n", order
[0]);
1172 ok(order
[1] == 1, "Expected order 1, got %d\n", order
[1]);
1174 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_getorderarray_seq
, "get order array", FALSE
);
1176 DestroyWindow(hwnd
);
1178 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1179 static WNDPROC listviewWndProc
;
1180 static HIMAGELIST test_create_imagelist
;
1182 static LRESULT CALLBACK
create_test_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1186 if (uMsg
== WM_CREATE
)
1188 LPCREATESTRUCT lpcs
= (LPCREATESTRUCT
)lParam
;
1189 lpcs
->style
|= LVS_REPORT
;
1191 ret
= CallWindowProc(listviewWndProc
, hwnd
, uMsg
, wParam
, lParam
);
1192 if (uMsg
== WM_CREATE
) SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)test_create_imagelist
);
1196 static void test_create(void)
1205 cls
.cbSize
= sizeof(WNDCLASSEX
);
1206 ok(GetClassInfoEx(GetModuleHandle(NULL
), "SysListView32", &cls
), "GetClassInfoEx failed\n");
1207 listviewWndProc
= cls
.lpfnWndProc
;
1208 cls
.lpfnWndProc
= create_test_wndproc
;
1209 cls
.lpszClassName
= "MyListView32";
1210 ok(RegisterClassEx(&cls
), "RegisterClassEx failed\n");
1212 test_create_imagelist
= ImageList_Create(16, 16, 0, 5, 10);
1213 hList
= CreateWindow("MyListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
1214 ok((HIMAGELIST
)SendMessage(hList
, LVM_GETIMAGELIST
, 0, 0) == test_create_imagelist
, "Image list not obtained\n");
1215 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1216 ok(IsWindow(hHeader
) && IsWindowVisible(hHeader
), "Listview not in report mode\n");
1217 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1218 DestroyWindow(hList
);
1220 /* header isn't created on LVS_ICON and LVS_LIST styles */
1221 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1222 GetModuleHandle(NULL
), 0);
1223 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1224 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1225 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1227 memset(&col
, 0, sizeof(LVCOLUMNA
));
1228 col
.mask
= LVCF_WIDTH
;
1230 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1231 ok(r
== 0, "Expected 0 column's inserted\n");
1232 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1233 ok(IsWindow(hHeader
), "Header should be created\n");
1234 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1235 DestroyWindow(hList
);
1237 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1238 GetModuleHandle(NULL
), 0);
1239 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1240 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1241 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1243 memset(&col
, 0, sizeof(LVCOLUMNA
));
1244 col
.mask
= LVCF_WIDTH
;
1246 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1247 ok(r
== 0, "Expected 0 column's inserted\n");
1248 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1249 ok(IsWindow(hHeader
), "Header should be created\n");
1250 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1251 DestroyWindow(hList
);
1253 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1254 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1255 GetModuleHandle(NULL
), 0);
1256 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLongPtr(hList
, GWL_STYLE
) | LVS_REPORT
);
1257 ok(ret
& WS_VISIBLE
, "Style wrong, should have WS_VISIBLE\n");
1258 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1259 ok(IsWindow(hHeader
), "Header should be created\n");
1260 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLong(hList
, GWL_STYLE
) & ~LVS_REPORT
);
1261 ok((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1262 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1263 ok(IsWindow(hHeader
), "Header should be created\n");
1264 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1265 DestroyWindow(hList
);
1267 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1268 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1269 GetModuleHandle(NULL
), 0);
1270 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
1271 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_LIST
) | LVS_REPORT
);
1272 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_LIST
)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1273 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1274 ok(IsWindow(hHeader
), "Header should be created\n");
1275 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1276 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
1277 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_REPORT
) | LVS_LIST
);
1278 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1279 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1280 ok(IsWindow(hHeader
), "Header should be created\n");
1281 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1282 DestroyWindow(hList
);
1284 /* LVS_REPORT without WS_VISIBLE */
1285 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1286 GetModuleHandle(NULL
), 0);
1287 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1288 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1289 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1291 memset(&col
, 0, sizeof(LVCOLUMNA
));
1292 col
.mask
= LVCF_WIDTH
;
1294 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1295 ok(r
== 0, "Expected 0 column's inserted\n");
1296 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1297 ok(IsWindow(hHeader
), "Header should be created\n");
1298 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1299 DestroyWindow(hList
);
1301 /* LVS_REPORT without WS_VISIBLE, try to show it */
1302 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1303 GetModuleHandle(NULL
), 0);
1304 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1305 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1306 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1307 ShowWindow(hList
, SW_SHOW
);
1308 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1309 ok(IsWindow(hHeader
), "Header should be created\n");
1310 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1311 DestroyWindow(hList
);
1313 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1314 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
|LVS_NOCOLUMNHEADER
|WS_VISIBLE
,
1315 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
1316 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1317 ok(IsWindow(hHeader
), "Header should be created\n");
1318 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1319 /* HDS_DRAGDROP set by default */
1320 ok(GetWindowLongPtr(hHeader
, GWL_STYLE
) & HDS_DRAGDROP
, "Expected header to have HDS_DRAGDROP\n");
1321 DestroyWindow(hList
);
1323 /* setting LVS_EX_HEADERDRAGDROP creates header */
1324 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1325 GetModuleHandle(NULL
), 0);
1326 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1327 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1328 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1329 SendMessage(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1330 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1331 ok(IsWindow(hHeader
), "Header should be created\n");
1332 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1333 DestroyWindow(hList
);
1335 /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1336 hList
= create_custom_listview_control(0);
1337 SendMessage(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1338 r
= SendMessage(hList
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1339 ok(r
& LVS_EX_HEADERDRAGDROP
, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1340 DestroyWindow(hList
);
1342 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1343 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1344 GetModuleHandle(NULL
), 0);
1345 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1346 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1348 rect
.left
= LVIR_BOUNDS
;
1350 rect
.right
= rect
.bottom
= -10;
1351 r
= SendMessage(hList
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1352 ok(r
!= 0, "Expected not-null LRESULT\n");
1354 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1355 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1356 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1358 DestroyWindow(hList
);
1361 static void test_redraw(void)
1363 HWND hwnd
, hwndheader
;
1368 hwnd
= create_listview_control(0);
1369 hwndheader
= subclass_header(hwnd
);
1371 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1373 trace("invalidate & update\n");
1374 InvalidateRect(hwnd
, NULL
, TRUE
);
1376 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, redraw_listview_seq
, "redraw listview", FALSE
);
1378 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1380 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1381 /* 1. Without backbuffer */
1382 res
= ListView_SetBkColor(hwnd
, CLR_NONE
);
1385 hdc
= GetWindowDC(hwndparent
);
1387 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1388 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1389 ok(r
!= 0, "Expected not zero result\n");
1390 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1391 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1393 res
= ListView_SetBkColor(hwnd
, CLR_DEFAULT
);
1396 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1397 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1398 ok(r
!= 0, "Expected not zero result\n");
1399 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1400 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1402 /* 2. With backbuffer */
1403 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_DOUBLEBUFFER
,
1404 LVS_EX_DOUBLEBUFFER
);
1405 res
= ListView_SetBkColor(hwnd
, CLR_NONE
);
1408 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1409 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1410 ok(r
!= 0, "Expected not zero result\n");
1411 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1412 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1414 res
= ListView_SetBkColor(hwnd
, CLR_DEFAULT
);
1417 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1418 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1419 todo_wine
ok(r
!= 0, "Expected not zero result\n");
1420 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1421 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1423 ReleaseDC(hwndparent
, hdc
);
1425 DestroyWindow(hwnd
);
1428 static LRESULT WINAPI
cd_wndproc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1430 COLORREF clr
, c0ffee
= RGB(0xc0, 0xff, 0xee);
1432 if(msg
== WM_NOTIFY
) {
1433 NMHDR
*nmhdr
= (PVOID
)lp
;
1434 if(nmhdr
->code
== NM_CUSTOMDRAW
) {
1435 NMLVCUSTOMDRAW
*nmlvcd
= (PVOID
)nmhdr
;
1436 trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd
->nmcd
.dwDrawStage
);
1437 switch(nmlvcd
->nmcd
.dwDrawStage
) {
1439 SetBkColor(nmlvcd
->nmcd
.hdc
, c0ffee
);
1440 return CDRF_NOTIFYITEMDRAW
;
1441 case CDDS_ITEMPREPAINT
:
1442 nmlvcd
->clrTextBk
= CLR_DEFAULT
;
1443 return CDRF_NOTIFYSUBITEMDRAW
;
1444 case CDDS_ITEMPREPAINT
| CDDS_SUBITEM
:
1445 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1446 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1447 return CDRF_NOTIFYPOSTPAINT
;
1448 case CDDS_ITEMPOSTPAINT
| CDDS_SUBITEM
:
1449 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1450 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1451 return CDRF_DODEFAULT
;
1453 return CDRF_DODEFAULT
;
1457 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
1460 static void test_customdraw(void)
1465 hwnd
= create_listview_control(0);
1467 insert_column(hwnd
, 0);
1468 insert_column(hwnd
, 1);
1469 insert_item(hwnd
, 0);
1471 oldwndproc
= (WNDPROC
)SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
,
1472 (LONG_PTR
)cd_wndproc
);
1474 InvalidateRect(hwnd
, NULL
, TRUE
);
1477 SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
, (LONG_PTR
)oldwndproc
);
1479 DestroyWindow(hwnd
);
1482 static void test_icon_spacing(void)
1484 /* LVM_SETICONSPACING */
1485 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1491 hwnd
= create_custom_listview_control(LVS_ICON
);
1492 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1494 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, (WPARAM
)hwndparent
, (LPARAM
)NF_REQUERY
);
1495 expect(NFR_ANSI
, r
);
1497 /* reset the icon spacing to defaults */
1498 SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1500 /* now we can request what the defaults are */
1501 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1505 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1507 trace("test icon spacing\n");
1509 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(20, 30));
1510 ok(r
== MAKELONG(w
, h
) ||
1511 broken(r
== MAKELONG(w
, w
)), /* win98 */
1512 "Expected %d, got %d\n", MAKELONG(w
, h
), r
);
1514 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(25, 35));
1515 expect(MAKELONG(20,30), r
);
1517 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1,-1));
1518 expect(MAKELONG(25,35), r
);
1520 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_icon_spacing_seq
, "test icon spacing seq", FALSE
);
1522 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1523 DestroyWindow(hwnd
);
1526 static void test_color(void)
1528 /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1535 COLORREF colors
[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE
, RGB(255,255,255)};
1537 hwnd
= create_listview_control(0);
1538 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1540 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1542 trace("test color seq\n");
1543 for (i
= 0; i
< 4; i
++)
1547 r
= SendMessage(hwnd
, LVM_SETBKCOLOR
, 0, color
);
1549 r
= SendMessage(hwnd
, LVM_GETBKCOLOR
, 0, color
);
1552 r
= SendMessage(hwnd
, LVM_SETTEXTCOLOR
, 0, color
);
1554 r
= SendMessage(hwnd
, LVM_GETTEXTCOLOR
, 0, color
);
1557 r
= SendMessage(hwnd
, LVM_SETTEXTBKCOLOR
, 0, color
);
1559 r
= SendMessage(hwnd
, LVM_GETTEXTBKCOLOR
, 0, color
);
1563 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_color_seq
, "test color seq", FALSE
);
1565 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1566 DestroyWindow(hwnd
);
1569 static void test_item_count(void)
1571 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1584 static CHAR item0text
[] = "item0";
1585 static CHAR item1text
[] = "item1";
1586 static CHAR item2text
[] = "item2";
1588 hwnd
= create_listview_control(0);
1589 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1591 /* resize in dpiaware manner to fit all 3 items added */
1593 hOldFont
= SelectObject(hdc
, GetStockObject(SYSTEM_FONT
));
1594 GetTextMetricsA(hdc
, &tm
);
1595 /* 2 extra pixels for bounds and header border */
1596 height
= tm
.tmHeight
+ 2;
1597 SelectObject(hdc
, hOldFont
);
1600 GetWindowRect(hwnd
, &rect
);
1601 /* 3 items + 1 header + 1 to be sure */
1602 MoveWindow(hwnd
, 0, 0, rect
.right
- rect
.left
, 5 * height
, FALSE
);
1604 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1606 trace("test item count\n");
1608 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1612 item0
.mask
= LVIF_TEXT
;
1615 item0
.pszText
= item0text
;
1616 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1619 /* [item0, item1] */
1620 item1
.mask
= LVIF_TEXT
;
1623 item1
.pszText
= item1text
;
1624 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1627 /* [item0, item1, item2] */
1628 item2
.mask
= LVIF_TEXT
;
1631 item2
.pszText
= item2text
;
1632 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1635 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1638 /* [item0, item1] */
1639 r
= SendMessage(hwnd
, LVM_DELETEITEM
, 2, 0);
1642 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1646 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1649 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1653 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1656 /* [item0, item1] */
1657 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1660 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1663 /* [item0, item1, item2] */
1664 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1667 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1670 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_item_count_seq
, "test item count seq", FALSE
);
1672 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1673 DestroyWindow(hwnd
);
1676 static void test_item_position(void)
1678 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1687 static CHAR item0text
[] = "item0";
1688 static CHAR item1text
[] = "item1";
1689 static CHAR item2text
[] = "item2";
1691 hwnd
= create_custom_listview_control(LVS_ICON
);
1692 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1694 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1696 trace("test item position\n");
1699 item0
.mask
= LVIF_TEXT
;
1702 item0
.pszText
= item0text
;
1703 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1706 /* [item0, item1] */
1707 item1
.mask
= LVIF_TEXT
;
1710 item1
.pszText
= item1text
;
1711 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1714 /* [item0, item1, item2] */
1715 item2
.mask
= LVIF_TEXT
;
1718 item2
.pszText
= item2text
;
1719 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1722 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 1, MAKELPARAM(10,5));
1724 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 1, (LPARAM
) &position
);
1726 expect2(10, 5, position
.x
, position
.y
);
1728 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 2, MAKELPARAM(0,0));
1730 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 2, (LPARAM
) &position
);
1732 expect2(0, 0, position
.x
, position
.y
);
1734 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 0, MAKELPARAM(20,20));
1736 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
) &position
);
1738 expect2(20, 20, position
.x
, position
.y
);
1740 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_itempos_seq
, "test item position seq", TRUE
);
1742 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1743 DestroyWindow(hwnd
);
1746 static void test_getorigin(void)
1754 position
.x
= position
.y
= 0;
1756 hwnd
= create_custom_listview_control(LVS_ICON
);
1757 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1758 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1759 trace("test get origin results\n");
1760 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1762 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1763 DestroyWindow(hwnd
);
1765 hwnd
= create_custom_listview_control(LVS_SMALLICON
);
1766 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1767 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1768 trace("test get origin results\n");
1769 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1771 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1772 DestroyWindow(hwnd
);
1774 hwnd
= create_custom_listview_control(LVS_LIST
);
1775 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1776 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1777 trace("test get origin results\n");
1778 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1780 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1781 DestroyWindow(hwnd
);
1783 hwnd
= create_custom_listview_control(LVS_REPORT
);
1784 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1785 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1786 trace("test get origin results\n");
1787 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1789 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1790 DestroyWindow(hwnd
);
1794 static void test_multiselect(void)
1796 typedef struct t_select_task
1807 int i
,j
,item_count
,selected_count
;
1808 static const int items
=5;
1814 static struct t_select_task task_list
[] = {
1815 { "using VK_DOWN", 0, VK_DOWN
, -1, -1 },
1816 { "using VK_UP", -1, VK_UP
, -1, -1 },
1817 { "using VK_END", 0, VK_END
, 1, -1 },
1818 { "using VK_HOME", -1, VK_HOME
, 1, -1 }
1822 hwnd
= create_listview_control(0);
1824 for (i
=0;i
<items
;i
++) {
1825 insert_item(hwnd
, 0);
1828 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1830 expect(items
,item_count
);
1833 task
= task_list
[i
];
1835 /* deselect all items */
1836 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1837 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1839 /* set initial position */
1840 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, (task
.initPos
== -1 ? item_count
-1 : task
.initPos
));
1841 ListView_SetItemState(hwnd
,(task
.initPos
== -1 ? item_count
-1 : task
.initPos
),LVIS_SELECTED
,LVIS_SELECTED
);
1843 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1845 ok(selected_count
== 1, "There should be only one selected item at the beginning (is %d)\n",selected_count
);
1847 /* Set SHIFT key pressed */
1848 GetKeyboardState(kstate
);
1849 kstate
[VK_SHIFT
]=0x80;
1850 SetKeyboardState(kstate
);
1852 for (j
=1;j
<=(task
.count
== -1 ? item_count
: task
.count
);j
++) {
1853 r
= SendMessage(hwnd
, WM_KEYDOWN
, task
.loopVK
, 0);
1855 r
= SendMessage(hwnd
, WM_KEYUP
, task
.loopVK
, 0);
1859 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1861 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
);
1863 /* Set SHIFT key released */
1864 GetKeyboardState(kstate
);
1865 kstate
[VK_SHIFT
]=0x00;
1866 SetKeyboardState(kstate
);
1868 DestroyWindow(hwnd
);
1870 /* make multiple selection, then switch to LVS_SINGLESEL */
1871 hwnd
= create_listview_control(0);
1872 for (i
=0;i
<items
;i
++) {
1873 insert_item(hwnd
, 0);
1875 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1876 expect(items
,item_count
);
1877 /* deselect all items */
1878 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1879 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1881 ListView_SetItemState(hwnd
, i
, LVIS_SELECTED
, LVIS_SELECTED
);
1884 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1886 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1890 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1891 ok(!(style
& LVS_SINGLESEL
), "LVS_SINGLESEL isn't expected\n");
1892 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SINGLESEL
);
1893 /* check that style is accepted */
1894 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1895 ok(style
& LVS_SINGLESEL
, "LVS_SINGLESEL expected\n");
1898 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1899 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1901 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1903 SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1906 /* select one more */
1907 ListView_SetItemState(hwnd
, 3, LVIS_SELECTED
, LVIS_SELECTED
);
1910 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1911 ok(!(r
& LVIS_SELECTED
), "Expected item %d to be unselected\n", i
);
1913 r
= ListView_GetItemState(hwnd
, 3, LVIS_SELECTED
);
1914 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1916 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1918 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1922 /* try to select all on LVS_SINGLESEL */
1923 memset(&item
, 0, sizeof(item
));
1924 item
.stateMask
= LVIS_SELECTED
;
1925 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1927 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1929 item
.stateMask
= LVIS_SELECTED
;
1930 item
.state
= LVIS_SELECTED
;
1931 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1934 r
= ListView_GetSelectedCount(hwnd
);
1936 r
= ListView_GetSelectionMark(hwnd
);
1939 /* try to deselect all on LVS_SINGLESEL */
1940 item
.stateMask
= LVIS_SELECTED
;
1941 item
.state
= LVIS_SELECTED
;
1942 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
1945 item
.stateMask
= LVIS_SELECTED
;
1947 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1949 r
= ListView_GetSelectedCount(hwnd
);
1952 DestroyWindow(hwnd
);
1955 static void test_subitem_rect(void)
1962 /* test LVM_GETSUBITEMRECT for header */
1963 hwnd
= create_listview_control(0);
1964 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1965 /* add some columns */
1966 memset(&col
, 0, sizeof(LVCOLUMN
));
1967 col
.mask
= LVCF_WIDTH
;
1970 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1974 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 1, (LPARAM
)&col
);
1978 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 2, (LPARAM
)&col
);
1980 /* item = -1 means header, subitem index is 1 based */
1981 rect
.left
= LVIR_BOUNDS
;
1983 rect
.right
= rect
.bottom
= 0;
1984 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1987 rect
.left
= LVIR_BOUNDS
;
1989 rect
.right
= rect
.bottom
= 0;
1990 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1992 ok(r
!= 0, "Expected not-null LRESULT\n");
1993 expect(100, rect
.left
);
1994 expect(250, rect
.right
);
1996 expect(3, rect
.top
);
1998 rect
.left
= LVIR_BOUNDS
;
2000 rect
.right
= rect
.bottom
= 0;
2001 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2003 ok(r
!= 0, "Expected not-null LRESULT\n");
2004 expect(250, rect
.left
);
2005 expect(450, rect
.right
);
2007 expect(3, rect
.top
);
2009 /* item LVS_REPORT padding isn't applied to subitems */
2010 insert_item(hwnd
, 0);
2012 rect
.left
= LVIR_BOUNDS
;
2014 rect
.right
= rect
.bottom
= 0;
2015 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2016 ok(r
!= 0, "Expected not-null LRESULT\n");
2017 expect(100, rect
.left
);
2018 expect(250, rect
.right
);
2020 rect
.left
= LVIR_ICON
;
2022 rect
.right
= rect
.bottom
= 0;
2023 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2024 ok(r
!= 0, "Expected not-null LRESULT\n");
2025 /* no icon attached - zero width rectangle, with no left padding */
2026 expect(100, rect
.left
);
2027 expect(100, rect
.right
);
2029 rect
.left
= LVIR_LABEL
;
2031 rect
.right
= rect
.bottom
= 0;
2032 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2033 ok(r
!= 0, "Expected not-null LRESULT\n");
2034 /* same as full LVIR_BOUNDS */
2035 expect(100, rect
.left
);
2036 expect(250, rect
.right
);
2038 DestroyWindow(hwnd
);
2040 /* try it for non LVS_REPORT style */
2041 hwnd
= CreateWindow("SysListView32", "Test", LVS_ICON
, 0, 0, 100, 100, NULL
, NULL
,
2042 GetModuleHandle(NULL
), 0);
2043 rect
.left
= LVIR_BOUNDS
;
2045 rect
.right
= rect
.bottom
= -10;
2046 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2047 ok(r
== 0, "Expected not-null LRESULT\n");
2048 /* rect is unchanged */
2049 expect(0, rect
.left
);
2050 expect(-10, rect
.right
);
2051 expect(1, rect
.top
);
2052 expect(-10, rect
.bottom
);
2053 DestroyWindow(hwnd
);
2056 /* comparison callback for test_sorting */
2057 static INT WINAPI
test_CallBackCompare(LPARAM first
, LPARAM second
, LPARAM lParam
)
2059 if (first
== second
) return 0;
2060 return (first
> second
? 1 : -1);
2063 static void test_sorting(void)
2069 static CHAR names
[][5] = {"A", "B", "C", "D", "0"};
2072 hwnd
= create_listview_control(0);
2073 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2075 /* insert some items */
2076 item
.mask
= LVIF_PARAM
| LVIF_STATE
;
2077 item
.state
= LVIS_SELECTED
;
2081 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2084 item
.mask
= LVIF_PARAM
;
2088 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2091 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
2092 item
.state
= LVIS_SELECTED
;
2096 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2099 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2102 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2105 r
= SendMessage(hwnd
, LVM_SORTITEMS
, 0, (LPARAM
)test_CallBackCompare
);
2108 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2110 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2112 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_SELECTED
);
2114 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_SELECTED
);
2115 expect(LVIS_SELECTED
, r
);
2116 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_SELECTED
);
2117 expect(LVIS_SELECTED
, r
);
2119 DestroyWindow(hwnd
);
2121 /* switch to LVS_SORTASCENDING when some items added */
2122 hwnd
= create_listview_control(0);
2123 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2125 item
.mask
= LVIF_TEXT
;
2128 item
.pszText
= names
[1];
2129 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2132 item
.mask
= LVIF_TEXT
;
2135 item
.pszText
= names
[2];
2136 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2139 item
.mask
= LVIF_TEXT
;
2142 item
.pszText
= names
[0];
2143 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2146 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2147 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
2148 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2149 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2151 /* no sorting performed when switched to LVS_SORTASCENDING */
2152 item
.mask
= LVIF_TEXT
;
2154 item
.pszText
= buff
;
2155 item
.cchTextMax
= sizeof(buff
);
2156 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2158 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2161 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2163 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2166 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2168 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2170 /* adding new item doesn't resort list */
2171 item
.mask
= LVIF_TEXT
;
2174 item
.pszText
= names
[3];
2175 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2178 item
.mask
= LVIF_TEXT
;
2180 item
.pszText
= buff
;
2181 item
.cchTextMax
= sizeof(buff
);
2182 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2184 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2187 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2189 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2192 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2194 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2197 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2199 ok(lstrcmp(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
2201 /* corner case - item should be placed at first position */
2202 item
.mask
= LVIF_TEXT
;
2205 item
.pszText
= names
[4];
2206 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2210 item
.pszText
= buff
;
2211 item
.cchTextMax
= sizeof(buff
);
2212 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2214 ok(lstrcmp(buff
, names
[4]) == 0, "Expected '%s', got '%s'\n", names
[4], buff
);
2217 item
.pszText
= buff
;
2218 item
.cchTextMax
= sizeof(buff
);
2219 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2221 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2224 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2226 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2229 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2231 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2234 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2236 ok(lstrcmp(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
2238 DestroyWindow(hwnd
);
2241 static void test_ownerdata(void)
2244 LONG_PTR style
, ret
;
2248 /* it isn't possible to set LVS_OWNERDATA after creation */
2251 win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2255 hwnd
= create_listview_control(0);
2256 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2257 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2258 ok(!(style
& LVS_OWNERDATA
) && style
, "LVS_OWNERDATA isn't expected\n");
2260 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2262 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
2263 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2264 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2265 "try to switch to LVS_OWNERDATA seq", FALSE
);
2267 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2268 ok(!(style
& LVS_OWNERDATA
), "LVS_OWNERDATA isn't expected\n");
2269 DestroyWindow(hwnd
);
2272 /* try to set LVS_OWNERDATA after creation just having it */
2273 hwnd
= create_listview_control(LVS_OWNERDATA
);
2274 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2275 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2276 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2278 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2280 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
2281 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2282 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2283 "try to switch to LVS_OWNERDATA seq", FALSE
);
2284 DestroyWindow(hwnd
);
2286 /* try to remove LVS_OWNERDATA after creation just having it */
2289 win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2293 hwnd
= create_listview_control(LVS_OWNERDATA
);
2294 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2295 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2296 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2298 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2300 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_OWNERDATA
);
2301 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2302 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2303 "try to switch to LVS_OWNERDATA seq", FALSE
);
2304 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2305 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2306 DestroyWindow(hwnd
);
2309 /* try select an item */
2310 hwnd
= create_listview_control(LVS_OWNERDATA
);
2311 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2312 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2313 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2314 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2316 memset(&item
, 0, sizeof(item
));
2317 item
.stateMask
= LVIS_SELECTED
;
2318 item
.state
= LVIS_SELECTED
;
2319 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2321 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2323 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2325 DestroyWindow(hwnd
);
2327 /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2328 hwnd
= create_listview_control(LVS_OWNERDATA
);
2329 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2330 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2331 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2332 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2334 memset(&item
, 0, sizeof(item
));
2335 item
.mask
= LVIF_STATE
;
2337 item
.stateMask
= LVIS_SELECTED
;
2338 item
.state
= LVIS_SELECTED
;
2339 res
= SendMessageA(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2341 DestroyWindow(hwnd
);
2343 /* check notifications after focused/selected changed */
2344 hwnd
= create_listview_control(LVS_OWNERDATA
);
2345 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2346 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2347 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2349 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2351 memset(&item
, 0, sizeof(item
));
2352 item
.stateMask
= LVIS_SELECTED
;
2353 item
.state
= LVIS_SELECTED
;
2354 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2357 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownderdata_select_focus_parent_seq
,
2358 "ownerdata select notification", TRUE
);
2360 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2362 memset(&item
, 0, sizeof(item
));
2363 item
.stateMask
= LVIS_FOCUSED
;
2364 item
.state
= LVIS_FOCUSED
;
2365 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2368 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownderdata_select_focus_parent_seq
,
2369 "ownerdata focus notification", TRUE
);
2370 DestroyWindow(hwnd
);
2372 /* check notifications on LVM_GETITEM */
2373 /* zero callback mask */
2374 hwnd
= create_listview_control(LVS_OWNERDATA
);
2375 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2376 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2377 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2379 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2381 memset(&item
, 0, sizeof(item
));
2382 item
.stateMask
= LVIS_SELECTED
;
2383 item
.mask
= LVIF_STATE
;
2384 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2387 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
2388 "ownerdata getitem selected state 1", FALSE
);
2390 /* non zero callback mask but not we asking for */
2391 res
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_OVERLAYMASK
, 0);
2394 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2396 memset(&item
, 0, sizeof(item
));
2397 item
.stateMask
= LVIS_SELECTED
;
2398 item
.mask
= LVIF_STATE
;
2399 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2402 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
2403 "ownerdata getitem selected state 2", FALSE
);
2405 /* LVIS_OVERLAYMASK callback mask, asking for index */
2406 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2408 memset(&item
, 0, sizeof(item
));
2409 item
.stateMask
= LVIS_OVERLAYMASK
;
2410 item
.mask
= LVIF_STATE
;
2411 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2414 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
2415 "ownerdata getitem selected state 2", FALSE
);
2417 DestroyWindow(hwnd
);
2419 /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
2420 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_SORTASCENDING
);
2421 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2422 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2423 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
2424 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2425 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SORTASCENDING
);
2426 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2427 ok(!(style
& LVS_SORTASCENDING
), "Expected LVS_SORTASCENDING not set\n");
2428 DestroyWindow(hwnd
);
2429 /* apparently it's allowed to switch these style on after creation */
2430 hwnd
= create_listview_control(LVS_OWNERDATA
);
2431 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2432 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2433 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
2434 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
2435 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2436 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2437 DestroyWindow(hwnd
);
2439 hwnd
= create_listview_control(LVS_OWNERDATA
);
2440 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2441 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2442 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
2443 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTDESCENDING
);
2444 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2445 ok(style
& LVS_SORTDESCENDING
, "Expected LVS_SORTDESCENDING to be set\n");
2446 DestroyWindow(hwnd
);
2449 static void test_norecompute(void)
2451 static CHAR testA
[] = "test";
2457 /* self containing control */
2458 hwnd
= create_listview_control(0);
2459 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2460 memset(&item
, 0, sizeof(item
));
2461 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
2463 item
.stateMask
= LVIS_SELECTED
;
2464 item
.state
= LVIS_SELECTED
;
2465 item
.pszText
= testA
;
2466 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2468 /* retrieve with LVIF_NORECOMPUTE */
2469 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2471 item
.pszText
= buff
;
2472 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2473 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2475 ok(lstrcmp(buff
, testA
) == 0, "Expected (%s), got (%s)\n", testA
, buff
);
2477 item
.mask
= LVIF_TEXT
;
2479 item
.pszText
= LPSTR_TEXTCALLBACK
;
2480 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2483 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2485 item
.pszText
= buff
;
2486 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2488 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2489 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2491 ok(item
.pszText
== LPSTR_TEXTCALLBACK
, "Expected (%p), got (%p)\n",
2492 LPSTR_TEXTCALLBACK
, (VOID
*)item
.pszText
);
2493 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq", FALSE
);
2495 DestroyWindow(hwnd
);
2498 hwnd
= create_listview_control(LVS_OWNERDATA
);
2499 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2501 item
.mask
= LVIF_STATE
;
2502 item
.stateMask
= LVIS_SELECTED
;
2503 item
.state
= LVIS_SELECTED
;
2505 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2508 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2510 item
.pszText
= buff
;
2511 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2512 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2513 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2515 ok(item
.pszText
== LPSTR_TEXTCALLBACK
, "Expected (%p), got (%p)\n",
2516 LPSTR_TEXTCALLBACK
, (VOID
*)item
.pszText
);
2517 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE
);
2519 DestroyWindow(hwnd
);
2522 static void test_nosortheader(void)
2527 hwnd
= create_listview_control(0);
2528 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2530 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
2531 ok(IsWindow(header
), "header expected\n");
2533 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2534 ok(style
& HDS_BUTTONS
, "expected header to have HDS_BUTTONS\n");
2536 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2537 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
| LVS_NOSORTHEADER
);
2538 /* HDS_BUTTONS retained */
2539 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2540 ok(style
& HDS_BUTTONS
, "expected header to retain HDS_BUTTONS\n");
2542 DestroyWindow(hwnd
);
2544 /* create with LVS_NOSORTHEADER */
2545 hwnd
= create_listview_control(LVS_NOSORTHEADER
);
2546 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2548 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
2549 ok(IsWindow(header
), "header expected\n");
2551 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2552 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
2554 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2555 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
& ~LVS_NOSORTHEADER
);
2556 /* not changed here */
2557 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2558 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
2560 DestroyWindow(hwnd
);
2563 static void test_setredraw(void)
2569 hwnd
= create_listview_control(0);
2570 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2572 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2573 ListView seems to handle it internally without DefWinProc */
2575 /* default value first */
2576 ret
= SendMessage(hwnd
, WM_SETREDRAW
, TRUE
, 0);
2579 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2580 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
2581 ret
= SendMessage(hwnd
, WM_SETREDRAW
, FALSE
, 0);
2583 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2584 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
2586 DestroyWindow(hwnd
);
2589 static void test_hittest(void)
2595 static CHAR text
[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2598 HIMAGELIST himl
, himl2
;
2601 hwnd
= create_listview_control(0);
2602 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2604 /* LVS_REPORT with a single subitem (2 columns) */
2605 insert_column(hwnd
, 0);
2606 insert_column(hwnd
, 1);
2607 insert_item(hwnd
, 0);
2610 /* the only purpose of that line is to be as long as a half item rect */
2611 item
.pszText
= text
;
2612 r
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0, (LPARAM
)&item
);
2615 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
2617 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
2620 memset(&bounds
, 0, sizeof(bounds
));
2621 bounds
.left
= LVIR_BOUNDS
;
2622 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&bounds
);
2623 ok(bounds
.bottom
- bounds
.top
> 0, "Expected non zero item height\n");
2624 ok(bounds
.right
- bounds
.left
> 0, "Expected non zero item width\n");
2625 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pos
);
2628 /* LVS_EX_FULLROWSELECT not set, no icons attached */
2629 x
= pos
.x
+ 50; /* column half width */
2630 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2631 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, __LINE__
);
2632 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2633 x
= pos
.x
+ 150; /* outside column */
2634 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2635 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2636 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, TRUE
, TRUE
, TRUE
, __LINE__
);
2637 /* parent client area is 100x100 by default */
2638 MoveWindow(hwnd
, 0, 0, 300, 100, FALSE
);
2639 x
= pos
.x
+ 150; /* outside column */
2640 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2641 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, FALSE
, FALSE
, __LINE__
);
2642 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2643 /* the same with LVS_EX_FULLROWSELECT */
2644 SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
2645 x
= pos
.x
+ 150; /* outside column */
2646 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2647 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEM
, FALSE
, FALSE
, __LINE__
);
2648 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2649 MoveWindow(hwnd
, 0, 0, 100, 100, FALSE
);
2650 x
= pos
.x
+ 150; /* outside column */
2651 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2652 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2653 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, TRUE
, TRUE
, TRUE
, __LINE__
);
2654 /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
2655 himl
= ImageList_Create(16, 16, 0, 4, 4);
2656 ok(himl
!= NULL
, "failed to create imagelist\n");
2657 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
2658 ok(hbmp
!= NULL
, "failed to create bitmap\n");
2659 r
= ImageList_Add(himl
, hbmp
, 0);
2660 ok(r
== 0, "should be zero\n");
2661 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
2662 ok(hbmp
!= NULL
, "failed to create bitmap\n");
2663 r
= ImageList_Add(himl
, hbmp
, 0);
2664 ok(r
== 1, "should be one\n");
2666 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
2667 ok(r
== 0, "should return zero\n");
2669 item
.mask
= LVIF_IMAGE
;
2673 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2677 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2678 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, __LINE__
);
2679 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2681 /* state icons indices are 1 based, check with valid index */
2682 item
.mask
= LVIF_STATE
;
2683 item
.state
= INDEXTOSTATEIMAGEMASK(1);
2684 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2687 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2691 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2692 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, __LINE__
);
2693 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2695 himl2
= (HIMAGELIST
)SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)NULL
);
2696 ok(himl2
== himl
, "should return handle\n");
2698 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
2699 ok(r
== 0, "should return zero\n");
2702 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2703 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, __LINE__
);
2704 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2706 DestroyWindow(hwnd
);
2709 static void test_getviewrect(void)
2716 hwnd
= create_listview_control(0);
2717 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2720 r
= SendMessage(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
2723 insert_column(hwnd
, 0);
2724 insert_column(hwnd
, 1);
2726 memset(&item
, 0, sizeof(item
));
2729 SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
2731 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
2733 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(120, 0));
2736 rect
.left
= rect
.right
= rect
.top
= rect
.bottom
= -1;
2737 r
= SendMessage(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
2739 /* left is set to (2e31-1) - XP SP2 */
2740 expect(0, rect
.right
);
2741 expect(0, rect
.top
);
2742 expect(0, rect
.bottom
);
2744 /* switch to LVS_ICON */
2745 SetWindowLong(hwnd
, GWL_STYLE
, GetWindowLong(hwnd
, GWL_STYLE
) & ~LVS_REPORT
);
2747 rect
.left
= rect
.right
= rect
.top
= rect
.bottom
= -1;
2748 r
= SendMessage(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
2750 expect(0, rect
.left
);
2751 expect(0, rect
.top
);
2752 /* precise value differs for 2k, XP and Vista */
2753 ok(rect
.bottom
> 0, "Expected positive bottom value, got %d\n", rect
.bottom
);
2754 ok(rect
.right
> 0, "Expected positive right value, got %d\n", rect
.right
);
2756 DestroyWindow(hwnd
);
2759 static void test_getitemposition(void)
2766 hwnd
= create_listview_control(0);
2767 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2768 header
= subclass_header(hwnd
);
2770 /* LVS_REPORT, single item, no columns added */
2771 insert_item(hwnd
, 0);
2773 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2776 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
2778 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq1
, "get item position 1", FALSE
);
2780 /* LVS_REPORT, single item, single column */
2781 insert_column(hwnd
, 0);
2783 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2786 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
2788 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq2
, "get item position 2", TRUE
);
2790 memset(&rect
, 0, sizeof(rect
));
2791 SendMessage(header
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2794 /* offset by header height */
2795 expect(rect
.bottom
- rect
.top
, pt
.y
);
2797 DestroyWindow(hwnd
);
2800 static void test_columnscreation(void)
2805 hwnd
= create_listview_control(0);
2806 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2808 insert_item(hwnd
, 0);
2810 /* headers columns aren't created automatically */
2811 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
2812 ok(IsWindow(header
), "Expected header handle\n");
2813 r
= SendMessage(header
, HDM_GETITEMCOUNT
, 0, 0);
2816 DestroyWindow(hwnd
);
2819 static void test_getitemrect(void)
2831 hwnd
= create_listview_control(0);
2832 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2835 memset(&item
, 0, sizeof(item
));
2838 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
2841 rect
.left
= LVIR_BOUNDS
;
2842 rect
.right
= rect
.top
= rect
.bottom
= -1;
2843 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2846 /* zero width rectangle with no padding */
2847 expect(0, rect
.left
);
2848 expect(0, rect
.right
);
2850 insert_column(hwnd
, 0);
2851 insert_column(hwnd
, 1);
2853 col
.mask
= LVCF_WIDTH
;
2855 r
= SendMessage(hwnd
, LVM_SETCOLUMN
, 0, (LPARAM
)&col
);
2858 col
.mask
= LVCF_WIDTH
;
2860 r
= SendMessage(hwnd
, LVM_SETCOLUMN
, 1, (LPARAM
)&col
);
2863 rect
.left
= LVIR_BOUNDS
;
2864 rect
.right
= rect
.top
= rect
.bottom
= -1;
2865 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2868 /* still no left padding */
2869 expect(0, rect
.left
);
2870 expect(150, rect
.right
);
2872 rect
.left
= LVIR_SELECTBOUNDS
;
2873 rect
.right
= rect
.top
= rect
.bottom
= -1;
2874 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2877 expect(2, rect
.left
);
2879 rect
.left
= LVIR_LABEL
;
2880 rect
.right
= rect
.top
= rect
.bottom
= -1;
2881 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2883 /* padding, column width */
2884 expect(2, rect
.left
);
2885 expect(50, rect
.right
);
2887 /* no icons attached */
2888 rect
.left
= LVIR_ICON
;
2889 rect
.right
= rect
.top
= rect
.bottom
= -1;
2890 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2893 expect(2, rect
.left
);
2894 expect(2, rect
.right
);
2897 order
[0] = 1; order
[1] = 0;
2898 r
= SendMessage(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
2901 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
2903 /* 1 indexed column width + padding */
2904 todo_wine
expect(102, pt
.x
);
2905 /* rect is at zero too */
2906 rect
.left
= LVIR_BOUNDS
;
2907 rect
.right
= rect
.top
= rect
.bottom
= -1;
2908 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2910 expect(0, rect
.left
);
2911 /* just width sum */
2912 expect(150, rect
.right
);
2914 rect
.left
= LVIR_SELECTBOUNDS
;
2915 rect
.right
= rect
.top
= rect
.bottom
= -1;
2916 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2918 /* column width + padding */
2919 todo_wine
expect(102, rect
.left
);
2921 /* back to initial order */
2922 order
[0] = 0; order
[1] = 1;
2923 r
= SendMessage(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
2927 himl
= ImageList_Create(16, 16, 0, 2, 2);
2928 ok(himl
!= NULL
, "failed to create imagelist\n");
2929 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
2930 ok(hbm
!= NULL
, "failed to create bitmap\n");
2931 r
= ImageList_Add(himl
, hbm
, 0);
2932 ok(r
== 0, "should be zero\n");
2933 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
2934 ok(hbm
!= NULL
, "failed to create bitmap\n");
2935 r
= ImageList_Add(himl
, hbm
, 0);
2936 ok(r
== 1, "should be one\n");
2938 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
2939 ok(r
== 0, "should return zero\n");
2941 item
.mask
= LVIF_STATE
;
2942 item
.state
= INDEXTOSTATEIMAGEMASK(1);
2943 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2946 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2950 rect
.left
= LVIR_ICON
;
2951 rect
.right
= rect
.top
= rect
.bottom
= -1;
2952 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2954 /* padding + stateicon width */
2955 expect(18, rect
.left
);
2956 expect(18, rect
.right
);
2958 rect
.left
= LVIR_LABEL
;
2959 rect
.right
= rect
.top
= rect
.bottom
= -1;
2960 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2962 /* padding + stateicon width -> column width */
2963 expect(18, rect
.left
);
2964 expect(50, rect
.right
);
2966 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)NULL
);
2967 ok(r
!= 0, "should return current list handle\n");
2969 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
2970 ok(r
== 0, "should return zero\n");
2972 item
.mask
= LVIF_STATE
| LVIF_IMAGE
;
2975 item
.stateMask
= ~0;
2978 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2982 rect
.left
= LVIR_ICON
;
2983 rect
.right
= rect
.top
= rect
.bottom
= -1;
2984 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2986 /* padding, icon width */
2987 expect(2, rect
.left
);
2988 expect(18, rect
.right
);
2990 rect
.left
= LVIR_LABEL
;
2991 rect
.right
= rect
.top
= rect
.bottom
= -1;
2992 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2994 /* padding + icon width -> column width */
2995 expect(18, rect
.left
);
2996 expect(50, rect
.right
);
2999 rect
.left
= LVIR_SELECTBOUNDS
;
3000 rect
.right
= rect
.top
= rect
.bottom
= -1;
3001 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3003 /* padding, column width */
3004 expect(2, rect
.left
);
3005 todo_wine
expect(50, rect
.right
);
3007 /* try with indentation */
3008 item
.mask
= LVIF_INDENT
;
3012 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
3016 rect
.left
= LVIR_BOUNDS
;
3017 rect
.right
= rect
.top
= rect
.bottom
= -1;
3018 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3020 /* padding + 1 icon width, column width */
3021 expect(0, rect
.left
);
3022 expect(150, rect
.right
);
3025 rect
.left
= LVIR_SELECTBOUNDS
;
3026 rect
.right
= rect
.top
= rect
.bottom
= -1;
3027 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3029 /* padding + 1 icon width, column width */
3030 expect(2 + 16, rect
.left
);
3031 todo_wine
expect(50, rect
.right
);
3034 rect
.left
= LVIR_LABEL
;
3035 rect
.right
= rect
.top
= rect
.bottom
= -1;
3036 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3038 /* padding + 2 icon widths, column width */
3039 expect(2 + 16*2, rect
.left
);
3040 expect(50, rect
.right
);
3043 rect
.left
= LVIR_ICON
;
3044 rect
.right
= rect
.top
= rect
.bottom
= -1;
3045 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3047 /* padding + 1 icon width indentation, icon width */
3048 expect(2 + 16, rect
.left
);
3049 expect(34, rect
.right
);
3052 DestroyWindow(hwnd
);
3055 static void test_editbox(void)
3057 HWND hwnd
, hwndedit
, hwndedit2
;
3060 static CHAR testitemA
[] = "testitem";
3061 static CHAR testitem1A
[] = "testitem1";
3062 static CHAR buffer
[10];
3064 hwnd
= create_listview_control(LVS_EDITLABELS
);
3065 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3067 insert_column(hwnd
, 0);
3069 memset(&item
, 0, sizeof(item
));
3070 item
.mask
= LVIF_TEXT
;
3071 item
.pszText
= testitemA
;
3074 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3077 /* setting focus is necessary */
3079 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3080 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3082 /* modify initial string */
3083 r
= SendMessage(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
3085 /* return focus to listview */
3088 memset(&item
, 0, sizeof(item
));
3089 item
.mask
= LVIF_TEXT
;
3090 item
.pszText
= buffer
;
3091 item
.cchTextMax
= 10;
3094 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3097 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
3099 /* send LVM_EDITLABEL on already created edit */
3101 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3102 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3103 /* focus will be set to edit */
3104 ok(GetFocus() == hwndedit
, "Expected Edit window to be focused\n");
3105 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3106 ok(IsWindow(hwndedit2
), "Expected Edit window to be created\n");
3108 /* creating label disabled when control isn't focused */
3110 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3111 todo_wine
ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
3113 /* check EN_KILLFOCUS handling */
3114 memset(&item
, 0, sizeof(item
));
3115 item
.pszText
= testitemA
;
3118 r
= SendMessage(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
3122 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3123 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3124 /* modify edit and notify control that it lost focus */
3125 r
= SendMessage(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
3127 r
= SendMessage(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
3129 memset(&item
, 0, sizeof(item
));
3130 item
.pszText
= buffer
;
3131 item
.cchTextMax
= 10;
3134 r
= SendMessage(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
3135 expect(lstrlen(item
.pszText
), r
);
3136 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
3137 /* end edit without saving */
3138 r
= SendMessage(hwndedit
, WM_KEYDOWN
, VK_ESCAPE
, 0);
3140 memset(&item
, 0, sizeof(item
));
3141 item
.pszText
= buffer
;
3142 item
.cchTextMax
= 10;
3145 r
= SendMessage(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
3146 expect(lstrlen(item
.pszText
), r
);
3147 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
3149 /* LVM_EDITLABEL with -1 destroys current edit */
3150 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_GETEDITCONTROL
, 0, 0);
3151 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
3152 /* no edit present */
3153 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, -1, 0);
3154 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
3155 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3156 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3158 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
3159 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, -1, 0);
3160 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
3161 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
3162 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
3163 /* check another negative value */
3164 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3165 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3166 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
3167 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, -2, 0);
3168 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
3169 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
3170 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
3171 /* and value greater then max item index */
3172 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3173 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3174 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
3175 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
3176 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, r
, 0);
3177 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
3178 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
3179 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
3181 /* messaging tests */
3183 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3185 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3186 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3187 /* testing only sizing messages */
3188 ok_sequence(sequences
, EDITBOX_SEQ_INDEX
, editbox_create_pos
,
3189 "edit box create - sizing", TRUE
);
3191 DestroyWindow(hwnd
);
3194 static void test_notifyformat(void)
3199 hwnd
= create_listview_control(0);
3200 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3202 /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
3203 CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
3204 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3206 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
3208 r
= SendMessage(hwnd
, LVM_SETUNICODEFORMAT
, 1, 0);
3210 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3213 r
= SendMessage(hwnd
, LVM_SETUNICODEFORMAT
, 0, 0);
3215 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3220 win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
3221 DestroyWindow(hwnd
);
3225 DestroyWindow(hwnd
);
3227 /* test failure in parent WM_NOTIFYFORMAT */
3229 hwnd
= create_listview_control(0);
3230 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3231 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3232 ok(IsWindow(header
), "expected header to be created\n");
3233 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3235 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3237 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
3238 ok(r
!= 0, "Expected valid format\n");
3240 notifyFormat
= NFR_UNICODE
;
3241 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
3242 expect(NFR_UNICODE
, r
);
3243 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3245 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3248 notifyFormat
= NFR_ANSI
;
3249 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
3250 expect(NFR_ANSI
, r
);
3251 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3253 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3256 DestroyWindow(hwnd
);
3258 /* try different unicode window combination and defaults */
3259 if (!GetModuleHandleW(NULL
))
3261 win_skip("Additional notify format tests are incompatible with Win9x\n");
3265 hwndparentW
= create_parent_window(TRUE
);
3266 ok(IsWindow(hwndparentW
), "Unicode parent creation failed\n");
3267 if (!IsWindow(hwndparentW
)) return;
3270 hwnd
= create_listview_controlW(0, hwndparentW
);
3271 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3272 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3273 ok(IsWindow(header
), "expected header to be created\n");
3274 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3276 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3278 DestroyWindow(hwnd
);
3279 /* recieving error code defaulting to ansi */
3281 hwnd
= create_listview_controlW(0, hwndparentW
);
3282 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3283 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3284 ok(IsWindow(header
), "expected header to be created\n");
3285 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3287 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3289 DestroyWindow(hwnd
);
3290 /* recieving ansi code from unicode window, use it */
3291 notifyFormat
= NFR_ANSI
;
3292 hwnd
= create_listview_controlW(0, hwndparentW
);
3293 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3294 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3295 ok(IsWindow(header
), "expected header to be created\n");
3296 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3298 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3300 DestroyWindow(hwnd
);
3301 /* unicode listview with ansi parent window */
3303 hwnd
= create_listview_controlW(0, hwndparent
);
3304 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3305 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3306 ok(IsWindow(header
), "expected header to be created\n");
3307 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3309 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3311 DestroyWindow(hwnd
);
3312 /* unicode listview with ansi parent window, return error code */
3314 hwnd
= create_listview_controlW(0, hwndparent
);
3315 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3316 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3317 ok(IsWindow(header
), "expected header to be created\n");
3318 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3320 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3322 DestroyWindow(hwnd
);
3324 DestroyWindow(hwndparentW
);
3327 static void test_indentation(void)
3333 hwnd
= create_listview_control(0);
3334 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3336 memset(&item
, 0, sizeof(item
));
3337 item
.mask
= LVIF_INDENT
;
3339 item
.iIndent
= I_INDENTCALLBACK
;
3340 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3343 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3346 item
.mask
= LVIF_INDENT
;
3347 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
3350 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
3351 "get indent dispinfo", FALSE
);
3353 DestroyWindow(hwnd
);
3356 INT CALLBACK
DummyCompareEx(LPARAM first
, LPARAM second
, LPARAM param
)
3361 static BOOL
is_below_comctl_5(void)
3366 hwnd
= create_listview_control(0);
3367 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3368 insert_item(hwnd
, 0);
3370 ret
= SendMessage(hwnd
, LVM_SORTITEMSEX
, 0, (LPARAM
)&DummyCompareEx
);
3372 DestroyWindow(hwnd
);
3377 START_TEST(listview
)
3380 BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
3382 hComctl32
= GetModuleHandleA("comctl32.dll");
3383 pInitCommonControlsEx
= (void*)GetProcAddress(hComctl32
, "InitCommonControlsEx");
3384 if (pInitCommonControlsEx
)
3386 INITCOMMONCONTROLSEX iccex
;
3387 iccex
.dwSize
= sizeof(iccex
);
3388 iccex
.dwICC
= ICC_LISTVIEW_CLASSES
;
3389 pInitCommonControlsEx(&iccex
);
3392 InitCommonControls();
3394 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
3396 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3397 hwndparent
= create_parent_window(FALSE
);
3398 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_parent_wnd_seq
, "create parent window", TRUE
);
3399 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3401 g_is_below_5
= is_below_comctl_5();
3409 test_icon_spacing();
3412 test_item_position();
3417 test_subitem_rect();
3421 test_nosortheader();
3425 test_getitemposition();
3426 test_columnscreation();
3428 test_notifyformat();
3431 DestroyWindow(hwndparent
);