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)
44 #elif defined __x86_64__
50 static const CHAR manifest_name
[] = "cc6.manifest";
52 static const CHAR manifest
[] =
53 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
54 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"
55 " <assemblyIdentity\n"
57 " name=\"Wine.ComCtl32.Tests\"\n"
58 " version=\"1.0.0.0\"\n"
59 " processorArchitecture=\"" ARCH
"\"\n"
61 "<description>Wine comctl32 test suite</description>\n"
63 " <dependentAssembly>\n"
64 " <assemblyIdentity\n"
66 " name=\"microsoft.windows.common-controls\"\n"
67 " version=\"6.0.0.0\"\n"
68 " processorArchitecture=\"" ARCH
"\"\n"
69 " publicKeyToken=\"6595b64144ccf1df\"\n"
72 "</dependentAssembly>\n"
76 static const WCHAR testparentclassW
[] =
77 {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
79 HWND hwndparent
, hwndparentW
;
80 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
82 /* format reported to control:
83 -1 falls to defproc, anything else returned */
85 /* indicates we're running < 5.80 version */
88 static HWND
subclass_editbox(HWND hwndListview
);
90 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
92 static const struct message create_ownerdrawfixed_parent_seq
[] = {
93 { WM_NOTIFYFORMAT
, sent
},
94 { WM_QUERYUISTATE
, sent
|optional
}, /* Win2K and higher */
95 { WM_MEASUREITEM
, sent
},
96 { WM_PARENTNOTIFY
, sent
},
100 static const struct message redraw_listview_seq
[] = {
101 { WM_PAINT
, sent
|id
, 0, 0, LISTVIEW_ID
},
102 { WM_PAINT
, sent
|id
, 0, 0, HEADER_ID
},
103 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
104 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
105 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
106 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
107 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
111 static const struct message listview_icon_spacing_seq
[] = {
112 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(20, 30) },
113 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(25, 35) },
114 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(-1, -1) },
118 static const struct message listview_color_seq
[] = {
119 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
120 { LVM_GETBKCOLOR
, sent
},
121 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
122 { LVM_GETTEXTCOLOR
, sent
},
123 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
124 { LVM_GETTEXTBKCOLOR
, sent
},
126 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
127 { LVM_GETBKCOLOR
, sent
},
128 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
129 { LVM_GETTEXTCOLOR
, sent
},
130 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
131 { LVM_GETTEXTBKCOLOR
, sent
},
133 { LVM_SETBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
134 { LVM_GETBKCOLOR
, sent
},
135 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, CLR_NONE
},
136 { LVM_GETTEXTCOLOR
, sent
},
137 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
138 { LVM_GETTEXTBKCOLOR
, sent
},
140 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
141 { LVM_GETBKCOLOR
, sent
},
142 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
143 { LVM_GETTEXTCOLOR
, sent
},
144 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
145 { LVM_GETTEXTBKCOLOR
, sent
},
149 static const struct message listview_item_count_seq
[] = {
150 { LVM_GETITEMCOUNT
, sent
},
151 { LVM_INSERTITEM
, sent
},
152 { LVM_INSERTITEM
, sent
},
153 { LVM_INSERTITEM
, sent
},
154 { LVM_GETITEMCOUNT
, sent
},
155 { LVM_DELETEITEM
, sent
|wparam
, 2 },
156 { LVM_GETITEMCOUNT
, sent
},
157 { LVM_DELETEALLITEMS
, sent
},
158 { LVM_GETITEMCOUNT
, sent
},
159 { LVM_INSERTITEM
, sent
},
160 { LVM_INSERTITEM
, sent
},
161 { LVM_GETITEMCOUNT
, sent
},
162 { LVM_INSERTITEM
, sent
},
163 { LVM_GETITEMCOUNT
, sent
},
167 static const struct message listview_itempos_seq
[] = {
168 { LVM_INSERTITEM
, sent
},
169 { LVM_INSERTITEM
, sent
},
170 { LVM_INSERTITEM
, sent
},
171 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 1, MAKELPARAM(10,5) },
172 { LVM_GETITEMPOSITION
, sent
|wparam
, 1 },
173 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 2, MAKELPARAM(0,0) },
174 { LVM_GETITEMPOSITION
, sent
|wparam
, 2 },
175 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 0, MAKELPARAM(20,20) },
176 { LVM_GETITEMPOSITION
, sent
|wparam
, 0 },
180 static const struct message listview_ownerdata_switchto_seq
[] = {
181 { WM_STYLECHANGING
, sent
},
182 { WM_STYLECHANGED
, sent
},
186 static const struct message listview_getorderarray_seq
[] = {
187 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
188 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
192 static const struct message empty_seq
[] = {
196 static const struct message forward_erasebkgnd_parent_seq
[] = {
197 { WM_ERASEBKGND
, sent
},
201 static const struct message ownderdata_select_focus_parent_seq
[] = {
202 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
203 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
207 static const struct message textcallback_set_again_parent_seq
[] = {
208 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
209 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
213 static const struct message single_getdispinfo_parent_seq
[] = {
214 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
218 static const struct message getitemposition_seq1
[] = {
219 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
223 static const struct message getitemposition_seq2
[] = {
224 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
225 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
229 static const struct message editbox_create_pos
[] = {
230 /* sequence sent after LVN_BEGINLABELEDIT */
231 { WM_WINDOWPOSCHANGING
, sent
},
232 { WM_NCCALCSIZE
, sent
},
233 { WM_WINDOWPOSCHANGED
, sent
},
234 { WM_MOVE
, sent
|defwinproc
},
235 { WM_SIZE
, sent
|defwinproc
},
236 /* the rest is todo */
237 { WM_WINDOWPOSCHANGING
, sent
},
238 { WM_WINDOWPOSCHANGED
, sent
},
247 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
249 static LONG defwndproc_counter
= 0;
253 msg
.message
= message
;
254 msg
.flags
= sent
|wparam
|lparam
;
255 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
258 if (message
== WM_NOTIFY
&& lParam
) msg
.id
= ((NMHDR
*)lParam
)->code
;
260 /* log system messages, except for painting */
261 if (message
< WM_USER
&&
262 message
!= WM_PAINT
&&
263 message
!= WM_ERASEBKGND
&&
264 message
!= WM_NCPAINT
&&
265 message
!= WM_NCHITTEST
&&
266 message
!= WM_GETTEXT
&&
267 message
!= WM_GETICON
&&
268 message
!= WM_DEVICECHANGE
)
270 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
272 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
274 add_message(sequences
, PARENT_FULL_SEQ_INDEX
, &msg
);
280 switch (((NMHDR
*)lParam
)->code
)
282 case LVN_BEGINLABELEDIT
:
283 /* subclass edit box */
285 subclass_editbox(((NMHDR
*)lParam
)->hwndFrom
);
289 case LVN_ENDLABELEDIT
:
290 /* always accept new item text */
295 case WM_NOTIFYFORMAT
:
297 /* force to return format */
298 if (lParam
== NF_QUERY
&& notifyFormat
!= -1) return notifyFormat
;
303 defwndproc_counter
++;
304 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
305 defwndproc_counter
--;
310 static BOOL
register_parent_wnd_class(BOOL Unicode
)
318 clsW
.lpfnWndProc
= parent_wnd_proc
;
321 clsW
.hInstance
= GetModuleHandleW(NULL
);
323 clsW
.hCursor
= LoadCursorA(0, IDC_ARROW
);
324 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
325 clsW
.lpszMenuName
= NULL
;
326 clsW
.lpszClassName
= testparentclassW
;
331 clsA
.lpfnWndProc
= parent_wnd_proc
;
334 clsA
.hInstance
= GetModuleHandleA(NULL
);
336 clsA
.hCursor
= LoadCursorA(0, IDC_ARROW
);
337 clsA
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
338 clsA
.lpszMenuName
= NULL
;
339 clsA
.lpszClassName
= "Listview test parent class";
342 return Unicode
? RegisterClassW(&clsW
) : RegisterClassA(&clsA
);
345 static HWND
create_parent_window(BOOL Unicode
)
347 static const WCHAR nameW
[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W'};
349 if (!register_parent_wnd_class(Unicode
))
356 return CreateWindowExW(0, testparentclassW
, nameW
,
357 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
358 WS_MAXIMIZEBOX
| WS_VISIBLE
,
360 GetDesktopWindow(), NULL
, GetModuleHandleW(NULL
), NULL
);
362 return CreateWindowExA(0, "Listview test parent class",
363 "Listview test parent window",
364 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
365 WS_MAXIMIZEBOX
| WS_VISIBLE
,
367 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
370 static LRESULT WINAPI
listview_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
372 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
373 static LONG defwndproc_counter
= 0;
377 trace("listview: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
379 /* some debug output for style changing */
380 if ((message
== WM_STYLECHANGING
||
381 message
== WM_STYLECHANGED
) && lParam
)
383 STYLESTRUCT
*style
= (STYLESTRUCT
*)lParam
;
384 trace("\told style: 0x%08x, new style: 0x%08x\n", style
->styleOld
, style
->styleNew
);
387 msg
.message
= message
;
388 msg
.flags
= sent
|wparam
|lparam
;
389 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
392 msg
.id
= LISTVIEW_ID
;
393 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
395 defwndproc_counter
++;
396 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
397 defwndproc_counter
--;
401 static HWND
create_listview_control(DWORD style
)
403 struct subclass_info
*info
;
407 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
411 GetClientRect(hwndparent
, &rect
);
412 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
413 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
| style
,
414 0, 0, rect
.right
, rect
.bottom
,
415 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
416 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
420 HeapFree(GetProcessHeap(), 0, info
);
424 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
425 (LONG_PTR
)listview_subclass_proc
);
426 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
431 /* unicode listview window with specified parent */
432 static HWND
create_listview_controlW(DWORD style
, HWND parent
)
434 struct subclass_info
*info
;
437 static const WCHAR nameW
[] = {'f','o','o',0};
439 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
443 GetClientRect(parent
, &rect
);
444 hwnd
= CreateWindowExW(0, WC_LISTVIEWW
, nameW
,
445 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
| style
,
446 0, 0, rect
.right
, rect
.bottom
,
447 parent
, NULL
, GetModuleHandleW(NULL
), NULL
);
448 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
452 HeapFree(GetProcessHeap(), 0, info
);
456 info
->oldproc
= (WNDPROC
)SetWindowLongPtrW(hwnd
, GWLP_WNDPROC
,
457 (LONG_PTR
)listview_subclass_proc
);
458 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
463 static HWND
create_custom_listview_control(DWORD style
)
465 struct subclass_info
*info
;
469 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
473 GetClientRect(hwndparent
, &rect
);
474 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
475 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
476 0, 0, rect
.right
, rect
.bottom
,
477 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
478 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
482 HeapFree(GetProcessHeap(), 0, info
);
486 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
487 (LONG_PTR
)listview_subclass_proc
);
488 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
493 static LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
495 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
496 static LONG defwndproc_counter
= 0;
500 trace("header: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
502 msg
.message
= message
;
503 msg
.flags
= sent
|wparam
|lparam
;
504 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
508 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
510 defwndproc_counter
++;
511 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
512 defwndproc_counter
--;
516 static HWND
subclass_header(HWND hwndListview
)
518 struct subclass_info
*info
;
521 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
525 hwnd
= ListView_GetHeader(hwndListview
);
526 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
527 (LONG_PTR
)header_subclass_proc
);
528 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
533 static LRESULT WINAPI
editbox_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
535 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
536 static LONG defwndproc_counter
= 0;
540 msg
.message
= message
;
541 msg
.flags
= sent
|wparam
|lparam
;
542 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
546 /* all we need is sizing */
547 if (message
== WM_WINDOWPOSCHANGING
||
548 message
== WM_NCCALCSIZE
||
549 message
== WM_WINDOWPOSCHANGED
||
550 message
== WM_MOVE
||
553 add_message(sequences
, EDITBOX_SEQ_INDEX
, &msg
);
556 defwndproc_counter
++;
557 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
558 defwndproc_counter
--;
562 static HWND
subclass_editbox(HWND hwndListview
)
564 struct subclass_info
*info
;
567 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
571 hwnd
= (HWND
)SendMessage(hwndListview
, LVM_GETEDITCONTROL
, 0, 0);
572 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
573 (LONG_PTR
)editbox_subclass_proc
);
574 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
579 /* Performs a single LVM_HITTEST test */
580 static void test_lvm_hittest(HWND hwnd
, INT x
, INT y
, INT item
, UINT flags
,
581 BOOL todo_item
, BOOL todo_flags
, int line
)
590 trace("hittesting pt=(%d,%d)\n", lpht
.pt
.x
, lpht
.pt
.y
);
591 ret
= SendMessage(hwnd
, LVM_HITTEST
, 0, (LPARAM
)&lpht
);
597 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
598 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
599 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
604 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
605 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
606 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
612 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
615 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
618 /* Performs a single LVM_SUBITEMHITTEST test */
619 static void test_lvm_subitemhittest(HWND hwnd
, INT x
, INT y
, INT item
, INT subitem
, UINT flags
,
620 BOOL todo_item
, BOOL todo_subitem
, BOOL todo_flags
, int line
)
628 trace("subhittesting pt=(%d,%d)\n", lpht
.pt
.x
, lpht
.pt
.y
);
629 ret
= SendMessage(hwnd
, LVM_SUBITEMHITTEST
, 0, (LPARAM
)&lpht
);
635 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
636 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
641 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
642 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
648 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
651 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
656 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
659 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
662 static void test_images(void)
670 static CHAR hello
[] = "hello";
672 himl
= ImageList_Create(40, 40, 0, 4, 4);
673 ok(himl
!= NULL
, "failed to create imagelist\n");
675 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
676 ok(hbmp
!= NULL
, "failed to create bitmap\n");
678 r
= ImageList_Add(himl
, hbmp
, 0);
679 ok(r
== 0, "should be zero\n");
681 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED
,
682 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
683 ok(hwnd
!= NULL
, "failed to create listview window\n");
685 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0,
686 LVS_EX_UNDERLINEHOT
| LVS_EX_FLATSB
| LVS_EX_ONECLICKACTIVATE
);
688 ok(r
== 0, "should return zero\n");
690 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
691 ok(r
== 0, "should return zero\n");
693 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELONG(100,50));
694 /* returns dimensions */
696 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
697 ok(r
== 0, "should be zero items\n");
699 item
.mask
= LVIF_IMAGE
| LVIF_TEXT
;
704 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
705 ok(r
== -1, "should fail\n");
708 item
.pszText
= hello
;
709 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
710 ok(r
== 0, "should not fail\n");
712 memset(&r1
, 0, sizeof r1
);
714 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r1
);
716 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
717 ok(r
== TRUE
, "should not fail\n");
720 item
.pszText
= hello
;
721 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
722 ok(r
== 0, "should not fail\n");
724 memset(&r2
, 0, sizeof r2
);
726 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r2
);
728 ok(!memcmp(&r1
, &r2
, sizeof r1
), "rectangle should be the same\n");
733 static void test_checkboxes(void)
738 static CHAR text
[] = "Text",
742 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
743 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
744 ok(hwnd
!= NULL
, "failed to create listview window\n");
746 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
747 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
748 item
.stateMask
= 0xffff;
753 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
754 ok(r
== 0, "ret %d\n", r
);
757 item
.mask
= LVIF_STATE
;
758 item
.stateMask
= 0xffff;
759 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
760 ok(item
.state
== 0xfccc, "state %x\n", item
.state
);
762 /* Don't set LVIF_STATE */
763 item
.mask
= LVIF_TEXT
;
764 item
.stateMask
= 0xffff;
769 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
770 ok(r
== 1, "ret %d\n", r
);
773 item
.mask
= LVIF_STATE
;
774 item
.stateMask
= 0xffff;
775 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
776 ok(item
.state
== 0, "state %x\n", item
.state
);
778 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
779 ok(r
== 0, "should return zero\n");
781 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
783 item
.mask
= LVIF_STATE
;
784 item
.stateMask
= 0xffff;
785 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
786 ok(item
.state
== 0x1ccc, "state %x\n", item
.state
);
788 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
790 item
.mask
= LVIF_TEXT
;
792 item
.pszText
= text2
;
793 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
794 ok(r
== 2, "ret %d\n", r
);
797 item
.mask
= LVIF_STATE
;
798 item
.stateMask
= 0xffff;
799 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
800 ok(item
.state
== 0x1000, "state %x\n", item
.state
);
802 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
804 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
805 item
.stateMask
= 0xffff;
807 item
.pszText
= text3
;
808 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
809 ok(r
== 3, "ret %d\n", r
);
812 item
.mask
= LVIF_STATE
;
813 item
.stateMask
= 0xffff;
814 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
815 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
817 /* Set an item's state to checked */
819 item
.mask
= LVIF_STATE
;
820 item
.stateMask
= 0xf000;
822 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
825 item
.mask
= LVIF_STATE
;
826 item
.stateMask
= 0xffff;
827 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
828 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
830 /* Check that only the bits we asked for are returned,
831 * and that all the others are set to zero
834 item
.mask
= LVIF_STATE
;
835 item
.stateMask
= 0xf000;
837 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
838 ok(item
.state
== 0x2000, "state %x\n", item
.state
);
840 /* Set the style again and check that doesn't change an item's state */
841 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
842 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
845 item
.mask
= LVIF_STATE
;
846 item
.stateMask
= 0xffff;
847 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
848 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
850 /* Unsetting the checkbox extended style doesn't change an item's state */
851 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
852 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
855 item
.mask
= LVIF_STATE
;
856 item
.stateMask
= 0xffff;
857 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
858 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
860 /* Now setting the style again will change an item's state */
861 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
862 ok(r
== 0, "ret %x\n", r
);
865 item
.mask
= LVIF_STATE
;
866 item
.stateMask
= 0xffff;
867 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
868 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
870 /* Toggle checkbox tests (bug 9934) */
871 memset (&item
, 0xcc, sizeof(item
));
872 item
.mask
= LVIF_STATE
;
875 item
.state
= LVIS_FOCUSED
;
876 item
.stateMask
= LVIS_FOCUSED
;
877 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
881 item
.mask
= LVIF_STATE
;
882 item
.stateMask
= 0xffff;
883 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
884 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
886 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
888 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
892 item
.mask
= LVIF_STATE
;
893 item
.stateMask
= 0xffff;
894 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
895 ok(item
.state
== 0x2aab, "state %x\n", item
.state
);
897 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
899 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
903 item
.mask
= LVIF_STATE
;
904 item
.stateMask
= 0xffff;
905 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
906 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
911 static void insert_column(HWND hwnd
, int idx
)
916 memset(&column
, 0xcc, sizeof(column
));
917 column
.mask
= LVCF_SUBITEM
;
918 column
.iSubItem
= idx
;
920 rc
= ListView_InsertColumn(hwnd
, idx
, &column
);
924 static void insert_item(HWND hwnd
, int idx
)
926 static CHAR text
[] = "foo";
931 memset(&item
, 0xcc, sizeof (item
));
932 item
.mask
= LVIF_TEXT
;
937 rc
= ListView_InsertItem(hwnd
, &item
);
941 static void test_items(void)
943 const LPARAM lparamTest
= 0x42;
947 static CHAR text
[] = "Text";
949 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
950 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
951 ok(hwnd
!= NULL
, "failed to create listview window\n");
954 * Test setting/getting item params
957 /* Set up two columns */
958 insert_column(hwnd
, 0);
959 insert_column(hwnd
, 1);
961 /* LVIS_SELECTED with zero stateMask */
963 memset (&item
, 0, sizeof (item
));
964 item
.mask
= LVIF_STATE
;
965 item
.state
= LVIS_SELECTED
;
969 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
970 ok(r
== 0, "ret %d\n", r
);
972 memset (&item
, 0xcc, sizeof (item
));
973 item
.mask
= LVIF_STATE
;
974 item
.stateMask
= LVIS_SELECTED
;
978 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
979 ok(r
!= 0, "ret %d\n", r
);
980 ok(item
.state
& LVIS_SELECTED
, "Expected LVIS_SELECTED\n");
981 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
983 /* LVIS_SELECTED with zero stateMask */
985 memset (&item
, 0, sizeof (item
));
986 item
.mask
= LVIF_STATE
;
987 item
.state
= LVIS_FOCUSED
;
991 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
992 ok(r
== 0, "ret %d\n", r
);
994 memset (&item
, 0xcc, sizeof (item
));
995 item
.mask
= LVIF_STATE
;
996 item
.stateMask
= LVIS_FOCUSED
;
1000 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1001 ok(r
!= 0, "ret %d\n", r
);
1002 ok(item
.state
& LVIS_FOCUSED
, "Expected LVIS_FOCUSED\n");
1003 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
1005 /* LVIS_CUT with LVIS_FOCUSED stateMask */
1007 memset (&item
, 0, sizeof (item
));
1008 item
.mask
= LVIF_STATE
;
1009 item
.state
= LVIS_CUT
;
1010 item
.stateMask
= LVIS_FOCUSED
;
1013 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1014 ok(r
== 0, "ret %d\n", r
);
1016 memset (&item
, 0xcc, sizeof (item
));
1017 item
.mask
= LVIF_STATE
;
1018 item
.stateMask
= LVIS_CUT
;
1022 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1023 ok(r
!= 0, "ret %d\n", r
);
1024 ok(item
.state
& LVIS_CUT
, "Expected LVIS_CUT\n");
1025 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
1027 /* Insert an item with just a param */
1028 memset (&item
, 0xcc, sizeof (item
));
1029 item
.mask
= LVIF_PARAM
;
1032 item
.lParam
= lparamTest
;
1033 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1034 ok(r
== 0, "ret %d\n", r
);
1036 /* Test getting of the param */
1037 memset (&item
, 0xcc, sizeof (item
));
1038 item
.mask
= LVIF_PARAM
;
1041 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1042 ok(r
!= 0, "ret %d\n", r
);
1043 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1045 /* Set up a subitem */
1046 memset (&item
, 0xcc, sizeof (item
));
1047 item
.mask
= LVIF_TEXT
;
1050 item
.pszText
= text
;
1051 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1052 ok(r
!= 0, "ret %d\n", r
);
1054 /* Query param from subitem: returns main item param */
1055 memset (&item
, 0xcc, sizeof (item
));
1056 item
.mask
= LVIF_PARAM
;
1059 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1060 ok(r
!= 0, "ret %d\n", r
);
1061 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1063 /* Set up param on first subitem: no effect */
1064 memset (&item
, 0xcc, sizeof (item
));
1065 item
.mask
= LVIF_PARAM
;
1068 item
.lParam
= lparamTest
+1;
1069 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1070 ok(r
== 0, "ret %d\n", r
);
1072 /* Query param from subitem again: should still return main item param */
1073 memset (&item
, 0xcc, sizeof (item
));
1074 item
.mask
= LVIF_PARAM
;
1077 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1078 ok(r
!= 0, "ret %d\n", r
);
1079 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1081 /**** Some tests of state highlighting ****/
1082 memset (&item
, 0xcc, sizeof (item
));
1083 item
.mask
= LVIF_STATE
;
1086 item
.state
= LVIS_SELECTED
;
1087 item
.stateMask
= LVIS_SELECTED
| LVIS_DROPHILITED
;
1088 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
1089 ok(r
!= 0, "ret %d\n", r
);
1091 item
.state
= LVIS_DROPHILITED
;
1092 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
1093 ok(r
!= 0, "ret %d\n", r
);
1095 memset (&item
, 0xcc, sizeof (item
));
1096 item
.mask
= LVIF_STATE
;
1099 item
.stateMask
= -1;
1100 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1101 ok(r
!= 0, "ret %d\n", r
);
1102 ok(item
.state
== LVIS_SELECTED
, "got state %x, expected %x\n", item
.state
, LVIS_SELECTED
);
1104 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1105 ok(r
!= 0, "ret %d\n", r
);
1106 todo_wine
ok(item
.state
== LVIS_DROPHILITED
, "got state %x, expected %x\n", item
.state
, LVIS_DROPHILITED
);
1108 /* some notnull but meaningless masks */
1109 memset (&item
, 0, sizeof(item
));
1110 item
.mask
= LVIF_NORECOMPUTE
;
1113 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1114 ok(r
!= 0, "ret %d\n", r
);
1115 memset (&item
, 0, sizeof(item
));
1116 item
.mask
= LVIF_DI_SETITEM
;
1119 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1120 ok(r
!= 0, "ret %d\n", r
);
1122 /* set text to callback value already having it */
1123 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1125 memset (&item
, 0, sizeof (item
));
1126 item
.mask
= LVIF_TEXT
;
1127 item
.pszText
= LPSTR_TEXTCALLBACK
;
1129 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1130 ok(r
== 0, "ret %d\n", r
);
1131 memset (&item
, 0, sizeof (item
));
1133 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1135 item
.pszText
= LPSTR_TEXTCALLBACK
;
1136 r
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0 , (LPARAM
) &item
);
1139 ok_sequence(sequences
, PARENT_SEQ_INDEX
, textcallback_set_again_parent_seq
,
1140 "check callback text comparison rule", FALSE
);
1142 DestroyWindow(hwnd
);
1145 static void test_columns(void)
1147 HWND hwnd
, hwndheader
;
1152 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
1153 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1154 ok(hwnd
!= NULL
, "failed to create listview window\n");
1156 /* Add a column with no mask */
1157 memset(&column
, 0xcc, sizeof(column
));
1159 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
1160 ok(rc
==0, "Inserting column with no mask failed with %d\n", rc
);
1162 /* Check its width */
1163 rc
= ListView_GetColumnWidth(hwnd
, 0);
1165 broken(rc
==0), /* win9x */
1166 "Inserting column with no mask failed to set width to 10 with %d\n", rc
);
1168 DestroyWindow(hwnd
);
1170 /* LVM_GETCOLUMNORDERARRAY */
1171 hwnd
= create_listview_control(0);
1172 hwndheader
= subclass_header(hwnd
);
1174 memset(&column
, 0, sizeof(column
));
1175 column
.mask
= LVCF_WIDTH
;
1177 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
1178 ok(rc
== 0, "Inserting column failed with %d\n", rc
);
1181 rc
= ListView_InsertColumn(hwnd
, 1, &column
);
1182 ok(rc
== 1, "Inserting column failed with %d\n", rc
);
1184 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1186 rc
= SendMessage(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1187 ok(rc
!= 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
1188 ok(order
[0] == 0, "Expected order 0, got %d\n", order
[0]);
1189 ok(order
[1] == 1, "Expected order 1, got %d\n", order
[1]);
1191 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_getorderarray_seq
, "get order array", FALSE
);
1193 DestroyWindow(hwnd
);
1195 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1196 static WNDPROC listviewWndProc
;
1197 static HIMAGELIST test_create_imagelist
;
1199 static LRESULT CALLBACK
create_test_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1203 if (uMsg
== WM_CREATE
)
1205 LPCREATESTRUCT lpcs
= (LPCREATESTRUCT
)lParam
;
1206 lpcs
->style
|= LVS_REPORT
;
1208 ret
= CallWindowProc(listviewWndProc
, hwnd
, uMsg
, wParam
, lParam
);
1209 if (uMsg
== WM_CREATE
) SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)test_create_imagelist
);
1213 static void test_create(void)
1222 cls
.cbSize
= sizeof(WNDCLASSEX
);
1223 ok(GetClassInfoEx(GetModuleHandle(NULL
), "SysListView32", &cls
), "GetClassInfoEx failed\n");
1224 listviewWndProc
= cls
.lpfnWndProc
;
1225 cls
.lpfnWndProc
= create_test_wndproc
;
1226 cls
.lpszClassName
= "MyListView32";
1227 ok(RegisterClassEx(&cls
), "RegisterClassEx failed\n");
1229 test_create_imagelist
= ImageList_Create(16, 16, 0, 5, 10);
1230 hList
= CreateWindow("MyListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
1231 ok((HIMAGELIST
)SendMessage(hList
, LVM_GETIMAGELIST
, 0, 0) == test_create_imagelist
, "Image list not obtained\n");
1232 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1233 ok(IsWindow(hHeader
) && IsWindowVisible(hHeader
), "Listview not in report mode\n");
1234 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1235 DestroyWindow(hList
);
1237 /* header isn't created on LVS_ICON and LVS_LIST styles */
1238 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1239 GetModuleHandle(NULL
), 0);
1240 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1241 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1242 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1244 memset(&col
, 0, sizeof(LVCOLUMNA
));
1245 col
.mask
= LVCF_WIDTH
;
1247 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1248 ok(r
== 0, "Expected 0 column's inserted\n");
1249 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1250 ok(IsWindow(hHeader
), "Header should be created\n");
1251 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1252 DestroyWindow(hList
);
1254 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1255 GetModuleHandle(NULL
), 0);
1256 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1257 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1258 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1260 memset(&col
, 0, sizeof(LVCOLUMNA
));
1261 col
.mask
= LVCF_WIDTH
;
1263 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1264 ok(r
== 0, "Expected 0 column's inserted\n");
1265 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1266 ok(IsWindow(hHeader
), "Header should be created\n");
1267 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1268 DestroyWindow(hList
);
1270 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1271 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1272 GetModuleHandle(NULL
), 0);
1273 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLongPtr(hList
, GWL_STYLE
) | LVS_REPORT
);
1274 ok(ret
& WS_VISIBLE
, "Style wrong, should have WS_VISIBLE\n");
1275 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1276 ok(IsWindow(hHeader
), "Header should be created\n");
1277 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLong(hList
, GWL_STYLE
) & ~LVS_REPORT
);
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 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1285 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1286 GetModuleHandle(NULL
), 0);
1287 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
1288 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_LIST
) | LVS_REPORT
);
1289 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_LIST
)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1290 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1291 ok(IsWindow(hHeader
), "Header should be created\n");
1292 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1293 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
1294 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_REPORT
) | LVS_LIST
);
1295 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\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 */
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");
1308 memset(&col
, 0, sizeof(LVCOLUMNA
));
1309 col
.mask
= LVCF_WIDTH
;
1311 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1312 ok(r
== 0, "Expected 0 column's inserted\n");
1313 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1314 ok(IsWindow(hHeader
), "Header should be created\n");
1315 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1316 DestroyWindow(hList
);
1318 /* LVS_REPORT without WS_VISIBLE, try to show it */
1319 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1320 GetModuleHandle(NULL
), 0);
1321 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1322 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1323 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1324 ShowWindow(hList
, SW_SHOW
);
1325 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1326 ok(IsWindow(hHeader
), "Header should be created\n");
1327 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1328 DestroyWindow(hList
);
1330 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1331 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
|LVS_NOCOLUMNHEADER
|WS_VISIBLE
,
1332 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
1333 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1334 ok(IsWindow(hHeader
), "Header should be created\n");
1335 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1336 /* HDS_DRAGDROP set by default */
1337 ok(GetWindowLongPtr(hHeader
, GWL_STYLE
) & HDS_DRAGDROP
, "Expected header to have HDS_DRAGDROP\n");
1338 DestroyWindow(hList
);
1340 /* setting LVS_EX_HEADERDRAGDROP creates header */
1341 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1342 GetModuleHandle(NULL
), 0);
1343 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1344 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1345 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1346 SendMessage(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1347 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1348 ok(IsWindow(hHeader
) ||
1349 broken(!IsWindow(hHeader
)), /* 4.7x common controls */
1350 "Header should be created\n");
1351 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1352 DestroyWindow(hList
);
1354 /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1355 hList
= create_custom_listview_control(0);
1356 SendMessage(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1357 r
= SendMessage(hList
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1358 ok(r
& LVS_EX_HEADERDRAGDROP
, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1359 DestroyWindow(hList
);
1361 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1362 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1363 GetModuleHandle(NULL
), 0);
1364 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1365 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1367 rect
.left
= LVIR_BOUNDS
;
1369 rect
.right
= rect
.bottom
= -10;
1370 r
= SendMessage(hList
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1371 ok(r
!= 0, "Expected not-null LRESULT\n");
1373 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1374 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1375 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1377 DestroyWindow(hList
);
1379 /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1380 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1381 hList
= create_listview_control(LVS_OWNERDRAWFIXED
);
1382 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_ownerdrawfixed_parent_seq
,
1383 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE
);
1384 DestroyWindow(hList
);
1387 static void test_redraw(void)
1389 HWND hwnd
, hwndheader
;
1394 hwnd
= create_listview_control(0);
1395 hwndheader
= subclass_header(hwnd
);
1397 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1399 trace("invalidate & update\n");
1400 InvalidateRect(hwnd
, NULL
, TRUE
);
1402 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, redraw_listview_seq
, "redraw listview", FALSE
);
1404 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1406 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1407 /* 1. Without backbuffer */
1408 res
= ListView_SetBkColor(hwnd
, CLR_NONE
);
1411 hdc
= GetWindowDC(hwndparent
);
1413 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1414 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1415 ok(r
!= 0, "Expected not zero result\n");
1416 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1417 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1419 res
= ListView_SetBkColor(hwnd
, CLR_DEFAULT
);
1422 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1423 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1424 ok(r
!= 0, "Expected not zero result\n");
1425 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1426 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1428 /* 2. With backbuffer */
1429 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_DOUBLEBUFFER
,
1430 LVS_EX_DOUBLEBUFFER
);
1431 res
= ListView_SetBkColor(hwnd
, CLR_NONE
);
1434 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1435 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1436 ok(r
!= 0, "Expected not zero result\n");
1437 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1438 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1440 res
= ListView_SetBkColor(hwnd
, CLR_DEFAULT
);
1443 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1444 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1445 todo_wine
ok(r
!= 0, "Expected not zero result\n");
1446 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1447 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1449 ReleaseDC(hwndparent
, hdc
);
1451 DestroyWindow(hwnd
);
1454 static LRESULT WINAPI
cd_wndproc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1456 COLORREF clr
, c0ffee
= RGB(0xc0, 0xff, 0xee);
1458 if(msg
== WM_NOTIFY
) {
1459 NMHDR
*nmhdr
= (PVOID
)lp
;
1460 if(nmhdr
->code
== NM_CUSTOMDRAW
) {
1461 NMLVCUSTOMDRAW
*nmlvcd
= (PVOID
)nmhdr
;
1462 trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd
->nmcd
.dwDrawStage
);
1463 switch(nmlvcd
->nmcd
.dwDrawStage
) {
1465 SetBkColor(nmlvcd
->nmcd
.hdc
, c0ffee
);
1466 return CDRF_NOTIFYITEMDRAW
;
1467 case CDDS_ITEMPREPAINT
:
1468 nmlvcd
->clrTextBk
= CLR_DEFAULT
;
1469 return CDRF_NOTIFYSUBITEMDRAW
;
1470 case CDDS_ITEMPREPAINT
| CDDS_SUBITEM
:
1471 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1472 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1473 return CDRF_NOTIFYPOSTPAINT
;
1474 case CDDS_ITEMPOSTPAINT
| CDDS_SUBITEM
:
1475 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1476 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1477 return CDRF_DODEFAULT
;
1479 return CDRF_DODEFAULT
;
1483 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
1486 static void test_customdraw(void)
1491 hwnd
= create_listview_control(0);
1493 insert_column(hwnd
, 0);
1494 insert_column(hwnd
, 1);
1495 insert_item(hwnd
, 0);
1497 oldwndproc
= (WNDPROC
)SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
,
1498 (LONG_PTR
)cd_wndproc
);
1500 InvalidateRect(hwnd
, NULL
, TRUE
);
1503 SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
, (LONG_PTR
)oldwndproc
);
1505 DestroyWindow(hwnd
);
1508 static void test_icon_spacing(void)
1510 /* LVM_SETICONSPACING */
1511 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1517 hwnd
= create_custom_listview_control(LVS_ICON
);
1518 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1520 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, (WPARAM
)hwndparent
, (LPARAM
)NF_REQUERY
);
1521 expect(NFR_ANSI
, r
);
1523 /* reset the icon spacing to defaults */
1524 SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1526 /* now we can request what the defaults are */
1527 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1531 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1533 trace("test icon spacing\n");
1535 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(20, 30));
1536 ok(r
== MAKELONG(w
, h
) ||
1537 broken(r
== MAKELONG(w
, w
)), /* win98 */
1538 "Expected %d, got %d\n", MAKELONG(w
, h
), r
);
1540 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(25, 35));
1541 expect(MAKELONG(20,30), r
);
1543 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1,-1));
1544 expect(MAKELONG(25,35), r
);
1546 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_icon_spacing_seq
, "test icon spacing seq", FALSE
);
1548 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1549 DestroyWindow(hwnd
);
1552 static void test_color(void)
1554 /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1561 COLORREF colors
[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE
, RGB(255,255,255)};
1563 hwnd
= create_listview_control(0);
1564 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1566 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1568 trace("test color seq\n");
1569 for (i
= 0; i
< 4; i
++)
1573 r
= SendMessage(hwnd
, LVM_SETBKCOLOR
, 0, color
);
1575 r
= SendMessage(hwnd
, LVM_GETBKCOLOR
, 0, color
);
1578 r
= SendMessage(hwnd
, LVM_SETTEXTCOLOR
, 0, color
);
1580 r
= SendMessage(hwnd
, LVM_GETTEXTCOLOR
, 0, color
);
1583 r
= SendMessage(hwnd
, LVM_SETTEXTBKCOLOR
, 0, color
);
1585 r
= SendMessage(hwnd
, LVM_GETTEXTBKCOLOR
, 0, color
);
1589 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_color_seq
, "test color seq", FALSE
);
1591 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1592 DestroyWindow(hwnd
);
1595 static void test_item_count(void)
1597 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1610 static CHAR item0text
[] = "item0";
1611 static CHAR item1text
[] = "item1";
1612 static CHAR item2text
[] = "item2";
1614 hwnd
= create_listview_control(0);
1615 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1617 /* resize in dpiaware manner to fit all 3 items added */
1619 hOldFont
= SelectObject(hdc
, GetStockObject(SYSTEM_FONT
));
1620 GetTextMetricsA(hdc
, &tm
);
1621 /* 2 extra pixels for bounds and header border */
1622 height
= tm
.tmHeight
+ 2;
1623 SelectObject(hdc
, hOldFont
);
1626 GetWindowRect(hwnd
, &rect
);
1627 /* 3 items + 1 header + 1 to be sure */
1628 MoveWindow(hwnd
, 0, 0, rect
.right
- rect
.left
, 5 * height
, FALSE
);
1630 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1632 trace("test item count\n");
1634 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1638 item0
.mask
= LVIF_TEXT
;
1641 item0
.pszText
= item0text
;
1642 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1645 /* [item0, item1] */
1646 item1
.mask
= LVIF_TEXT
;
1649 item1
.pszText
= item1text
;
1650 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1653 /* [item0, item1, item2] */
1654 item2
.mask
= LVIF_TEXT
;
1657 item2
.pszText
= item2text
;
1658 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1661 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1664 /* [item0, item1] */
1665 r
= SendMessage(hwnd
, LVM_DELETEITEM
, 2, 0);
1668 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1672 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1675 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1679 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1682 /* [item0, item1] */
1683 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1686 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1689 /* [item0, item1, item2] */
1690 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1693 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1696 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_item_count_seq
, "test item count seq", FALSE
);
1698 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1699 DestroyWindow(hwnd
);
1702 static void test_item_position(void)
1704 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1713 static CHAR item0text
[] = "item0";
1714 static CHAR item1text
[] = "item1";
1715 static CHAR item2text
[] = "item2";
1717 hwnd
= create_custom_listview_control(LVS_ICON
);
1718 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1720 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1722 trace("test item position\n");
1725 item0
.mask
= LVIF_TEXT
;
1728 item0
.pszText
= item0text
;
1729 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1732 /* [item0, item1] */
1733 item1
.mask
= LVIF_TEXT
;
1736 item1
.pszText
= item1text
;
1737 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1740 /* [item0, item1, item2] */
1741 item2
.mask
= LVIF_TEXT
;
1744 item2
.pszText
= item2text
;
1745 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1748 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 1, MAKELPARAM(10,5));
1750 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 1, (LPARAM
) &position
);
1752 expect2(10, 5, position
.x
, position
.y
);
1754 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 2, MAKELPARAM(0,0));
1756 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 2, (LPARAM
) &position
);
1758 expect2(0, 0, position
.x
, position
.y
);
1760 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 0, MAKELPARAM(20,20));
1762 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
) &position
);
1764 expect2(20, 20, position
.x
, position
.y
);
1766 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_itempos_seq
, "test item position seq", TRUE
);
1768 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1769 DestroyWindow(hwnd
);
1772 static void test_getorigin(void)
1780 position
.x
= position
.y
= 0;
1782 hwnd
= create_custom_listview_control(LVS_ICON
);
1783 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1784 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1785 trace("test get origin results\n");
1786 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1788 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1789 DestroyWindow(hwnd
);
1791 hwnd
= create_custom_listview_control(LVS_SMALLICON
);
1792 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1793 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1794 trace("test get origin results\n");
1795 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1797 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1798 DestroyWindow(hwnd
);
1800 hwnd
= create_custom_listview_control(LVS_LIST
);
1801 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1802 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1803 trace("test get origin results\n");
1804 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1806 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1807 DestroyWindow(hwnd
);
1809 hwnd
= create_custom_listview_control(LVS_REPORT
);
1810 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1811 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1812 trace("test get origin results\n");
1813 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1815 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1816 DestroyWindow(hwnd
);
1820 static void test_multiselect(void)
1822 typedef struct t_select_task
1833 int i
,j
,item_count
,selected_count
;
1834 static const int items
=5;
1840 static struct t_select_task task_list
[] = {
1841 { "using VK_DOWN", 0, VK_DOWN
, -1, -1 },
1842 { "using VK_UP", -1, VK_UP
, -1, -1 },
1843 { "using VK_END", 0, VK_END
, 1, -1 },
1844 { "using VK_HOME", -1, VK_HOME
, 1, -1 }
1848 hwnd
= create_listview_control(0);
1850 for (i
=0;i
<items
;i
++) {
1851 insert_item(hwnd
, 0);
1854 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1856 expect(items
,item_count
);
1859 task
= task_list
[i
];
1861 /* deselect all items */
1862 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1863 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1865 /* set initial position */
1866 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, (task
.initPos
== -1 ? item_count
-1 : task
.initPos
));
1867 ListView_SetItemState(hwnd
,(task
.initPos
== -1 ? item_count
-1 : task
.initPos
),LVIS_SELECTED
,LVIS_SELECTED
);
1869 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1871 ok(selected_count
== 1, "There should be only one selected item at the beginning (is %d)\n",selected_count
);
1873 /* Set SHIFT key pressed */
1874 GetKeyboardState(kstate
);
1875 kstate
[VK_SHIFT
]=0x80;
1876 SetKeyboardState(kstate
);
1878 for (j
=1;j
<=(task
.count
== -1 ? item_count
: task
.count
);j
++) {
1879 r
= SendMessage(hwnd
, WM_KEYDOWN
, task
.loopVK
, 0);
1881 r
= SendMessage(hwnd
, WM_KEYUP
, task
.loopVK
, 0);
1885 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1887 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
);
1889 /* Set SHIFT key released */
1890 GetKeyboardState(kstate
);
1891 kstate
[VK_SHIFT
]=0x00;
1892 SetKeyboardState(kstate
);
1894 DestroyWindow(hwnd
);
1896 /* make multiple selection, then switch to LVS_SINGLESEL */
1897 hwnd
= create_listview_control(0);
1898 for (i
=0;i
<items
;i
++) {
1899 insert_item(hwnd
, 0);
1901 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1902 expect(items
,item_count
);
1903 /* deselect all items */
1904 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1905 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1907 ListView_SetItemState(hwnd
, i
, LVIS_SELECTED
, LVIS_SELECTED
);
1910 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1912 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1916 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1917 ok(!(style
& LVS_SINGLESEL
), "LVS_SINGLESEL isn't expected\n");
1918 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SINGLESEL
);
1919 /* check that style is accepted */
1920 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1921 ok(style
& LVS_SINGLESEL
, "LVS_SINGLESEL expected\n");
1924 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1925 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1927 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1929 SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1932 /* select one more */
1933 ListView_SetItemState(hwnd
, 3, LVIS_SELECTED
, LVIS_SELECTED
);
1936 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1937 ok(!(r
& LVIS_SELECTED
), "Expected item %d to be unselected\n", i
);
1939 r
= ListView_GetItemState(hwnd
, 3, LVIS_SELECTED
);
1940 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1942 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1944 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1948 /* try to select all on LVS_SINGLESEL */
1949 memset(&item
, 0, sizeof(item
));
1950 item
.stateMask
= LVIS_SELECTED
;
1951 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1953 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1955 item
.stateMask
= LVIS_SELECTED
;
1956 item
.state
= LVIS_SELECTED
;
1957 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1960 r
= ListView_GetSelectedCount(hwnd
);
1962 r
= ListView_GetSelectionMark(hwnd
);
1965 /* try to deselect all on LVS_SINGLESEL */
1966 item
.stateMask
= LVIS_SELECTED
;
1967 item
.state
= LVIS_SELECTED
;
1968 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
1971 item
.stateMask
= LVIS_SELECTED
;
1973 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1975 r
= ListView_GetSelectedCount(hwnd
);
1978 DestroyWindow(hwnd
);
1981 static void test_subitem_rect(void)
1988 /* test LVM_GETSUBITEMRECT for header */
1989 hwnd
= create_listview_control(0);
1990 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1991 /* add some columns */
1992 memset(&col
, 0, sizeof(LVCOLUMN
));
1993 col
.mask
= LVCF_WIDTH
;
1996 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
2000 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 1, (LPARAM
)&col
);
2004 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 2, (LPARAM
)&col
);
2006 /* item = -1 means header, subitem index is 1 based */
2007 rect
.left
= LVIR_BOUNDS
;
2009 rect
.right
= rect
.bottom
= 0;
2010 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2013 rect
.left
= LVIR_BOUNDS
;
2015 rect
.right
= rect
.bottom
= 0;
2016 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2018 ok(r
!= 0, "Expected not-null LRESULT\n");
2019 expect(100, rect
.left
);
2020 expect(250, rect
.right
);
2022 expect(3, rect
.top
);
2024 rect
.left
= LVIR_BOUNDS
;
2026 rect
.right
= rect
.bottom
= 0;
2027 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2029 ok(r
!= 0, "Expected not-null LRESULT\n");
2030 expect(250, rect
.left
);
2031 expect(450, rect
.right
);
2033 expect(3, rect
.top
);
2035 /* item LVS_REPORT padding isn't applied to subitems */
2036 insert_item(hwnd
, 0);
2038 rect
.left
= LVIR_BOUNDS
;
2040 rect
.right
= rect
.bottom
= 0;
2041 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2042 ok(r
!= 0, "Expected not-null LRESULT\n");
2043 expect(100, rect
.left
);
2044 expect(250, rect
.right
);
2046 rect
.left
= LVIR_ICON
;
2048 rect
.right
= rect
.bottom
= 0;
2049 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2050 ok(r
!= 0, "Expected not-null LRESULT\n");
2051 /* no icon attached - zero width rectangle, with no left padding */
2052 expect(100, rect
.left
);
2053 expect(100, rect
.right
);
2055 rect
.left
= LVIR_LABEL
;
2057 rect
.right
= rect
.bottom
= 0;
2058 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2059 ok(r
!= 0, "Expected not-null LRESULT\n");
2060 /* same as full LVIR_BOUNDS */
2061 expect(100, rect
.left
);
2062 expect(250, rect
.right
);
2064 DestroyWindow(hwnd
);
2066 /* try it for non LVS_REPORT style */
2067 hwnd
= CreateWindow("SysListView32", "Test", LVS_ICON
, 0, 0, 100, 100, NULL
, NULL
,
2068 GetModuleHandle(NULL
), 0);
2069 rect
.left
= LVIR_BOUNDS
;
2071 rect
.right
= rect
.bottom
= -10;
2072 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2073 ok(r
== 0, "Expected not-null LRESULT\n");
2074 /* rect is unchanged */
2075 expect(0, rect
.left
);
2076 expect(-10, rect
.right
);
2077 expect(1, rect
.top
);
2078 expect(-10, rect
.bottom
);
2079 DestroyWindow(hwnd
);
2082 /* comparison callback for test_sorting */
2083 static INT WINAPI
test_CallBackCompare(LPARAM first
, LPARAM second
, LPARAM lParam
)
2085 if (first
== second
) return 0;
2086 return (first
> second
? 1 : -1);
2089 static void test_sorting(void)
2095 static CHAR names
[][5] = {"A", "B", "C", "D", "0"};
2098 hwnd
= create_listview_control(0);
2099 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2101 /* insert some items */
2102 item
.mask
= LVIF_PARAM
| LVIF_STATE
;
2103 item
.state
= LVIS_SELECTED
;
2107 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2110 item
.mask
= LVIF_PARAM
;
2114 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2117 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
2118 item
.state
= LVIS_SELECTED
;
2122 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2125 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2128 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2131 r
= SendMessage(hwnd
, LVM_SORTITEMS
, 0, (LPARAM
)test_CallBackCompare
);
2134 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2136 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2138 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_SELECTED
);
2140 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_SELECTED
);
2141 expect(LVIS_SELECTED
, r
);
2142 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_SELECTED
);
2143 expect(LVIS_SELECTED
, r
);
2145 DestroyWindow(hwnd
);
2147 /* switch to LVS_SORTASCENDING when some items added */
2148 hwnd
= create_listview_control(0);
2149 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2151 item
.mask
= LVIF_TEXT
;
2154 item
.pszText
= names
[1];
2155 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2158 item
.mask
= LVIF_TEXT
;
2161 item
.pszText
= names
[2];
2162 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2165 item
.mask
= LVIF_TEXT
;
2168 item
.pszText
= names
[0];
2169 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2172 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2173 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
2174 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2175 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2177 /* no sorting performed when switched to LVS_SORTASCENDING */
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
);
2196 /* adding new item doesn't resort list */
2197 item
.mask
= LVIF_TEXT
;
2200 item
.pszText
= names
[3];
2201 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2204 item
.mask
= LVIF_TEXT
;
2206 item
.pszText
= buff
;
2207 item
.cchTextMax
= sizeof(buff
);
2208 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2210 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2213 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2215 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2218 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2220 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2223 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2225 ok(lstrcmp(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
2227 /* corner case - item should be placed at first position */
2228 item
.mask
= LVIF_TEXT
;
2231 item
.pszText
= names
[4];
2232 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2236 item
.pszText
= buff
;
2237 item
.cchTextMax
= sizeof(buff
);
2238 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2240 ok(lstrcmp(buff
, names
[4]) == 0, "Expected '%s', got '%s'\n", names
[4], buff
);
2243 item
.pszText
= buff
;
2244 item
.cchTextMax
= sizeof(buff
);
2245 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2247 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2250 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2252 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2255 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2257 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2260 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2262 ok(lstrcmp(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
2264 DestroyWindow(hwnd
);
2267 static void test_ownerdata(void)
2270 LONG_PTR style
, ret
;
2274 /* it isn't possible to set LVS_OWNERDATA after creation */
2277 win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2281 hwnd
= create_listview_control(0);
2282 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2283 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2284 ok(!(style
& LVS_OWNERDATA
) && style
, "LVS_OWNERDATA isn't expected\n");
2286 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2288 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
2289 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2290 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2291 "try to switch to LVS_OWNERDATA seq", FALSE
);
2293 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2294 ok(!(style
& LVS_OWNERDATA
), "LVS_OWNERDATA isn't expected\n");
2295 DestroyWindow(hwnd
);
2298 /* try to set LVS_OWNERDATA after creation just having it */
2299 hwnd
= create_listview_control(LVS_OWNERDATA
);
2300 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2301 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2302 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2304 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2306 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
2307 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2308 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2309 "try to switch to LVS_OWNERDATA seq", FALSE
);
2310 DestroyWindow(hwnd
);
2312 /* try to remove LVS_OWNERDATA after creation just having it */
2315 win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2319 hwnd
= create_listview_control(LVS_OWNERDATA
);
2320 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2321 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2322 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2324 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2326 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_OWNERDATA
);
2327 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2328 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2329 "try to switch to LVS_OWNERDATA seq", FALSE
);
2330 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2331 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2332 DestroyWindow(hwnd
);
2335 /* try select an item */
2336 hwnd
= create_listview_control(LVS_OWNERDATA
);
2337 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2338 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2339 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2340 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2342 memset(&item
, 0, sizeof(item
));
2343 item
.stateMask
= LVIS_SELECTED
;
2344 item
.state
= LVIS_SELECTED
;
2345 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2347 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2349 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2351 DestroyWindow(hwnd
);
2353 /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2354 hwnd
= create_listview_control(LVS_OWNERDATA
);
2355 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2356 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2357 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2358 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2360 memset(&item
, 0, sizeof(item
));
2361 item
.mask
= LVIF_STATE
;
2363 item
.stateMask
= LVIS_SELECTED
;
2364 item
.state
= LVIS_SELECTED
;
2365 res
= SendMessageA(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2367 DestroyWindow(hwnd
);
2369 /* check notifications after focused/selected changed */
2370 hwnd
= create_listview_control(LVS_OWNERDATA
);
2371 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2372 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2373 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2375 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2377 memset(&item
, 0, sizeof(item
));
2378 item
.stateMask
= LVIS_SELECTED
;
2379 item
.state
= LVIS_SELECTED
;
2380 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2383 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownderdata_select_focus_parent_seq
,
2384 "ownerdata select notification", TRUE
);
2386 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2388 memset(&item
, 0, sizeof(item
));
2389 item
.stateMask
= LVIS_FOCUSED
;
2390 item
.state
= LVIS_FOCUSED
;
2391 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2394 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownderdata_select_focus_parent_seq
,
2395 "ownerdata focus notification", TRUE
);
2396 DestroyWindow(hwnd
);
2398 /* check notifications on LVM_GETITEM */
2399 /* zero callback mask */
2400 hwnd
= create_listview_control(LVS_OWNERDATA
);
2401 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2402 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2403 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2405 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2407 memset(&item
, 0, sizeof(item
));
2408 item
.stateMask
= LVIS_SELECTED
;
2409 item
.mask
= LVIF_STATE
;
2410 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2413 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
2414 "ownerdata getitem selected state 1", FALSE
);
2416 /* non zero callback mask but not we asking for */
2417 res
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_OVERLAYMASK
, 0);
2420 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2422 memset(&item
, 0, sizeof(item
));
2423 item
.stateMask
= LVIS_SELECTED
;
2424 item
.mask
= LVIF_STATE
;
2425 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2428 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
2429 "ownerdata getitem selected state 2", FALSE
);
2431 /* LVIS_OVERLAYMASK callback mask, asking for index */
2432 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2434 memset(&item
, 0, sizeof(item
));
2435 item
.stateMask
= LVIS_OVERLAYMASK
;
2436 item
.mask
= LVIF_STATE
;
2437 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2440 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
2441 "ownerdata getitem selected state 2", FALSE
);
2443 DestroyWindow(hwnd
);
2445 /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
2446 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_SORTASCENDING
);
2447 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2448 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2449 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
2450 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2451 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SORTASCENDING
);
2452 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2453 ok(!(style
& LVS_SORTASCENDING
), "Expected LVS_SORTASCENDING not set\n");
2454 DestroyWindow(hwnd
);
2455 /* apparently it's allowed to switch these style on after creation */
2456 hwnd
= create_listview_control(LVS_OWNERDATA
);
2457 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2458 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2459 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
2460 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
2461 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2462 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2463 DestroyWindow(hwnd
);
2465 hwnd
= create_listview_control(LVS_OWNERDATA
);
2466 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2467 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2468 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
2469 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTDESCENDING
);
2470 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2471 ok(style
& LVS_SORTDESCENDING
, "Expected LVS_SORTDESCENDING to be set\n");
2472 DestroyWindow(hwnd
);
2475 static void test_norecompute(void)
2477 static CHAR testA
[] = "test";
2483 /* self containing control */
2484 hwnd
= create_listview_control(0);
2485 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2486 memset(&item
, 0, sizeof(item
));
2487 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
2489 item
.stateMask
= LVIS_SELECTED
;
2490 item
.state
= LVIS_SELECTED
;
2491 item
.pszText
= testA
;
2492 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2494 /* retrieve with LVIF_NORECOMPUTE */
2495 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2497 item
.pszText
= buff
;
2498 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2499 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2501 ok(lstrcmp(buff
, testA
) == 0, "Expected (%s), got (%s)\n", testA
, buff
);
2503 item
.mask
= LVIF_TEXT
;
2505 item
.pszText
= LPSTR_TEXTCALLBACK
;
2506 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2509 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2511 item
.pszText
= buff
;
2512 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2514 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2515 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2517 ok(item
.pszText
== LPSTR_TEXTCALLBACK
, "Expected (%p), got (%p)\n",
2518 LPSTR_TEXTCALLBACK
, (VOID
*)item
.pszText
);
2519 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq", FALSE
);
2521 DestroyWindow(hwnd
);
2524 hwnd
= create_listview_control(LVS_OWNERDATA
);
2525 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2527 item
.mask
= LVIF_STATE
;
2528 item
.stateMask
= LVIS_SELECTED
;
2529 item
.state
= LVIS_SELECTED
;
2531 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2534 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2536 item
.pszText
= buff
;
2537 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2538 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2539 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2541 ok(item
.pszText
== LPSTR_TEXTCALLBACK
, "Expected (%p), got (%p)\n",
2542 LPSTR_TEXTCALLBACK
, (VOID
*)item
.pszText
);
2543 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE
);
2545 DestroyWindow(hwnd
);
2548 static void test_nosortheader(void)
2553 hwnd
= create_listview_control(0);
2554 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2556 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
2557 ok(IsWindow(header
), "header expected\n");
2559 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2560 ok(style
& HDS_BUTTONS
, "expected header to have HDS_BUTTONS\n");
2562 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2563 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
| LVS_NOSORTHEADER
);
2564 /* HDS_BUTTONS retained */
2565 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2566 ok(style
& HDS_BUTTONS
, "expected header to retain HDS_BUTTONS\n");
2568 DestroyWindow(hwnd
);
2570 /* create with LVS_NOSORTHEADER */
2571 hwnd
= create_listview_control(LVS_NOSORTHEADER
);
2572 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2574 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
2575 ok(IsWindow(header
), "header expected\n");
2577 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2578 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
2580 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2581 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
& ~LVS_NOSORTHEADER
);
2582 /* not changed here */
2583 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2584 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
2586 DestroyWindow(hwnd
);
2589 static void test_setredraw(void)
2595 hwnd
= create_listview_control(0);
2596 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2598 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2599 ListView seems to handle it internally without DefWinProc */
2601 /* default value first */
2602 ret
= SendMessage(hwnd
, WM_SETREDRAW
, TRUE
, 0);
2605 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2606 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
2607 ret
= SendMessage(hwnd
, WM_SETREDRAW
, FALSE
, 0);
2609 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2610 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
2612 DestroyWindow(hwnd
);
2615 static void test_hittest(void)
2621 static CHAR text
[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2624 HIMAGELIST himl
, himl2
;
2627 hwnd
= create_listview_control(0);
2628 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2630 /* LVS_REPORT with a single subitem (2 columns) */
2631 insert_column(hwnd
, 0);
2632 insert_column(hwnd
, 1);
2633 insert_item(hwnd
, 0);
2636 /* the only purpose of that line is to be as long as a half item rect */
2637 item
.pszText
= text
;
2638 r
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0, (LPARAM
)&item
);
2641 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
2643 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
2646 memset(&bounds
, 0, sizeof(bounds
));
2647 bounds
.left
= LVIR_BOUNDS
;
2648 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&bounds
);
2649 ok(bounds
.bottom
- bounds
.top
> 0, "Expected non zero item height\n");
2650 ok(bounds
.right
- bounds
.left
> 0, "Expected non zero item width\n");
2651 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pos
);
2654 /* LVS_EX_FULLROWSELECT not set, no icons attached */
2655 x
= pos
.x
+ 50; /* column half width */
2656 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2657 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, __LINE__
);
2658 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2659 x
= pos
.x
+ 150; /* outside column */
2660 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2661 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2662 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2663 /* outside possible client rectangle (to right) */
2665 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2666 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2667 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
, __LINE__
);
2668 /* subitem returned with -1 item too */
2671 test_lvm_subitemhittest(hwnd
, x
, y
, -1, 1, LVHT_NOWHERE
, FALSE
, FALSE
, TRUE
, __LINE__
);
2672 /* parent client area is 100x100 by default */
2673 MoveWindow(hwnd
, 0, 0, 300, 100, FALSE
);
2674 x
= pos
.x
+ 150; /* outside column */
2675 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2676 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, FALSE
, FALSE
, __LINE__
);
2677 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2678 /* the same with LVS_EX_FULLROWSELECT */
2679 SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
2680 x
= pos
.x
+ 150; /* outside column */
2681 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2682 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEM
, FALSE
, FALSE
, __LINE__
);
2683 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2684 MoveWindow(hwnd
, 0, 0, 100, 100, FALSE
);
2685 x
= pos
.x
+ 150; /* outside column */
2686 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2687 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2688 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2689 /* outside possible client rectangle (to right) */
2691 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2692 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2693 test_lvm_subitemhittest(hwnd
, x
, y
, -1, -1, LVHT_NOWHERE
, FALSE
, FALSE
, FALSE
, __LINE__
);
2694 /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
2695 himl
= ImageList_Create(16, 16, 0, 4, 4);
2696 ok(himl
!= NULL
, "failed to create imagelist\n");
2697 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
2698 ok(hbmp
!= NULL
, "failed to create bitmap\n");
2699 r
= ImageList_Add(himl
, hbmp
, 0);
2700 ok(r
== 0, "should be zero\n");
2701 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
2702 ok(hbmp
!= NULL
, "failed to create bitmap\n");
2703 r
= ImageList_Add(himl
, hbmp
, 0);
2704 ok(r
== 1, "should be one\n");
2706 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
2707 ok(r
== 0, "should return zero\n");
2709 item
.mask
= LVIF_IMAGE
;
2713 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2717 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2718 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, __LINE__
);
2719 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2721 /* state icons indices are 1 based, check with valid index */
2722 item
.mask
= LVIF_STATE
;
2723 item
.state
= INDEXTOSTATEIMAGEMASK(1);
2724 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2727 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2731 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2732 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, __LINE__
);
2733 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2735 himl2
= (HIMAGELIST
)SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)NULL
);
2736 ok(himl2
== himl
, "should return handle\n");
2738 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
2739 ok(r
== 0, "should return zero\n");
2742 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2743 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, __LINE__
);
2744 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2746 DestroyWindow(hwnd
);
2749 static void test_getviewrect(void)
2756 hwnd
= create_listview_control(0);
2757 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2760 r
= SendMessage(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
2763 insert_column(hwnd
, 0);
2764 insert_column(hwnd
, 1);
2766 memset(&item
, 0, sizeof(item
));
2769 SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
2771 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
2773 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(120, 0));
2776 rect
.left
= rect
.right
= rect
.top
= rect
.bottom
= -1;
2777 r
= SendMessage(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
2779 /* left is set to (2e31-1) - XP SP2 */
2780 expect(0, rect
.right
);
2781 expect(0, rect
.top
);
2782 expect(0, rect
.bottom
);
2784 /* switch to LVS_ICON */
2785 SetWindowLong(hwnd
, GWL_STYLE
, GetWindowLong(hwnd
, GWL_STYLE
) & ~LVS_REPORT
);
2787 rect
.left
= rect
.right
= rect
.top
= rect
.bottom
= -1;
2788 r
= SendMessage(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
2790 expect(0, rect
.left
);
2791 expect(0, rect
.top
);
2792 /* precise value differs for 2k, XP and Vista */
2793 ok(rect
.bottom
> 0, "Expected positive bottom value, got %d\n", rect
.bottom
);
2794 ok(rect
.right
> 0, "Expected positive right value, got %d\n", rect
.right
);
2796 DestroyWindow(hwnd
);
2799 static void test_getitemposition(void)
2806 hwnd
= create_listview_control(0);
2807 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2808 header
= subclass_header(hwnd
);
2810 /* LVS_REPORT, single item, no columns added */
2811 insert_item(hwnd
, 0);
2813 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2816 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
2818 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq1
, "get item position 1", FALSE
);
2820 /* LVS_REPORT, single item, single column */
2821 insert_column(hwnd
, 0);
2823 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2826 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
2828 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq2
, "get item position 2", TRUE
);
2830 memset(&rect
, 0, sizeof(rect
));
2831 SendMessage(header
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2834 /* offset by header height */
2835 expect(rect
.bottom
- rect
.top
, pt
.y
);
2837 DestroyWindow(hwnd
);
2840 static void test_columnscreation(void)
2845 hwnd
= create_listview_control(0);
2846 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2848 insert_item(hwnd
, 0);
2850 /* headers columns aren't created automatically */
2851 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
2852 ok(IsWindow(header
), "Expected header handle\n");
2853 r
= SendMessage(header
, HDM_GETITEMCOUNT
, 0, 0);
2856 DestroyWindow(hwnd
);
2859 static void test_getitemrect(void)
2871 hwnd
= create_listview_control(0);
2872 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2875 memset(&item
, 0, sizeof(item
));
2878 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
2881 rect
.left
= LVIR_BOUNDS
;
2882 rect
.right
= rect
.top
= rect
.bottom
= -1;
2883 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2886 /* zero width rectangle with no padding */
2887 expect(0, rect
.left
);
2888 expect(0, rect
.right
);
2890 insert_column(hwnd
, 0);
2891 insert_column(hwnd
, 1);
2893 col
.mask
= LVCF_WIDTH
;
2895 r
= SendMessage(hwnd
, LVM_SETCOLUMN
, 0, (LPARAM
)&col
);
2898 col
.mask
= LVCF_WIDTH
;
2900 r
= SendMessage(hwnd
, LVM_SETCOLUMN
, 1, (LPARAM
)&col
);
2903 rect
.left
= LVIR_BOUNDS
;
2904 rect
.right
= rect
.top
= rect
.bottom
= -1;
2905 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2908 /* still no left padding */
2909 expect(0, rect
.left
);
2910 expect(150, rect
.right
);
2912 rect
.left
= LVIR_SELECTBOUNDS
;
2913 rect
.right
= rect
.top
= rect
.bottom
= -1;
2914 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2917 expect(2, rect
.left
);
2919 rect
.left
= LVIR_LABEL
;
2920 rect
.right
= rect
.top
= rect
.bottom
= -1;
2921 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2923 /* padding, column width */
2924 expect(2, rect
.left
);
2925 expect(50, rect
.right
);
2927 /* no icons attached */
2928 rect
.left
= LVIR_ICON
;
2929 rect
.right
= rect
.top
= rect
.bottom
= -1;
2930 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2933 expect(2, rect
.left
);
2934 expect(2, rect
.right
);
2937 order
[0] = 1; order
[1] = 0;
2938 r
= SendMessage(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
2941 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
2943 /* 1 indexed column width + padding */
2944 todo_wine
expect(102, pt
.x
);
2945 /* rect is at zero too */
2946 rect
.left
= LVIR_BOUNDS
;
2947 rect
.right
= rect
.top
= rect
.bottom
= -1;
2948 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2950 expect(0, rect
.left
);
2951 /* just width sum */
2952 expect(150, rect
.right
);
2954 rect
.left
= LVIR_SELECTBOUNDS
;
2955 rect
.right
= rect
.top
= rect
.bottom
= -1;
2956 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2958 /* column width + padding */
2959 todo_wine
expect(102, rect
.left
);
2961 /* back to initial order */
2962 order
[0] = 0; order
[1] = 1;
2963 r
= SendMessage(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
2967 himl
= ImageList_Create(16, 16, 0, 2, 2);
2968 ok(himl
!= NULL
, "failed to create imagelist\n");
2969 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
2970 ok(hbm
!= NULL
, "failed to create bitmap\n");
2971 r
= ImageList_Add(himl
, hbm
, 0);
2972 ok(r
== 0, "should be zero\n");
2973 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
2974 ok(hbm
!= NULL
, "failed to create bitmap\n");
2975 r
= ImageList_Add(himl
, hbm
, 0);
2976 ok(r
== 1, "should be one\n");
2978 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
2979 ok(r
== 0, "should return zero\n");
2981 item
.mask
= LVIF_STATE
;
2982 item
.state
= INDEXTOSTATEIMAGEMASK(1);
2983 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2986 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2990 rect
.left
= LVIR_ICON
;
2991 rect
.right
= rect
.top
= rect
.bottom
= -1;
2992 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2994 /* padding + stateicon width */
2995 expect(18, rect
.left
);
2996 expect(18, rect
.right
);
2998 rect
.left
= LVIR_LABEL
;
2999 rect
.right
= rect
.top
= rect
.bottom
= -1;
3000 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3002 /* padding + stateicon width -> column width */
3003 expect(18, rect
.left
);
3004 expect(50, rect
.right
);
3006 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)NULL
);
3007 ok(r
!= 0, "should return current list handle\n");
3009 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
3010 ok(r
== 0, "should return zero\n");
3012 item
.mask
= LVIF_STATE
| LVIF_IMAGE
;
3015 item
.stateMask
= ~0;
3018 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
3022 rect
.left
= LVIR_ICON
;
3023 rect
.right
= rect
.top
= rect
.bottom
= -1;
3024 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3026 /* padding, icon width */
3027 expect(2, rect
.left
);
3028 expect(18, rect
.right
);
3030 rect
.left
= LVIR_LABEL
;
3031 rect
.right
= rect
.top
= rect
.bottom
= -1;
3032 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3034 /* padding + icon width -> column width */
3035 expect(18, rect
.left
);
3036 expect(50, rect
.right
);
3039 rect
.left
= LVIR_SELECTBOUNDS
;
3040 rect
.right
= rect
.top
= rect
.bottom
= -1;
3041 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3043 /* padding, column width */
3044 expect(2, rect
.left
);
3045 expect(50, rect
.right
);
3047 /* try with indentation */
3048 item
.mask
= LVIF_INDENT
;
3052 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
3056 rect
.left
= LVIR_BOUNDS
;
3057 rect
.right
= rect
.top
= rect
.bottom
= -1;
3058 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3060 /* padding + 1 icon width, column width */
3061 expect(0, rect
.left
);
3062 expect(150, rect
.right
);
3065 rect
.left
= LVIR_SELECTBOUNDS
;
3066 rect
.right
= rect
.top
= rect
.bottom
= -1;
3067 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3069 /* padding + 1 icon width, column width */
3070 expect(2 + 16, rect
.left
);
3071 expect(50, rect
.right
);
3074 rect
.left
= LVIR_LABEL
;
3075 rect
.right
= rect
.top
= rect
.bottom
= -1;
3076 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3078 /* padding + 2 icon widths, column width */
3079 expect(2 + 16*2, rect
.left
);
3080 expect(50, rect
.right
);
3083 rect
.left
= LVIR_ICON
;
3084 rect
.right
= rect
.top
= rect
.bottom
= -1;
3085 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3087 /* padding + 1 icon width indentation, icon width */
3088 expect(2 + 16, rect
.left
);
3089 expect(34, rect
.right
);
3092 DestroyWindow(hwnd
);
3095 static void test_editbox(void)
3097 HWND hwnd
, hwndedit
, hwndedit2
;
3100 static CHAR testitemA
[] = "testitem";
3101 static CHAR testitem1A
[] = "testitem1";
3102 static CHAR buffer
[10];
3104 hwnd
= create_listview_control(LVS_EDITLABELS
);
3105 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3107 insert_column(hwnd
, 0);
3109 memset(&item
, 0, sizeof(item
));
3110 item
.mask
= LVIF_TEXT
;
3111 item
.pszText
= testitemA
;
3114 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3117 /* setting focus is necessary */
3119 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3120 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3122 /* modify initial string */
3123 r
= SendMessage(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
3125 /* return focus to listview */
3128 memset(&item
, 0, sizeof(item
));
3129 item
.mask
= LVIF_TEXT
;
3130 item
.pszText
= buffer
;
3131 item
.cchTextMax
= 10;
3134 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3137 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
3139 /* send LVM_EDITLABEL on already created edit */
3141 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3142 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3143 /* focus will be set to edit */
3144 ok(GetFocus() == hwndedit
, "Expected Edit window to be focused\n");
3145 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3146 ok(IsWindow(hwndedit2
), "Expected Edit window to be created\n");
3148 /* creating label disabled when control isn't focused */
3150 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3151 todo_wine
ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
3153 /* check EN_KILLFOCUS handling */
3154 memset(&item
, 0, sizeof(item
));
3155 item
.pszText
= testitemA
;
3158 r
= SendMessage(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
3162 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3163 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3164 /* modify edit and notify control that it lost focus */
3165 r
= SendMessage(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
3167 r
= SendMessage(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
3169 memset(&item
, 0, sizeof(item
));
3170 item
.pszText
= buffer
;
3171 item
.cchTextMax
= 10;
3174 r
= SendMessage(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
3175 expect(lstrlen(item
.pszText
), r
);
3176 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
3177 /* end edit without saving */
3178 r
= SendMessage(hwndedit
, WM_KEYDOWN
, VK_ESCAPE
, 0);
3180 memset(&item
, 0, sizeof(item
));
3181 item
.pszText
= buffer
;
3182 item
.cchTextMax
= 10;
3185 r
= SendMessage(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
3186 expect(lstrlen(item
.pszText
), r
);
3187 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
3189 /* LVM_EDITLABEL with -1 destroys current edit */
3190 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_GETEDITCONTROL
, 0, 0);
3191 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
3192 /* no edit present */
3193 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, -1, 0);
3194 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
3195 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3196 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3198 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
3199 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, -1, 0);
3200 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
3201 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
3202 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
3203 /* check another negative value */
3204 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3205 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3206 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
3207 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, -2, 0);
3208 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
3209 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
3210 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
3211 /* and value greater than max item index */
3212 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3213 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3214 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
3215 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
3216 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, r
, 0);
3217 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
3218 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
3219 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
3221 /* messaging tests */
3223 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3225 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3226 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3227 /* testing only sizing messages */
3228 ok_sequence(sequences
, EDITBOX_SEQ_INDEX
, editbox_create_pos
,
3229 "edit box create - sizing", TRUE
);
3231 DestroyWindow(hwnd
);
3234 static void test_notifyformat(void)
3239 hwnd
= create_listview_control(0);
3240 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3242 /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
3243 CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
3244 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3246 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
3248 r
= SendMessage(hwnd
, LVM_SETUNICODEFORMAT
, 1, 0);
3250 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3253 r
= SendMessage(hwnd
, LVM_SETUNICODEFORMAT
, 0, 0);
3255 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3260 win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
3261 DestroyWindow(hwnd
);
3265 DestroyWindow(hwnd
);
3267 /* test failure in parent WM_NOTIFYFORMAT */
3269 hwnd
= create_listview_control(0);
3270 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3271 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3272 ok(IsWindow(header
), "expected header to be created\n");
3273 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3275 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3277 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
3278 ok(r
!= 0, "Expected valid format\n");
3280 notifyFormat
= NFR_UNICODE
;
3281 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
3282 expect(NFR_UNICODE
, r
);
3283 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3285 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3288 notifyFormat
= NFR_ANSI
;
3289 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
3290 expect(NFR_ANSI
, r
);
3291 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3293 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3296 DestroyWindow(hwnd
);
3298 /* try different unicode window combination and defaults */
3299 if (!GetModuleHandleW(NULL
))
3301 win_skip("Additional notify format tests are incompatible with Win9x\n");
3305 hwndparentW
= create_parent_window(TRUE
);
3306 ok(IsWindow(hwndparentW
), "Unicode parent creation failed\n");
3307 if (!IsWindow(hwndparentW
)) return;
3310 hwnd
= create_listview_controlW(0, hwndparentW
);
3311 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3312 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3313 ok(IsWindow(header
), "expected header to be created\n");
3314 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3316 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3318 DestroyWindow(hwnd
);
3319 /* receiving error code defaulting to ansi */
3321 hwnd
= create_listview_controlW(0, hwndparentW
);
3322 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3323 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3324 ok(IsWindow(header
), "expected header to be created\n");
3325 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3327 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3329 DestroyWindow(hwnd
);
3330 /* receiving ansi code from unicode window, use it */
3331 notifyFormat
= NFR_ANSI
;
3332 hwnd
= create_listview_controlW(0, hwndparentW
);
3333 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3334 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3335 ok(IsWindow(header
), "expected header to be created\n");
3336 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3338 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3340 DestroyWindow(hwnd
);
3341 /* unicode listview with ansi parent window */
3343 hwnd
= create_listview_controlW(0, hwndparent
);
3344 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3345 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3346 ok(IsWindow(header
), "expected header to be created\n");
3347 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3349 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3351 DestroyWindow(hwnd
);
3352 /* unicode listview with ansi parent window, return error code */
3354 hwnd
= create_listview_controlW(0, hwndparent
);
3355 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3356 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3357 ok(IsWindow(header
), "expected header to be created\n");
3358 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3360 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3362 DestroyWindow(hwnd
);
3364 DestroyWindow(hwndparentW
);
3367 static void test_indentation(void)
3373 hwnd
= create_listview_control(0);
3374 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3376 memset(&item
, 0, sizeof(item
));
3377 item
.mask
= LVIF_INDENT
;
3379 item
.iIndent
= I_INDENTCALLBACK
;
3380 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3383 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3386 item
.mask
= LVIF_INDENT
;
3387 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
3390 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
3391 "get indent dispinfo", FALSE
);
3393 DestroyWindow(hwnd
);
3396 static INT CALLBACK
DummyCompareEx(LPARAM first
, LPARAM second
, LPARAM param
)
3401 static BOOL
is_below_comctl_5(void)
3406 hwnd
= create_listview_control(0);
3407 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3408 insert_item(hwnd
, 0);
3410 ret
= SendMessage(hwnd
, LVM_SORTITEMSEX
, 0, (LPARAM
)&DummyCompareEx
);
3412 DestroyWindow(hwnd
);
3417 static void unload_v6_module(ULONG_PTR cookie
)
3420 BOOL (WINAPI
*pDeactivateActCtx
)(DWORD
, ULONG_PTR
);
3422 hKernel32
= GetModuleHandleA("kernel32.dll");
3423 pDeactivateActCtx
= (void*)GetProcAddress(hKernel32
, "DeactivateActCtx");
3424 if (!pDeactivateActCtx
)
3426 win_skip("Activation contexts unsupported\n");
3430 pDeactivateActCtx(0, cookie
);
3432 DeleteFileA(manifest_name
);
3435 static BOOL
load_v6_module(ULONG_PTR
*pcookie
)
3438 HANDLE (WINAPI
*pCreateActCtxA
)(ACTCTXA
*);
3439 BOOL (WINAPI
*pActivateActCtx
)(HANDLE
, ULONG_PTR
*);
3448 hKernel32
= GetModuleHandleA("kernel32.dll");
3449 pCreateActCtxA
= (void*)GetProcAddress(hKernel32
, "CreateActCtxA");
3450 pActivateActCtx
= (void*)GetProcAddress(hKernel32
, "ActivateActCtx");
3451 if (!(pCreateActCtxA
&& pActivateActCtx
))
3453 win_skip("Activation contexts unsupported. No version 6 tests possible.\n");
3457 /* create manifest */
3458 file
= CreateFileA( manifest_name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
3459 if (file
!= INVALID_HANDLE_VALUE
)
3461 ret
= (WriteFile( file
, manifest
, sizeof(manifest
)-1, &written
, NULL
) &&
3462 written
== sizeof(manifest
)-1);
3463 CloseHandle( file
);
3466 DeleteFileA( manifest_name
);
3467 skip("Failed to fill manifest file. Skipping comctl32 V6 tests.\n");
3471 trace("created %s\n", manifest_name
);
3475 skip("Failed to create manifest file. Skipping comctl32 V6 tests.\n");
3479 memset(&ctx
, 0, sizeof(ctx
));
3480 ctx
.cbSize
= sizeof(ctx
);
3481 ctx
.lpSource
= manifest_name
;
3483 hCtx
= pCreateActCtxA(&ctx
);
3484 ok(hCtx
!= 0, "Expected context handle\n");
3486 ret
= pActivateActCtx(hCtx
, pcookie
);
3491 win_skip("A problem during context activation occurred.\n");
3492 DeleteFileA(manifest_name
);
3497 /* this is a XP SP3 failure workaround */
3498 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
3499 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
,
3501 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
3502 if (!IsWindow(hwnd
))
3504 win_skip("FIXME: failed to create ListView window.\n");
3505 unload_v6_module(*pcookie
);
3509 DestroyWindow(hwnd
);
3515 static void test_get_set_view(void)
3521 /* test style->view mapping */
3522 hwnd
= create_listview_control(0);
3523 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3525 ret
= SendMessage(hwnd
, LVM_GETVIEW
, 0, 0);
3526 expect(LV_VIEW_DETAILS
, ret
);
3528 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3530 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
& ~LVS_REPORT
);
3531 ret
= SendMessage(hwnd
, LVM_GETVIEW
, 0, 0);
3532 expect(LV_VIEW_ICON
, ret
);
3534 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3535 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
| LVS_SMALLICON
);
3536 ret
= SendMessage(hwnd
, LVM_GETVIEW
, 0, 0);
3537 expect(LV_VIEW_SMALLICON
, ret
);
3539 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3540 SetWindowLongPtr(hwnd
, GWL_STYLE
, (style
& ~LVS_SMALLICON
) | LVS_LIST
);
3541 ret
= SendMessage(hwnd
, LVM_GETVIEW
, 0, 0);
3542 expect(LV_VIEW_LIST
, ret
);
3544 /* switching view doesn't touch window style */
3545 ret
= SendMessage(hwnd
, LVM_SETVIEW
, LV_VIEW_DETAILS
, 0);
3547 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3548 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
3549 ret
= SendMessage(hwnd
, LVM_SETVIEW
, LV_VIEW_ICON
, 0);
3551 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3552 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
3553 ret
= SendMessage(hwnd
, LVM_SETVIEW
, LV_VIEW_SMALLICON
, 0);
3555 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3556 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
3558 DestroyWindow(hwnd
);
3561 static void test_canceleditlabel(void)
3563 HWND hwnd
, hwndedit
;
3567 static CHAR test
[] = "test";
3568 static const CHAR test1
[] = "test1";
3570 hwnd
= create_listview_control(LVS_EDITLABELS
);
3571 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3573 insert_item(hwnd
, 0);
3575 /* try without edit created */
3576 ret
= SendMessage(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
3579 /* cancel without data change */
3581 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3582 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
3583 ret
= SendMessage(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
3585 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
3587 /* cancel after data change */
3588 memset(&itema
, 0, sizeof(itema
));
3589 itema
.pszText
= test
;
3590 ret
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0, (LPARAM
)&itema
);
3593 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3594 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
3595 ret
= SetWindowText(hwndedit
, test1
);
3596 ok(ret
!= 0, "Expected edit text to change\n");
3597 ret
= SendMessage(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
3599 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
3600 memset(&itema
, 0, sizeof(itema
));
3601 itema
.pszText
= buff
;
3602 itema
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
3603 ret
= SendMessage(hwnd
, LVM_GETITEMTEXT
, 0, (LPARAM
)&itema
);
3605 ok(strcmp(buff
, test1
) == 0, "Expected label text not to change\n");
3607 DestroyWindow(hwnd
);
3610 static void test_mapidindex(void)
3615 /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
3616 hwnd
= create_listview_control(LVS_OWNERDATA
);
3617 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3618 insert_item(hwnd
, 0);
3619 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
3621 DestroyWindow(hwnd
);
3623 hwnd
= create_listview_control(0);
3624 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3626 /* LVM_MAPINDEXTOID with invalid index */
3627 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
3630 insert_item(hwnd
, 0);
3631 insert_item(hwnd
, 1);
3633 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, -1, 0);
3635 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 2, 0);
3638 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
3640 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
3642 /* remove 0 indexed item, id retained */
3643 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
3644 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
3646 /* new id starts from previous value */
3647 insert_item(hwnd
, 1);
3648 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
3651 /* get index by id */
3652 ret
= SendMessage(hwnd
, LVM_MAPIDTOINDEX
, -1, 0);
3654 ret
= SendMessage(hwnd
, LVM_MAPIDTOINDEX
, 0, 0);
3656 ret
= SendMessage(hwnd
, LVM_MAPIDTOINDEX
, 1, 0);
3658 ret
= SendMessage(hwnd
, LVM_MAPIDTOINDEX
, 2, 0);
3661 DestroyWindow(hwnd
);
3664 START_TEST(listview
)
3667 BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
3669 ULONG_PTR ctx_cookie
;
3671 hComctl32
= GetModuleHandleA("comctl32.dll");
3672 pInitCommonControlsEx
= (void*)GetProcAddress(hComctl32
, "InitCommonControlsEx");
3673 if (pInitCommonControlsEx
)
3675 INITCOMMONCONTROLSEX iccex
;
3676 iccex
.dwSize
= sizeof(iccex
);
3677 iccex
.dwICC
= ICC_LISTVIEW_CLASSES
;
3678 pInitCommonControlsEx(&iccex
);
3681 InitCommonControls();
3683 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
3685 hwndparent
= create_parent_window(FALSE
);
3686 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3688 g_is_below_5
= is_below_comctl_5();
3696 test_icon_spacing();
3699 test_item_position();
3704 test_subitem_rect();
3708 test_nosortheader();
3712 test_getitemposition();
3713 test_columnscreation();
3715 test_notifyformat();
3718 if (!load_v6_module(&ctx_cookie
))
3720 DestroyWindow(hwndparent
);
3724 /* comctl32 version 6 tests start here */
3725 test_get_set_view();
3726 test_canceleditlabel();
3729 unload_v6_module(ctx_cookie
);
3731 DestroyWindow(hwndparent
);