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_parent_wnd_seq
[] = {
93 { WM_GETMINMAXINFO
, sent
},
94 { WM_NCCREATE
, sent
},
95 { WM_NCCALCSIZE
, sent
|wparam
, 0 },
97 { WM_SHOWWINDOW
, sent
|wparam
, 1 },
98 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
99 { WM_QUERYNEWPALETTE
, sent
|optional
},
100 { WM_WINDOWPOSCHANGING
, sent
|wparam
, 0 },
101 { WM_WINDOWPOSCHANGED
, sent
|optional
},
102 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
103 { WM_ACTIVATEAPP
, sent
|wparam
, 1 },
104 { WM_NCACTIVATE
, sent
|wparam
, 1 },
105 { WM_ACTIVATE
, sent
|wparam
, 1 },
106 { WM_IME_SETCONTEXT
, sent
|wparam
|defwinproc
|optional
, 1 },
107 { WM_IME_NOTIFY
, sent
|defwinproc
|optional
},
108 { WM_SETFOCUS
, sent
|wparam
|defwinproc
, 0 },
109 /* Win9x adds SWP_NOZORDER below */
110 { WM_WINDOWPOSCHANGED
, sent
, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
111 { WM_NCCALCSIZE
, sent
|wparam
|optional
, 1 },
117 static const struct message create_ownerdrawfixed_parent_seq
[] = {
118 { WM_NOTIFYFORMAT
, sent
},
119 { WM_QUERYUISTATE
, sent
|optional
}, /* Win2K and higher */
120 { WM_MEASUREITEM
, sent
},
121 { WM_PARENTNOTIFY
, sent
},
125 static const struct message redraw_listview_seq
[] = {
126 { WM_PAINT
, sent
|id
, 0, 0, LISTVIEW_ID
},
127 { WM_PAINT
, sent
|id
, 0, 0, HEADER_ID
},
128 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
129 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, HEADER_ID
},
130 { WM_NOTIFY
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
131 { WM_NCPAINT
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
132 { WM_ERASEBKGND
, sent
|id
|defwinproc
, 0, 0, LISTVIEW_ID
},
136 static const struct message listview_icon_spacing_seq
[] = {
137 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(20, 30) },
138 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(25, 35) },
139 { LVM_SETICONSPACING
, sent
|lparam
, 0, MAKELPARAM(-1, -1) },
143 static const struct message listview_color_seq
[] = {
144 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
145 { LVM_GETBKCOLOR
, sent
},
146 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
147 { LVM_GETTEXTCOLOR
, sent
},
148 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(0,0,0) },
149 { LVM_GETTEXTBKCOLOR
, sent
},
151 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
152 { LVM_GETBKCOLOR
, sent
},
153 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
154 { LVM_GETTEXTCOLOR
, sent
},
155 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(100,50,200) },
156 { LVM_GETTEXTBKCOLOR
, sent
},
158 { LVM_SETBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
159 { LVM_GETBKCOLOR
, sent
},
160 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, CLR_NONE
},
161 { LVM_GETTEXTCOLOR
, sent
},
162 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, CLR_NONE
},
163 { LVM_GETTEXTBKCOLOR
, sent
},
165 { LVM_SETBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
166 { LVM_GETBKCOLOR
, sent
},
167 { LVM_SETTEXTCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
168 { LVM_GETTEXTCOLOR
, sent
},
169 { LVM_SETTEXTBKCOLOR
, sent
|lparam
, 0, RGB(255,255,255) },
170 { LVM_GETTEXTBKCOLOR
, sent
},
174 static const struct message listview_item_count_seq
[] = {
175 { LVM_GETITEMCOUNT
, sent
},
176 { LVM_INSERTITEM
, sent
},
177 { LVM_INSERTITEM
, sent
},
178 { LVM_INSERTITEM
, sent
},
179 { LVM_GETITEMCOUNT
, sent
},
180 { LVM_DELETEITEM
, sent
|wparam
, 2 },
181 { LVM_GETITEMCOUNT
, sent
},
182 { LVM_DELETEALLITEMS
, sent
},
183 { LVM_GETITEMCOUNT
, sent
},
184 { LVM_INSERTITEM
, sent
},
185 { LVM_INSERTITEM
, sent
},
186 { LVM_GETITEMCOUNT
, sent
},
187 { LVM_INSERTITEM
, sent
},
188 { LVM_GETITEMCOUNT
, sent
},
192 static const struct message listview_itempos_seq
[] = {
193 { LVM_INSERTITEM
, sent
},
194 { LVM_INSERTITEM
, sent
},
195 { LVM_INSERTITEM
, sent
},
196 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 1, MAKELPARAM(10,5) },
197 { LVM_GETITEMPOSITION
, sent
|wparam
, 1 },
198 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 2, MAKELPARAM(0,0) },
199 { LVM_GETITEMPOSITION
, sent
|wparam
, 2 },
200 { LVM_SETITEMPOSITION
, sent
|wparam
|lparam
, 0, MAKELPARAM(20,20) },
201 { LVM_GETITEMPOSITION
, sent
|wparam
, 0 },
205 static const struct message listview_ownerdata_switchto_seq
[] = {
206 { WM_STYLECHANGING
, sent
},
207 { WM_STYLECHANGED
, sent
},
211 static const struct message listview_getorderarray_seq
[] = {
212 { LVM_GETCOLUMNORDERARRAY
, sent
|id
|wparam
, 2, 0, LISTVIEW_ID
},
213 { HDM_GETORDERARRAY
, sent
|id
|wparam
, 2, 0, HEADER_ID
},
217 static const struct message empty_seq
[] = {
221 static const struct message forward_erasebkgnd_parent_seq
[] = {
222 { WM_ERASEBKGND
, sent
},
226 static const struct message ownderdata_select_focus_parent_seq
[] = {
227 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
228 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
232 static const struct message textcallback_set_again_parent_seq
[] = {
233 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGING
},
234 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_ITEMCHANGED
},
238 static const struct message single_getdispinfo_parent_seq
[] = {
239 { WM_NOTIFY
, sent
|id
, 0, 0, LVN_GETDISPINFOA
},
243 static const struct message getitemposition_seq1
[] = {
244 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
248 static const struct message getitemposition_seq2
[] = {
249 { LVM_GETITEMPOSITION
, sent
|id
, 0, 0, LISTVIEW_ID
},
250 { HDM_GETITEMRECT
, sent
|id
, 0, 0, HEADER_ID
},
254 static const struct message editbox_create_pos
[] = {
255 /* sequence sent after LVN_BEGINLABELEDIT */
256 { WM_WINDOWPOSCHANGING
, sent
},
257 { WM_NCCALCSIZE
, sent
},
258 { WM_WINDOWPOSCHANGED
, sent
},
259 { WM_MOVE
, sent
|defwinproc
},
260 { WM_SIZE
, sent
|defwinproc
},
261 /* the rest is todo */
262 { WM_WINDOWPOSCHANGING
, sent
},
263 { WM_WINDOWPOSCHANGED
, sent
},
272 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
274 static LONG defwndproc_counter
= 0;
278 msg
.message
= message
;
279 msg
.flags
= sent
|wparam
|lparam
;
280 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
283 if (message
== WM_NOTIFY
&& lParam
) msg
.id
= ((NMHDR
*)lParam
)->code
;
285 /* log system messages, except for painting */
286 if (message
< WM_USER
&&
287 message
!= WM_PAINT
&&
288 message
!= WM_ERASEBKGND
&&
289 message
!= WM_NCPAINT
&&
290 message
!= WM_NCHITTEST
&&
291 message
!= WM_GETTEXT
&&
292 message
!= WM_GETICON
&&
293 message
!= WM_DEVICECHANGE
)
295 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
297 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
299 add_message(sequences
, PARENT_FULL_SEQ_INDEX
, &msg
);
305 switch (((NMHDR
*)lParam
)->code
)
307 case LVN_BEGINLABELEDIT
:
308 /* subclass edit box */
310 subclass_editbox(((NMHDR
*)lParam
)->hwndFrom
);
314 case LVN_ENDLABELEDIT
:
315 /* always accept new item text */
320 case WM_NOTIFYFORMAT
:
322 /* force to return format */
323 if (lParam
== NF_QUERY
&& notifyFormat
!= -1) return notifyFormat
;
328 defwndproc_counter
++;
329 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
330 defwndproc_counter
--;
335 static BOOL
register_parent_wnd_class(BOOL Unicode
)
343 clsW
.lpfnWndProc
= parent_wnd_proc
;
346 clsW
.hInstance
= GetModuleHandleW(NULL
);
348 clsW
.hCursor
= LoadCursorA(0, IDC_ARROW
);
349 clsW
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
350 clsW
.lpszMenuName
= NULL
;
351 clsW
.lpszClassName
= testparentclassW
;
356 clsA
.lpfnWndProc
= parent_wnd_proc
;
359 clsA
.hInstance
= GetModuleHandleA(NULL
);
361 clsA
.hCursor
= LoadCursorA(0, IDC_ARROW
);
362 clsA
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
363 clsA
.lpszMenuName
= NULL
;
364 clsA
.lpszClassName
= "Listview test parent class";
367 return Unicode
? RegisterClassW(&clsW
) : RegisterClassA(&clsA
);
370 static HWND
create_parent_window(BOOL Unicode
)
372 static const WCHAR nameW
[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W'};
374 if (!register_parent_wnd_class(Unicode
))
381 return CreateWindowExW(0, testparentclassW
, nameW
,
382 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
383 WS_MAXIMIZEBOX
| WS_VISIBLE
,
385 GetDesktopWindow(), NULL
, GetModuleHandleW(NULL
), NULL
);
387 return CreateWindowExA(0, "Listview test parent class",
388 "Listview test parent window",
389 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
390 WS_MAXIMIZEBOX
| WS_VISIBLE
,
392 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
395 static LRESULT WINAPI
listview_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
397 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
398 static LONG defwndproc_counter
= 0;
402 trace("listview: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
404 /* some debug output for style changing */
405 if ((message
== WM_STYLECHANGING
||
406 message
== WM_STYLECHANGED
) && lParam
)
408 STYLESTRUCT
*style
= (STYLESTRUCT
*)lParam
;
409 trace("\told style: 0x%08x, new style: 0x%08x\n", style
->styleOld
, style
->styleNew
);
412 msg
.message
= message
;
413 msg
.flags
= sent
|wparam
|lparam
;
414 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
417 msg
.id
= LISTVIEW_ID
;
418 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
420 defwndproc_counter
++;
421 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
422 defwndproc_counter
--;
426 static HWND
create_listview_control(DWORD style
)
428 struct subclass_info
*info
;
432 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
436 GetClientRect(hwndparent
, &rect
);
437 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
438 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
| style
,
439 0, 0, rect
.right
, rect
.bottom
,
440 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
441 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
445 HeapFree(GetProcessHeap(), 0, info
);
449 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
450 (LONG_PTR
)listview_subclass_proc
);
451 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
456 /* unicode listview window with specified parent */
457 static HWND
create_listview_controlW(DWORD style
, HWND parent
)
459 struct subclass_info
*info
;
462 static const WCHAR nameW
[] = {'f','o','o',0};
464 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
468 GetClientRect(parent
, &rect
);
469 hwnd
= CreateWindowExW(0, WC_LISTVIEWW
, nameW
,
470 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
| style
,
471 0, 0, rect
.right
, rect
.bottom
,
472 parent
, NULL
, GetModuleHandleW(NULL
), NULL
);
473 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
477 HeapFree(GetProcessHeap(), 0, info
);
481 info
->oldproc
= (WNDPROC
)SetWindowLongPtrW(hwnd
, GWLP_WNDPROC
,
482 (LONG_PTR
)listview_subclass_proc
);
483 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
488 static HWND
create_custom_listview_control(DWORD style
)
490 struct subclass_info
*info
;
494 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
498 GetClientRect(hwndparent
, &rect
);
499 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
500 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| style
,
501 0, 0, rect
.right
, rect
.bottom
,
502 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
503 ok(hwnd
!= NULL
, "gle=%d\n", GetLastError());
507 HeapFree(GetProcessHeap(), 0, info
);
511 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
512 (LONG_PTR
)listview_subclass_proc
);
513 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
518 static LRESULT WINAPI
header_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
520 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
521 static LONG defwndproc_counter
= 0;
525 trace("header: %p, %04x, %08lx, %08lx\n", hwnd
, message
, wParam
, lParam
);
527 msg
.message
= message
;
528 msg
.flags
= sent
|wparam
|lparam
;
529 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
533 add_message(sequences
, LISTVIEW_SEQ_INDEX
, &msg
);
535 defwndproc_counter
++;
536 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
537 defwndproc_counter
--;
541 static HWND
subclass_header(HWND hwndListview
)
543 struct subclass_info
*info
;
546 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
550 hwnd
= ListView_GetHeader(hwndListview
);
551 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
552 (LONG_PTR
)header_subclass_proc
);
553 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
558 static LRESULT WINAPI
editbox_subclass_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
560 struct subclass_info
*info
= (struct subclass_info
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
561 static LONG defwndproc_counter
= 0;
565 msg
.message
= message
;
566 msg
.flags
= sent
|wparam
|lparam
;
567 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
571 /* all we need is sizing */
572 if (message
== WM_WINDOWPOSCHANGING
||
573 message
== WM_NCCALCSIZE
||
574 message
== WM_WINDOWPOSCHANGED
||
575 message
== WM_MOVE
||
578 add_message(sequences
, EDITBOX_SEQ_INDEX
, &msg
);
581 defwndproc_counter
++;
582 ret
= CallWindowProcA(info
->oldproc
, hwnd
, message
, wParam
, lParam
);
583 defwndproc_counter
--;
587 static HWND
subclass_editbox(HWND hwndListview
)
589 struct subclass_info
*info
;
592 info
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info
));
596 hwnd
= (HWND
)SendMessage(hwndListview
, LVM_GETEDITCONTROL
, 0, 0);
597 info
->oldproc
= (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
598 (LONG_PTR
)editbox_subclass_proc
);
599 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
604 /* Performs a single LVM_HITTEST test */
605 static void test_lvm_hittest(HWND hwnd
, INT x
, INT y
, INT item
, UINT flags
,
606 BOOL todo_item
, BOOL todo_flags
, int line
)
615 trace("hittesting pt=(%d,%d)\n", lpht
.pt
.x
, lpht
.pt
.y
);
616 ret
= SendMessage(hwnd
, LVM_HITTEST
, 0, (LPARAM
)&lpht
);
622 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
623 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
624 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
629 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
630 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
631 ok_(__FILE__
, line
)(lpht
.iSubItem
== 10, "Expected subitem not overwrited\n");
637 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
640 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
643 /* Performs a single LVM_SUBITEMHITTEST test */
644 static void test_lvm_subitemhittest(HWND hwnd
, INT x
, INT y
, INT item
, INT subitem
, UINT flags
,
645 BOOL todo_item
, BOOL todo_subitem
, BOOL todo_flags
, int line
)
653 trace("subhittesting pt=(%d,%d)\n", lpht
.pt
.x
, lpht
.pt
.y
);
654 ret
= SendMessage(hwnd
, LVM_SUBITEMHITTEST
, 0, (LPARAM
)&lpht
);
660 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
661 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
666 ok_(__FILE__
, line
)(ret
== item
, "Expected %d item, got %d\n", item
, ret
);
667 ok_(__FILE__
, line
)(lpht
.iItem
== item
, "Expected %d item, got %d\n", item
, lpht
.iItem
);
673 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
676 ok_(__FILE__
, line
)(lpht
.iSubItem
== subitem
, "Expected subitem %d, got %d\n", subitem
, lpht
.iSubItem
);
681 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
684 ok_(__FILE__
, line
)(lpht
.flags
== flags
, "Expected flags %x, got %x\n", flags
, lpht
.flags
);
687 static void test_images(void)
695 static CHAR hello
[] = "hello";
697 himl
= ImageList_Create(40, 40, 0, 4, 4);
698 ok(himl
!= NULL
, "failed to create imagelist\n");
700 hbmp
= CreateBitmap(40, 40, 1, 1, NULL
);
701 ok(hbmp
!= NULL
, "failed to create bitmap\n");
703 r
= ImageList_Add(himl
, hbmp
, 0);
704 ok(r
== 0, "should be zero\n");
706 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED
,
707 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
708 ok(hwnd
!= NULL
, "failed to create listview window\n");
710 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0,
711 LVS_EX_UNDERLINEHOT
| LVS_EX_FLATSB
| LVS_EX_ONECLICKACTIVATE
);
713 ok(r
== 0, "should return zero\n");
715 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)himl
);
716 ok(r
== 0, "should return zero\n");
718 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELONG(100,50));
719 /* returns dimensions */
721 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
722 ok(r
== 0, "should be zero items\n");
724 item
.mask
= LVIF_IMAGE
| LVIF_TEXT
;
729 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
730 ok(r
== -1, "should fail\n");
733 item
.pszText
= hello
;
734 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
735 ok(r
== 0, "should not fail\n");
737 memset(&r1
, 0, sizeof r1
);
739 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r1
);
741 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
742 ok(r
== TRUE
, "should not fail\n");
745 item
.pszText
= hello
;
746 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
747 ok(r
== 0, "should not fail\n");
749 memset(&r2
, 0, sizeof r2
);
751 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
) &r2
);
753 ok(!memcmp(&r1
, &r2
, sizeof r1
), "rectangle should be the same\n");
758 static void test_checkboxes(void)
763 static CHAR text
[] = "Text",
767 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
768 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
769 ok(hwnd
!= NULL
, "failed to create listview window\n");
771 /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
772 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
773 item
.stateMask
= 0xffff;
778 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
779 ok(r
== 0, "ret %d\n", r
);
782 item
.mask
= LVIF_STATE
;
783 item
.stateMask
= 0xffff;
784 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
785 ok(item
.state
== 0xfccc, "state %x\n", item
.state
);
787 /* Don't set LVIF_STATE */
788 item
.mask
= LVIF_TEXT
;
789 item
.stateMask
= 0xffff;
794 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
795 ok(r
== 1, "ret %d\n", r
);
798 item
.mask
= LVIF_STATE
;
799 item
.stateMask
= 0xffff;
800 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
801 ok(item
.state
== 0, "state %x\n", item
.state
);
803 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
804 ok(r
== 0, "should return zero\n");
806 /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
808 item
.mask
= LVIF_STATE
;
809 item
.stateMask
= 0xffff;
810 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
811 ok(item
.state
== 0x1ccc, "state %x\n", item
.state
);
813 /* Now add an item without specifying a state and check that its state goes to 0x1000 */
815 item
.mask
= LVIF_TEXT
;
817 item
.pszText
= text2
;
818 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
819 ok(r
== 2, "ret %d\n", r
);
822 item
.mask
= LVIF_STATE
;
823 item
.stateMask
= 0xffff;
824 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
825 ok(item
.state
== 0x1000, "state %x\n", item
.state
);
827 /* Add a further item this time specifying a state and still its state goes to 0x1000 */
829 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
830 item
.stateMask
= 0xffff;
832 item
.pszText
= text3
;
833 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
834 ok(r
== 3, "ret %d\n", r
);
837 item
.mask
= LVIF_STATE
;
838 item
.stateMask
= 0xffff;
839 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
840 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
842 /* Set an item's state to checked */
844 item
.mask
= LVIF_STATE
;
845 item
.stateMask
= 0xf000;
847 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
850 item
.mask
= LVIF_STATE
;
851 item
.stateMask
= 0xffff;
852 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
853 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
855 /* Check that only the bits we asked for are returned,
856 * and that all the others are set to zero
859 item
.mask
= LVIF_STATE
;
860 item
.stateMask
= 0xf000;
862 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
863 ok(item
.state
== 0x2000, "state %x\n", item
.state
);
865 /* Set the style again and check that doesn't change an item's state */
866 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
867 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
870 item
.mask
= LVIF_STATE
;
871 item
.stateMask
= 0xffff;
872 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
873 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
875 /* Unsetting the checkbox extended style doesn't change an item's state */
876 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, 0);
877 ok(r
== LVS_EX_CHECKBOXES
, "ret %x\n", r
);
880 item
.mask
= LVIF_STATE
;
881 item
.stateMask
= 0xffff;
882 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
883 ok(item
.state
== 0x2aaa, "state %x\n", item
.state
);
885 /* Now setting the style again will change an item's state */
886 r
= SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_CHECKBOXES
, LVS_EX_CHECKBOXES
);
887 ok(r
== 0, "ret %x\n", r
);
890 item
.mask
= LVIF_STATE
;
891 item
.stateMask
= 0xffff;
892 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
893 ok(item
.state
== 0x1aaa, "state %x\n", item
.state
);
895 /* Toggle checkbox tests (bug 9934) */
896 memset (&item
, 0xcc, sizeof(item
));
897 item
.mask
= LVIF_STATE
;
900 item
.state
= LVIS_FOCUSED
;
901 item
.stateMask
= LVIS_FOCUSED
;
902 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
906 item
.mask
= LVIF_STATE
;
907 item
.stateMask
= 0xffff;
908 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
909 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
911 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
913 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
917 item
.mask
= LVIF_STATE
;
918 item
.stateMask
= 0xffff;
919 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
920 ok(item
.state
== 0x2aab, "state %x\n", item
.state
);
922 r
= SendMessage(hwnd
, WM_KEYDOWN
, VK_SPACE
, 0);
924 r
= SendMessage(hwnd
, WM_KEYUP
, VK_SPACE
, 0);
928 item
.mask
= LVIF_STATE
;
929 item
.stateMask
= 0xffff;
930 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
931 ok(item
.state
== 0x1aab, "state %x\n", item
.state
);
936 static void insert_column(HWND hwnd
, int idx
)
941 memset(&column
, 0xcc, sizeof(column
));
942 column
.mask
= LVCF_SUBITEM
;
943 column
.iSubItem
= idx
;
945 rc
= ListView_InsertColumn(hwnd
, idx
, &column
);
949 static void insert_item(HWND hwnd
, int idx
)
951 static CHAR text
[] = "foo";
956 memset(&item
, 0xcc, sizeof (item
));
957 item
.mask
= LVIF_TEXT
;
962 rc
= ListView_InsertItem(hwnd
, &item
);
966 static void test_items(void)
968 const LPARAM lparamTest
= 0x42;
972 static CHAR text
[] = "Text";
974 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
975 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
976 ok(hwnd
!= NULL
, "failed to create listview window\n");
979 * Test setting/getting item params
982 /* Set up two columns */
983 insert_column(hwnd
, 0);
984 insert_column(hwnd
, 1);
986 /* LVIS_SELECTED with zero stateMask */
988 memset (&item
, 0, sizeof (item
));
989 item
.mask
= LVIF_STATE
;
990 item
.state
= LVIS_SELECTED
;
994 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
995 ok(r
== 0, "ret %d\n", r
);
997 memset (&item
, 0xcc, sizeof (item
));
998 item
.mask
= LVIF_STATE
;
999 item
.stateMask
= LVIS_SELECTED
;
1003 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1004 ok(r
!= 0, "ret %d\n", r
);
1005 ok(item
.state
& LVIS_SELECTED
, "Expected LVIS_SELECTED\n");
1006 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
1008 /* LVIS_SELECTED with zero stateMask */
1010 memset (&item
, 0, sizeof (item
));
1011 item
.mask
= LVIF_STATE
;
1012 item
.state
= LVIS_FOCUSED
;
1016 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1017 ok(r
== 0, "ret %d\n", r
);
1019 memset (&item
, 0xcc, sizeof (item
));
1020 item
.mask
= LVIF_STATE
;
1021 item
.stateMask
= LVIS_FOCUSED
;
1025 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1026 ok(r
!= 0, "ret %d\n", r
);
1027 ok(item
.state
& LVIS_FOCUSED
, "Expected LVIS_FOCUSED\n");
1028 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
1030 /* LVIS_CUT with LVIS_FOCUSED stateMask */
1032 memset (&item
, 0, sizeof (item
));
1033 item
.mask
= LVIF_STATE
;
1034 item
.state
= LVIS_CUT
;
1035 item
.stateMask
= LVIS_FOCUSED
;
1038 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1039 ok(r
== 0, "ret %d\n", r
);
1041 memset (&item
, 0xcc, sizeof (item
));
1042 item
.mask
= LVIF_STATE
;
1043 item
.stateMask
= LVIS_CUT
;
1047 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1048 ok(r
!= 0, "ret %d\n", r
);
1049 ok(item
.state
& LVIS_CUT
, "Expected LVIS_CUT\n");
1050 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
1052 /* Insert an item with just a param */
1053 memset (&item
, 0xcc, sizeof (item
));
1054 item
.mask
= LVIF_PARAM
;
1057 item
.lParam
= lparamTest
;
1058 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1059 ok(r
== 0, "ret %d\n", r
);
1061 /* Test getting of the param */
1062 memset (&item
, 0xcc, sizeof (item
));
1063 item
.mask
= LVIF_PARAM
;
1066 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1067 ok(r
!= 0, "ret %d\n", r
);
1068 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1070 /* Set up a subitem */
1071 memset (&item
, 0xcc, sizeof (item
));
1072 item
.mask
= LVIF_TEXT
;
1075 item
.pszText
= text
;
1076 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1077 ok(r
!= 0, "ret %d\n", r
);
1079 /* Query param from subitem: returns main item param */
1080 memset (&item
, 0xcc, sizeof (item
));
1081 item
.mask
= LVIF_PARAM
;
1084 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1085 ok(r
!= 0, "ret %d\n", r
);
1086 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1088 /* Set up param on first subitem: no effect */
1089 memset (&item
, 0xcc, sizeof (item
));
1090 item
.mask
= LVIF_PARAM
;
1093 item
.lParam
= lparamTest
+1;
1094 r
= SendMessage(hwnd
, LVM_SETITEMA
, 0, (LPARAM
) &item
);
1095 ok(r
== 0, "ret %d\n", r
);
1097 /* Query param from subitem again: should still return main item param */
1098 memset (&item
, 0xcc, sizeof (item
));
1099 item
.mask
= LVIF_PARAM
;
1102 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1103 ok(r
!= 0, "ret %d\n", r
);
1104 ok(item
.lParam
== lparamTest
, "got lParam %lx, expected %lx\n", item
.lParam
, lparamTest
);
1106 /**** Some tests of state highlighting ****/
1107 memset (&item
, 0xcc, sizeof (item
));
1108 item
.mask
= LVIF_STATE
;
1111 item
.state
= LVIS_SELECTED
;
1112 item
.stateMask
= LVIS_SELECTED
| LVIS_DROPHILITED
;
1113 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
1114 ok(r
!= 0, "ret %d\n", r
);
1116 item
.state
= LVIS_DROPHILITED
;
1117 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
) &item
);
1118 ok(r
!= 0, "ret %d\n", r
);
1120 memset (&item
, 0xcc, sizeof (item
));
1121 item
.mask
= LVIF_STATE
;
1124 item
.stateMask
= -1;
1125 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1126 ok(r
!= 0, "ret %d\n", r
);
1127 ok(item
.state
== LVIS_SELECTED
, "got state %x, expected %x\n", item
.state
, LVIS_SELECTED
);
1129 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
1130 ok(r
!= 0, "ret %d\n", r
);
1131 todo_wine
ok(item
.state
== LVIS_DROPHILITED
, "got state %x, expected %x\n", item
.state
, LVIS_DROPHILITED
);
1133 /* some notnull but meaningless masks */
1134 memset (&item
, 0, sizeof(item
));
1135 item
.mask
= LVIF_NORECOMPUTE
;
1138 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1139 ok(r
!= 0, "ret %d\n", r
);
1140 memset (&item
, 0, sizeof(item
));
1141 item
.mask
= LVIF_DI_SETITEM
;
1144 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1145 ok(r
!= 0, "ret %d\n", r
);
1147 /* set text to callback value already having it */
1148 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1150 memset (&item
, 0, sizeof (item
));
1151 item
.mask
= LVIF_TEXT
;
1152 item
.pszText
= LPSTR_TEXTCALLBACK
;
1154 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
) &item
);
1155 ok(r
== 0, "ret %d\n", r
);
1156 memset (&item
, 0, sizeof (item
));
1158 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1160 item
.pszText
= LPSTR_TEXTCALLBACK
;
1161 r
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0 , (LPARAM
) &item
);
1164 ok_sequence(sequences
, PARENT_SEQ_INDEX
, textcallback_set_again_parent_seq
,
1165 "check callback text comparison rule", FALSE
);
1167 DestroyWindow(hwnd
);
1170 static void test_columns(void)
1172 HWND hwnd
, hwndheader
;
1177 hwnd
= CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT
,
1178 10, 10, 100, 200, hwndparent
, NULL
, NULL
, NULL
);
1179 ok(hwnd
!= NULL
, "failed to create listview window\n");
1181 /* Add a column with no mask */
1182 memset(&column
, 0xcc, sizeof(column
));
1184 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
1185 ok(rc
==0, "Inserting column with no mask failed with %d\n", rc
);
1187 /* Check its width */
1188 rc
= ListView_GetColumnWidth(hwnd
, 0);
1190 broken(rc
==0), /* win9x */
1191 "Inserting column with no mask failed to set width to 10 with %d\n", rc
);
1193 DestroyWindow(hwnd
);
1195 /* LVM_GETCOLUMNORDERARRAY */
1196 hwnd
= create_listview_control(0);
1197 hwndheader
= subclass_header(hwnd
);
1199 memset(&column
, 0, sizeof(column
));
1200 column
.mask
= LVCF_WIDTH
;
1202 rc
= ListView_InsertColumn(hwnd
, 0, &column
);
1203 ok(rc
== 0, "Inserting column failed with %d\n", rc
);
1206 rc
= ListView_InsertColumn(hwnd
, 1, &column
);
1207 ok(rc
== 1, "Inserting column failed with %d\n", rc
);
1209 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1211 rc
= SendMessage(hwnd
, LVM_GETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
1212 ok(rc
!= 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
1213 ok(order
[0] == 0, "Expected order 0, got %d\n", order
[0]);
1214 ok(order
[1] == 1, "Expected order 1, got %d\n", order
[1]);
1216 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_getorderarray_seq
, "get order array", FALSE
);
1218 DestroyWindow(hwnd
);
1220 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1221 static WNDPROC listviewWndProc
;
1222 static HIMAGELIST test_create_imagelist
;
1224 static LRESULT CALLBACK
create_test_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1228 if (uMsg
== WM_CREATE
)
1230 LPCREATESTRUCT lpcs
= (LPCREATESTRUCT
)lParam
;
1231 lpcs
->style
|= LVS_REPORT
;
1233 ret
= CallWindowProc(listviewWndProc
, hwnd
, uMsg
, wParam
, lParam
);
1234 if (uMsg
== WM_CREATE
) SendMessage(hwnd
, LVM_SETIMAGELIST
, 0, (LPARAM
)test_create_imagelist
);
1238 static void test_create(void)
1247 cls
.cbSize
= sizeof(WNDCLASSEX
);
1248 ok(GetClassInfoEx(GetModuleHandle(NULL
), "SysListView32", &cls
), "GetClassInfoEx failed\n");
1249 listviewWndProc
= cls
.lpfnWndProc
;
1250 cls
.lpfnWndProc
= create_test_wndproc
;
1251 cls
.lpszClassName
= "MyListView32";
1252 ok(RegisterClassEx(&cls
), "RegisterClassEx failed\n");
1254 test_create_imagelist
= ImageList_Create(16, 16, 0, 5, 10);
1255 hList
= CreateWindow("MyListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
1256 ok((HIMAGELIST
)SendMessage(hList
, LVM_GETIMAGELIST
, 0, 0) == test_create_imagelist
, "Image list not obtained\n");
1257 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1258 ok(IsWindow(hHeader
) && IsWindowVisible(hHeader
), "Listview not in report mode\n");
1259 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1260 DestroyWindow(hList
);
1262 /* header isn't created on LVS_ICON and LVS_LIST styles */
1263 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1264 GetModuleHandle(NULL
), 0);
1265 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1266 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1267 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1269 memset(&col
, 0, sizeof(LVCOLUMNA
));
1270 col
.mask
= LVCF_WIDTH
;
1272 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1273 ok(r
== 0, "Expected 0 column's inserted\n");
1274 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1275 ok(IsWindow(hHeader
), "Header should be created\n");
1276 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1277 DestroyWindow(hList
);
1279 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1280 GetModuleHandle(NULL
), 0);
1281 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1282 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1283 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1285 memset(&col
, 0, sizeof(LVCOLUMNA
));
1286 col
.mask
= LVCF_WIDTH
;
1288 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1289 ok(r
== 0, "Expected 0 column's inserted\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 DestroyWindow(hList
);
1295 /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1296 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
, 0, 0, 100, 100, NULL
, NULL
,
1297 GetModuleHandle(NULL
), 0);
1298 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLongPtr(hList
, GWL_STYLE
) | LVS_REPORT
);
1299 ok(ret
& WS_VISIBLE
, "Style wrong, should have WS_VISIBLE\n");
1300 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1301 ok(IsWindow(hHeader
), "Header should be created\n");
1302 ret
= SetWindowLongPtr(hList
, GWL_STYLE
, GetWindowLong(hList
, GWL_STYLE
) & ~LVS_REPORT
);
1303 ok((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1304 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1305 ok(IsWindow(hHeader
), "Header should be created\n");
1306 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1307 DestroyWindow(hList
);
1309 /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1310 hList
= CreateWindow("SysListView32", "Test", WS_VISIBLE
|LVS_LIST
, 0, 0, 100, 100, NULL
, NULL
,
1311 GetModuleHandle(NULL
), 0);
1312 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
1313 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_LIST
) | LVS_REPORT
);
1314 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_LIST
)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1315 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1316 ok(IsWindow(hHeader
), "Header should be created\n");
1317 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1318 ret
= SetWindowLongPtr(hList
, GWL_STYLE
,
1319 (GetWindowLongPtr(hList
, GWL_STYLE
) & ~LVS_REPORT
) | LVS_LIST
);
1320 ok(((ret
& WS_VISIBLE
) && (ret
& LVS_REPORT
)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1321 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1322 ok(IsWindow(hHeader
), "Header should be created\n");
1323 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1324 DestroyWindow(hList
);
1326 /* LVS_REPORT without WS_VISIBLE */
1327 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1328 GetModuleHandle(NULL
), 0);
1329 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1330 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1331 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1333 memset(&col
, 0, sizeof(LVCOLUMNA
));
1334 col
.mask
= LVCF_WIDTH
;
1336 r
= SendMessage(hList
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
1337 ok(r
== 0, "Expected 0 column's inserted\n");
1338 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1339 ok(IsWindow(hHeader
), "Header should be created\n");
1340 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1341 DestroyWindow(hList
);
1343 /* LVS_REPORT without WS_VISIBLE, try to show it */
1344 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1345 GetModuleHandle(NULL
), 0);
1346 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1347 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1348 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1349 ShowWindow(hList
, SW_SHOW
);
1350 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1351 ok(IsWindow(hHeader
), "Header should be created\n");
1352 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1353 DestroyWindow(hList
);
1355 /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1356 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
|LVS_NOCOLUMNHEADER
|WS_VISIBLE
,
1357 0, 0, 100, 100, NULL
, NULL
, GetModuleHandle(NULL
), 0);
1358 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1359 ok(IsWindow(hHeader
), "Header should be created\n");
1360 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1361 /* HDS_DRAGDROP set by default */
1362 ok(GetWindowLongPtr(hHeader
, GWL_STYLE
) & HDS_DRAGDROP
, "Expected header to have HDS_DRAGDROP\n");
1363 DestroyWindow(hList
);
1365 /* setting LVS_EX_HEADERDRAGDROP creates header */
1366 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1367 GetModuleHandle(NULL
), 0);
1368 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1369 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1370 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1371 SendMessage(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1372 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1373 ok(IsWindow(hHeader
) ||
1374 broken(!IsWindow(hHeader
)), /* 4.7x common controls */
1375 "Header should be created\n");
1376 ok(hHeader
== GetDlgItem(hList
, 0), "Expected header as dialog item\n");
1377 DestroyWindow(hList
);
1379 /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1380 hList
= create_custom_listview_control(0);
1381 SendMessage(hList
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_HEADERDRAGDROP
);
1382 r
= SendMessage(hList
, LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
1383 ok(r
& LVS_EX_HEADERDRAGDROP
, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1384 DestroyWindow(hList
);
1386 /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1387 hList
= CreateWindow("SysListView32", "Test", LVS_REPORT
, 0, 0, 100, 100, NULL
, NULL
,
1388 GetModuleHandle(NULL
), 0);
1389 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1390 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1392 rect
.left
= LVIR_BOUNDS
;
1394 rect
.right
= rect
.bottom
= -10;
1395 r
= SendMessage(hList
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
1396 ok(r
!= 0, "Expected not-null LRESULT\n");
1398 hHeader
= (HWND
)SendMessage(hList
, LVM_GETHEADER
, 0, 0);
1399 ok(!IsWindow(hHeader
), "Header shouldn't be created\n");
1400 ok(NULL
== GetDlgItem(hList
, 0), "NULL dialog item expected\n");
1402 DestroyWindow(hList
);
1404 /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1405 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1406 hList
= create_listview_control(LVS_OWNERDRAWFIXED
);
1407 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_ownerdrawfixed_parent_seq
,
1408 "created with LVS_OWNERDRAWFIXED - parent seq", TRUE
);
1409 DestroyWindow(hList
);
1412 static void test_redraw(void)
1414 HWND hwnd
, hwndheader
;
1419 hwnd
= create_listview_control(0);
1420 hwndheader
= subclass_header(hwnd
);
1422 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1424 trace("invalidate & update\n");
1425 InvalidateRect(hwnd
, NULL
, TRUE
);
1427 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, redraw_listview_seq
, "redraw listview", FALSE
);
1429 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1431 /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1432 /* 1. Without backbuffer */
1433 res
= ListView_SetBkColor(hwnd
, CLR_NONE
);
1436 hdc
= GetWindowDC(hwndparent
);
1438 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1439 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1440 ok(r
!= 0, "Expected not zero result\n");
1441 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1442 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1444 res
= ListView_SetBkColor(hwnd
, CLR_DEFAULT
);
1447 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1448 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1449 ok(r
!= 0, "Expected not zero result\n");
1450 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1451 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1453 /* 2. With backbuffer */
1454 SendMessageA(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_DOUBLEBUFFER
,
1455 LVS_EX_DOUBLEBUFFER
);
1456 res
= ListView_SetBkColor(hwnd
, CLR_NONE
);
1459 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1460 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1461 ok(r
!= 0, "Expected not zero result\n");
1462 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, forward_erasebkgnd_parent_seq
,
1463 "forward WM_ERASEBKGND on CLR_NONE", FALSE
);
1465 res
= ListView_SetBkColor(hwnd
, CLR_DEFAULT
);
1468 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1469 r
= SendMessageA(hwnd
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0);
1470 todo_wine
ok(r
!= 0, "Expected not zero result\n");
1471 ok_sequence(sequences
, PARENT_FULL_SEQ_INDEX
, empty_seq
,
1472 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE
);
1474 ReleaseDC(hwndparent
, hdc
);
1476 DestroyWindow(hwnd
);
1479 static LRESULT WINAPI
cd_wndproc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1481 COLORREF clr
, c0ffee
= RGB(0xc0, 0xff, 0xee);
1483 if(msg
== WM_NOTIFY
) {
1484 NMHDR
*nmhdr
= (PVOID
)lp
;
1485 if(nmhdr
->code
== NM_CUSTOMDRAW
) {
1486 NMLVCUSTOMDRAW
*nmlvcd
= (PVOID
)nmhdr
;
1487 trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd
->nmcd
.dwDrawStage
);
1488 switch(nmlvcd
->nmcd
.dwDrawStage
) {
1490 SetBkColor(nmlvcd
->nmcd
.hdc
, c0ffee
);
1491 return CDRF_NOTIFYITEMDRAW
;
1492 case CDDS_ITEMPREPAINT
:
1493 nmlvcd
->clrTextBk
= CLR_DEFAULT
;
1494 return CDRF_NOTIFYSUBITEMDRAW
;
1495 case CDDS_ITEMPREPAINT
| CDDS_SUBITEM
:
1496 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1497 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1498 return CDRF_NOTIFYPOSTPAINT
;
1499 case CDDS_ITEMPOSTPAINT
| CDDS_SUBITEM
:
1500 clr
= GetBkColor(nmlvcd
->nmcd
.hdc
);
1501 todo_wine
ok(clr
== c0ffee
, "clr=%.8x\n", clr
);
1502 return CDRF_DODEFAULT
;
1504 return CDRF_DODEFAULT
;
1508 return DefWindowProcA(hwnd
, msg
, wp
, lp
);
1511 static void test_customdraw(void)
1516 hwnd
= create_listview_control(0);
1518 insert_column(hwnd
, 0);
1519 insert_column(hwnd
, 1);
1520 insert_item(hwnd
, 0);
1522 oldwndproc
= (WNDPROC
)SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
,
1523 (LONG_PTR
)cd_wndproc
);
1525 InvalidateRect(hwnd
, NULL
, TRUE
);
1528 SetWindowLongPtr(hwndparent
, GWLP_WNDPROC
, (LONG_PTR
)oldwndproc
);
1530 DestroyWindow(hwnd
);
1533 static void test_icon_spacing(void)
1535 /* LVM_SETICONSPACING */
1536 /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1542 hwnd
= create_custom_listview_control(LVS_ICON
);
1543 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1545 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, (WPARAM
)hwndparent
, (LPARAM
)NF_REQUERY
);
1546 expect(NFR_ANSI
, r
);
1548 /* reset the icon spacing to defaults */
1549 SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1551 /* now we can request what the defaults are */
1552 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1, -1));
1556 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1558 trace("test icon spacing\n");
1560 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(20, 30));
1561 ok(r
== MAKELONG(w
, h
) ||
1562 broken(r
== MAKELONG(w
, w
)), /* win98 */
1563 "Expected %d, got %d\n", MAKELONG(w
, h
), r
);
1565 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(25, 35));
1566 expect(MAKELONG(20,30), r
);
1568 r
= SendMessage(hwnd
, LVM_SETICONSPACING
, 0, MAKELPARAM(-1,-1));
1569 expect(MAKELONG(25,35), r
);
1571 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_icon_spacing_seq
, "test icon spacing seq", FALSE
);
1573 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1574 DestroyWindow(hwnd
);
1577 static void test_color(void)
1579 /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1586 COLORREF colors
[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE
, RGB(255,255,255)};
1588 hwnd
= create_listview_control(0);
1589 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1591 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1593 trace("test color seq\n");
1594 for (i
= 0; i
< 4; i
++)
1598 r
= SendMessage(hwnd
, LVM_SETBKCOLOR
, 0, color
);
1600 r
= SendMessage(hwnd
, LVM_GETBKCOLOR
, 0, color
);
1603 r
= SendMessage(hwnd
, LVM_SETTEXTCOLOR
, 0, color
);
1605 r
= SendMessage(hwnd
, LVM_GETTEXTCOLOR
, 0, color
);
1608 r
= SendMessage(hwnd
, LVM_SETTEXTBKCOLOR
, 0, color
);
1610 r
= SendMessage(hwnd
, LVM_GETTEXTBKCOLOR
, 0, color
);
1614 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_color_seq
, "test color seq", FALSE
);
1616 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1617 DestroyWindow(hwnd
);
1620 static void test_item_count(void)
1622 /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1635 static CHAR item0text
[] = "item0";
1636 static CHAR item1text
[] = "item1";
1637 static CHAR item2text
[] = "item2";
1639 hwnd
= create_listview_control(0);
1640 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1642 /* resize in dpiaware manner to fit all 3 items added */
1644 hOldFont
= SelectObject(hdc
, GetStockObject(SYSTEM_FONT
));
1645 GetTextMetricsA(hdc
, &tm
);
1646 /* 2 extra pixels for bounds and header border */
1647 height
= tm
.tmHeight
+ 2;
1648 SelectObject(hdc
, hOldFont
);
1651 GetWindowRect(hwnd
, &rect
);
1652 /* 3 items + 1 header + 1 to be sure */
1653 MoveWindow(hwnd
, 0, 0, rect
.right
- rect
.left
, 5 * height
, FALSE
);
1655 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1657 trace("test item count\n");
1659 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1663 item0
.mask
= LVIF_TEXT
;
1666 item0
.pszText
= item0text
;
1667 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1670 /* [item0, item1] */
1671 item1
.mask
= LVIF_TEXT
;
1674 item1
.pszText
= item1text
;
1675 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1678 /* [item0, item1, item2] */
1679 item2
.mask
= LVIF_TEXT
;
1682 item2
.pszText
= item2text
;
1683 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1686 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1689 /* [item0, item1] */
1690 r
= SendMessage(hwnd
, LVM_DELETEITEM
, 2, 0);
1693 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1697 r
= SendMessage(hwnd
, LVM_DELETEALLITEMS
, 0, 0);
1700 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1704 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1707 /* [item0, item1] */
1708 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1711 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1714 /* [item0, item1, item2] */
1715 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1718 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1721 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_item_count_seq
, "test item count seq", FALSE
);
1723 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1724 DestroyWindow(hwnd
);
1727 static void test_item_position(void)
1729 /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1738 static CHAR item0text
[] = "item0";
1739 static CHAR item1text
[] = "item1";
1740 static CHAR item2text
[] = "item2";
1742 hwnd
= create_custom_listview_control(LVS_ICON
);
1743 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1745 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1747 trace("test item position\n");
1750 item0
.mask
= LVIF_TEXT
;
1753 item0
.pszText
= item0text
;
1754 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item0
);
1757 /* [item0, item1] */
1758 item1
.mask
= LVIF_TEXT
;
1761 item1
.pszText
= item1text
;
1762 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item1
);
1765 /* [item0, item1, item2] */
1766 item2
.mask
= LVIF_TEXT
;
1769 item2
.pszText
= item2text
;
1770 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item2
);
1773 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 1, MAKELPARAM(10,5));
1775 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 1, (LPARAM
) &position
);
1777 expect2(10, 5, position
.x
, position
.y
);
1779 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 2, MAKELPARAM(0,0));
1781 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 2, (LPARAM
) &position
);
1783 expect2(0, 0, position
.x
, position
.y
);
1785 r
= SendMessage(hwnd
, LVM_SETITEMPOSITION
, 0, MAKELPARAM(20,20));
1787 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
) &position
);
1789 expect2(20, 20, position
.x
, position
.y
);
1791 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_itempos_seq
, "test item position seq", TRUE
);
1793 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1794 DestroyWindow(hwnd
);
1797 static void test_getorigin(void)
1805 position
.x
= position
.y
= 0;
1807 hwnd
= create_custom_listview_control(LVS_ICON
);
1808 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1809 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1810 trace("test get origin results\n");
1811 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1813 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1814 DestroyWindow(hwnd
);
1816 hwnd
= create_custom_listview_control(LVS_SMALLICON
);
1817 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1818 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1819 trace("test get origin results\n");
1820 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1822 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1823 DestroyWindow(hwnd
);
1825 hwnd
= create_custom_listview_control(LVS_LIST
);
1826 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1827 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1828 trace("test get origin results\n");
1829 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1831 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1832 DestroyWindow(hwnd
);
1834 hwnd
= create_custom_listview_control(LVS_REPORT
);
1835 ok(hwnd
!= NULL
, "failed to create a listview window\n");
1836 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1837 trace("test get origin results\n");
1838 r
= SendMessage(hwnd
, LVM_GETORIGIN
, 0, (LPARAM
)&position
);
1840 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1841 DestroyWindow(hwnd
);
1845 static void test_multiselect(void)
1847 typedef struct t_select_task
1858 int i
,j
,item_count
,selected_count
;
1859 static const int items
=5;
1865 static struct t_select_task task_list
[] = {
1866 { "using VK_DOWN", 0, VK_DOWN
, -1, -1 },
1867 { "using VK_UP", -1, VK_UP
, -1, -1 },
1868 { "using VK_END", 0, VK_END
, 1, -1 },
1869 { "using VK_HOME", -1, VK_HOME
, 1, -1 }
1873 hwnd
= create_listview_control(0);
1875 for (i
=0;i
<items
;i
++) {
1876 insert_item(hwnd
, 0);
1879 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1881 expect(items
,item_count
);
1884 task
= task_list
[i
];
1886 /* deselect all items */
1887 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1888 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1890 /* set initial position */
1891 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, (task
.initPos
== -1 ? item_count
-1 : task
.initPos
));
1892 ListView_SetItemState(hwnd
,(task
.initPos
== -1 ? item_count
-1 : task
.initPos
),LVIS_SELECTED
,LVIS_SELECTED
);
1894 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1896 ok(selected_count
== 1, "There should be only one selected item at the beginning (is %d)\n",selected_count
);
1898 /* Set SHIFT key pressed */
1899 GetKeyboardState(kstate
);
1900 kstate
[VK_SHIFT
]=0x80;
1901 SetKeyboardState(kstate
);
1903 for (j
=1;j
<=(task
.count
== -1 ? item_count
: task
.count
);j
++) {
1904 r
= SendMessage(hwnd
, WM_KEYDOWN
, task
.loopVK
, 0);
1906 r
= SendMessage(hwnd
, WM_KEYUP
, task
.loopVK
, 0);
1910 selected_count
= (int)SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1912 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
);
1914 /* Set SHIFT key released */
1915 GetKeyboardState(kstate
);
1916 kstate
[VK_SHIFT
]=0x00;
1917 SetKeyboardState(kstate
);
1919 DestroyWindow(hwnd
);
1921 /* make multiple selection, then switch to LVS_SINGLESEL */
1922 hwnd
= create_listview_control(0);
1923 for (i
=0;i
<items
;i
++) {
1924 insert_item(hwnd
, 0);
1926 item_count
= (int)SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
1927 expect(items
,item_count
);
1928 /* deselect all items */
1929 ListView_SetItemState(hwnd
, -1, 0, LVIS_SELECTED
);
1930 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1932 ListView_SetItemState(hwnd
, i
, LVIS_SELECTED
, LVIS_SELECTED
);
1935 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1937 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1941 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1942 ok(!(style
& LVS_SINGLESEL
), "LVS_SINGLESEL isn't expected\n");
1943 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SINGLESEL
);
1944 /* check that style is accepted */
1945 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
1946 ok(style
& LVS_SINGLESEL
, "LVS_SINGLESEL expected\n");
1949 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1950 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1952 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1954 SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1957 /* select one more */
1958 ListView_SetItemState(hwnd
, 3, LVIS_SELECTED
, LVIS_SELECTED
);
1961 r
= ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
);
1962 ok(!(r
& LVIS_SELECTED
), "Expected item %d to be unselected\n", i
);
1964 r
= ListView_GetItemState(hwnd
, 3, LVIS_SELECTED
);
1965 ok(r
& LVIS_SELECTED
, "Expected item %d to be selected\n", i
);
1967 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
1969 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
1973 /* try to select all on LVS_SINGLESEL */
1974 memset(&item
, 0, sizeof(item
));
1975 item
.stateMask
= LVIS_SELECTED
;
1976 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1978 SendMessage(hwnd
, LVM_SETSELECTIONMARK
, 0, -1);
1980 item
.stateMask
= LVIS_SELECTED
;
1981 item
.state
= LVIS_SELECTED
;
1982 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
1985 r
= ListView_GetSelectedCount(hwnd
);
1987 r
= ListView_GetSelectionMark(hwnd
);
1990 /* try to deselect all on LVS_SINGLESEL */
1991 item
.stateMask
= LVIS_SELECTED
;
1992 item
.state
= LVIS_SELECTED
;
1993 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
1996 item
.stateMask
= LVIS_SELECTED
;
1998 r
= SendMessage(hwnd
, LVM_SETITEMSTATE
, -1, (LPARAM
)&item
);
2000 r
= ListView_GetSelectedCount(hwnd
);
2003 DestroyWindow(hwnd
);
2006 static void test_subitem_rect(void)
2013 /* test LVM_GETSUBITEMRECT for header */
2014 hwnd
= create_listview_control(0);
2015 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2016 /* add some columns */
2017 memset(&col
, 0, sizeof(LVCOLUMN
));
2018 col
.mask
= LVCF_WIDTH
;
2021 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 0, (LPARAM
)&col
);
2025 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 1, (LPARAM
)&col
);
2029 r
= SendMessage(hwnd
, LVM_INSERTCOLUMN
, 2, (LPARAM
)&col
);
2031 /* item = -1 means header, subitem index is 1 based */
2032 rect
.left
= LVIR_BOUNDS
;
2034 rect
.right
= rect
.bottom
= 0;
2035 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2038 rect
.left
= LVIR_BOUNDS
;
2040 rect
.right
= rect
.bottom
= 0;
2041 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2043 ok(r
!= 0, "Expected not-null LRESULT\n");
2044 expect(100, rect
.left
);
2045 expect(250, rect
.right
);
2047 expect(3, rect
.top
);
2049 rect
.left
= LVIR_BOUNDS
;
2051 rect
.right
= rect
.bottom
= 0;
2052 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2054 ok(r
!= 0, "Expected not-null LRESULT\n");
2055 expect(250, rect
.left
);
2056 expect(450, rect
.right
);
2058 expect(3, rect
.top
);
2060 /* item LVS_REPORT padding isn't applied to subitems */
2061 insert_item(hwnd
, 0);
2063 rect
.left
= LVIR_BOUNDS
;
2065 rect
.right
= rect
.bottom
= 0;
2066 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2067 ok(r
!= 0, "Expected not-null LRESULT\n");
2068 expect(100, rect
.left
);
2069 expect(250, rect
.right
);
2071 rect
.left
= LVIR_ICON
;
2073 rect
.right
= rect
.bottom
= 0;
2074 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2075 ok(r
!= 0, "Expected not-null LRESULT\n");
2076 /* no icon attached - zero width rectangle, with no left padding */
2077 expect(100, rect
.left
);
2078 expect(100, rect
.right
);
2080 rect
.left
= LVIR_LABEL
;
2082 rect
.right
= rect
.bottom
= 0;
2083 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, 0, (LPARAM
)&rect
);
2084 ok(r
!= 0, "Expected not-null LRESULT\n");
2085 /* same as full LVIR_BOUNDS */
2086 expect(100, rect
.left
);
2087 expect(250, rect
.right
);
2089 DestroyWindow(hwnd
);
2091 /* try it for non LVS_REPORT style */
2092 hwnd
= CreateWindow("SysListView32", "Test", LVS_ICON
, 0, 0, 100, 100, NULL
, NULL
,
2093 GetModuleHandle(NULL
), 0);
2094 rect
.left
= LVIR_BOUNDS
;
2096 rect
.right
= rect
.bottom
= -10;
2097 r
= SendMessage(hwnd
, LVM_GETSUBITEMRECT
, -1, (LPARAM
)&rect
);
2098 ok(r
== 0, "Expected not-null LRESULT\n");
2099 /* rect is unchanged */
2100 expect(0, rect
.left
);
2101 expect(-10, rect
.right
);
2102 expect(1, rect
.top
);
2103 expect(-10, rect
.bottom
);
2104 DestroyWindow(hwnd
);
2107 /* comparison callback for test_sorting */
2108 static INT WINAPI
test_CallBackCompare(LPARAM first
, LPARAM second
, LPARAM lParam
)
2110 if (first
== second
) return 0;
2111 return (first
> second
? 1 : -1);
2114 static void test_sorting(void)
2120 static CHAR names
[][5] = {"A", "B", "C", "D", "0"};
2123 hwnd
= create_listview_control(0);
2124 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2126 /* insert some items */
2127 item
.mask
= LVIF_PARAM
| LVIF_STATE
;
2128 item
.state
= LVIS_SELECTED
;
2132 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2135 item
.mask
= LVIF_PARAM
;
2139 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2142 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
2143 item
.state
= LVIS_SELECTED
;
2147 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2150 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2153 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2156 r
= SendMessage(hwnd
, LVM_SORTITEMS
, 0, (LPARAM
)test_CallBackCompare
);
2159 r
= SendMessage(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2161 r
= SendMessage(hwnd
, LVM_GETSELECTIONMARK
, 0, 0);
2163 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 0, LVIS_SELECTED
);
2165 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 1, LVIS_SELECTED
);
2166 expect(LVIS_SELECTED
, r
);
2167 r
= SendMessage(hwnd
, LVM_GETITEMSTATE
, 2, LVIS_SELECTED
);
2168 expect(LVIS_SELECTED
, r
);
2170 DestroyWindow(hwnd
);
2172 /* switch to LVS_SORTASCENDING when some items added */
2173 hwnd
= create_listview_control(0);
2174 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2176 item
.mask
= LVIF_TEXT
;
2179 item
.pszText
= names
[1];
2180 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2183 item
.mask
= LVIF_TEXT
;
2186 item
.pszText
= names
[2];
2187 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2190 item
.mask
= LVIF_TEXT
;
2193 item
.pszText
= names
[0];
2194 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2197 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2198 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
2199 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2200 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2202 /* no sorting performed when switched to LVS_SORTASCENDING */
2203 item
.mask
= LVIF_TEXT
;
2205 item
.pszText
= buff
;
2206 item
.cchTextMax
= sizeof(buff
);
2207 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2209 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2212 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2214 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2217 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2219 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2221 /* adding new item doesn't resort list */
2222 item
.mask
= LVIF_TEXT
;
2225 item
.pszText
= names
[3];
2226 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2229 item
.mask
= LVIF_TEXT
;
2231 item
.pszText
= buff
;
2232 item
.cchTextMax
= sizeof(buff
);
2233 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2235 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2238 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2240 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2243 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2245 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2248 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2250 ok(lstrcmp(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
2252 /* corner case - item should be placed at first position */
2253 item
.mask
= LVIF_TEXT
;
2256 item
.pszText
= names
[4];
2257 r
= SendMessage(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
) &item
);
2261 item
.pszText
= buff
;
2262 item
.cchTextMax
= sizeof(buff
);
2263 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2265 ok(lstrcmp(buff
, names
[4]) == 0, "Expected '%s', got '%s'\n", names
[4], buff
);
2268 item
.pszText
= buff
;
2269 item
.cchTextMax
= sizeof(buff
);
2270 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2272 ok(lstrcmp(buff
, names
[1]) == 0, "Expected '%s', got '%s'\n", names
[1], buff
);
2275 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2277 ok(lstrcmp(buff
, names
[2]) == 0, "Expected '%s', got '%s'\n", names
[2], buff
);
2280 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2282 ok(lstrcmp(buff
, names
[0]) == 0, "Expected '%s', got '%s'\n", names
[0], buff
);
2285 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
) &item
);
2287 ok(lstrcmp(buff
, names
[3]) == 0, "Expected '%s', got '%s'\n", names
[3], buff
);
2289 DestroyWindow(hwnd
);
2292 static void test_ownerdata(void)
2295 LONG_PTR style
, ret
;
2299 /* it isn't possible to set LVS_OWNERDATA after creation */
2302 win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2306 hwnd
= create_listview_control(0);
2307 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2308 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2309 ok(!(style
& LVS_OWNERDATA
) && style
, "LVS_OWNERDATA isn't expected\n");
2311 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2313 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
2314 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2315 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2316 "try to switch to LVS_OWNERDATA seq", FALSE
);
2318 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2319 ok(!(style
& LVS_OWNERDATA
), "LVS_OWNERDATA isn't expected\n");
2320 DestroyWindow(hwnd
);
2323 /* try to set LVS_OWNERDATA after creation just having it */
2324 hwnd
= create_listview_control(LVS_OWNERDATA
);
2325 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2326 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2327 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2329 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2331 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_OWNERDATA
);
2332 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2333 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2334 "try to switch to LVS_OWNERDATA seq", FALSE
);
2335 DestroyWindow(hwnd
);
2337 /* try to remove LVS_OWNERDATA after creation just having it */
2340 win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2344 hwnd
= create_listview_control(LVS_OWNERDATA
);
2345 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2346 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2347 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2349 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2351 ret
= SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_OWNERDATA
);
2352 ok(ret
== style
, "Expected set GWL_STYLE to succeed\n");
2353 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, listview_ownerdata_switchto_seq
,
2354 "try to switch to LVS_OWNERDATA seq", FALSE
);
2355 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2356 ok(style
& LVS_OWNERDATA
, "LVS_OWNERDATA is expected\n");
2357 DestroyWindow(hwnd
);
2360 /* try select an item */
2361 hwnd
= create_listview_control(LVS_OWNERDATA
);
2362 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2363 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2364 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2365 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2367 memset(&item
, 0, sizeof(item
));
2368 item
.stateMask
= LVIS_SELECTED
;
2369 item
.state
= LVIS_SELECTED
;
2370 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2372 res
= SendMessageA(hwnd
, LVM_GETSELECTEDCOUNT
, 0, 0);
2374 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2376 DestroyWindow(hwnd
);
2378 /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2379 hwnd
= create_listview_control(LVS_OWNERDATA
);
2380 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2381 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2382 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2383 res
= SendMessageA(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2385 memset(&item
, 0, sizeof(item
));
2386 item
.mask
= LVIF_STATE
;
2388 item
.stateMask
= LVIS_SELECTED
;
2389 item
.state
= LVIS_SELECTED
;
2390 res
= SendMessageA(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2392 DestroyWindow(hwnd
);
2394 /* check notifications after focused/selected changed */
2395 hwnd
= create_listview_control(LVS_OWNERDATA
);
2396 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2397 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2398 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2400 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2402 memset(&item
, 0, sizeof(item
));
2403 item
.stateMask
= LVIS_SELECTED
;
2404 item
.state
= LVIS_SELECTED
;
2405 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2408 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownderdata_select_focus_parent_seq
,
2409 "ownerdata select notification", TRUE
);
2411 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2413 memset(&item
, 0, sizeof(item
));
2414 item
.stateMask
= LVIS_FOCUSED
;
2415 item
.state
= LVIS_FOCUSED
;
2416 res
= SendMessageA(hwnd
, LVM_SETITEMSTATE
, 0, (LPARAM
)&item
);
2419 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ownderdata_select_focus_parent_seq
,
2420 "ownerdata focus notification", TRUE
);
2421 DestroyWindow(hwnd
);
2423 /* check notifications on LVM_GETITEM */
2424 /* zero callback mask */
2425 hwnd
= create_listview_control(LVS_OWNERDATA
);
2426 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2427 res
= SendMessageA(hwnd
, LVM_SETITEMCOUNT
, 1, 0);
2428 ok(res
!= 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2430 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2432 memset(&item
, 0, sizeof(item
));
2433 item
.stateMask
= LVIS_SELECTED
;
2434 item
.mask
= LVIF_STATE
;
2435 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2438 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
2439 "ownerdata getitem selected state 1", FALSE
);
2441 /* non zero callback mask but not we asking for */
2442 res
= SendMessageA(hwnd
, LVM_SETCALLBACKMASK
, LVIS_OVERLAYMASK
, 0);
2445 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2447 memset(&item
, 0, sizeof(item
));
2448 item
.stateMask
= LVIS_SELECTED
;
2449 item
.mask
= LVIF_STATE
;
2450 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2453 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
,
2454 "ownerdata getitem selected state 2", FALSE
);
2456 /* LVIS_OVERLAYMASK callback mask, asking for index */
2457 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2459 memset(&item
, 0, sizeof(item
));
2460 item
.stateMask
= LVIS_OVERLAYMASK
;
2461 item
.mask
= LVIF_STATE
;
2462 res
= SendMessageA(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
2465 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
2466 "ownerdata getitem selected state 2", FALSE
);
2468 DestroyWindow(hwnd
);
2470 /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
2471 hwnd
= create_listview_control(LVS_OWNERDATA
| LVS_SORTASCENDING
);
2472 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2473 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2474 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
2475 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2476 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
& ~LVS_SORTASCENDING
);
2477 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2478 ok(!(style
& LVS_SORTASCENDING
), "Expected LVS_SORTASCENDING not set\n");
2479 DestroyWindow(hwnd
);
2480 /* apparently it's allowed to switch these style on after creation */
2481 hwnd
= create_listview_control(LVS_OWNERDATA
);
2482 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2483 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2484 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
2485 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTASCENDING
);
2486 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2487 ok(style
& LVS_SORTASCENDING
, "Expected LVS_SORTASCENDING to be set\n");
2488 DestroyWindow(hwnd
);
2490 hwnd
= create_listview_control(LVS_OWNERDATA
);
2491 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2492 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2493 ok(style
& LVS_OWNERDATA
, "Expected LVS_OWNERDATA\n");
2494 SetWindowLongPtrA(hwnd
, GWL_STYLE
, style
| LVS_SORTDESCENDING
);
2495 style
= GetWindowLongPtrA(hwnd
, GWL_STYLE
);
2496 ok(style
& LVS_SORTDESCENDING
, "Expected LVS_SORTDESCENDING to be set\n");
2497 DestroyWindow(hwnd
);
2500 static void test_norecompute(void)
2502 static CHAR testA
[] = "test";
2508 /* self containing control */
2509 hwnd
= create_listview_control(0);
2510 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2511 memset(&item
, 0, sizeof(item
));
2512 item
.mask
= LVIF_TEXT
| LVIF_STATE
;
2514 item
.stateMask
= LVIS_SELECTED
;
2515 item
.state
= LVIS_SELECTED
;
2516 item
.pszText
= testA
;
2517 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2519 /* retrieve with LVIF_NORECOMPUTE */
2520 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2522 item
.pszText
= buff
;
2523 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2524 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2526 ok(lstrcmp(buff
, testA
) == 0, "Expected (%s), got (%s)\n", testA
, buff
);
2528 item
.mask
= LVIF_TEXT
;
2530 item
.pszText
= LPSTR_TEXTCALLBACK
;
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
);
2539 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2540 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2542 ok(item
.pszText
== LPSTR_TEXTCALLBACK
, "Expected (%p), got (%p)\n",
2543 LPSTR_TEXTCALLBACK
, (VOID
*)item
.pszText
);
2544 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq", FALSE
);
2546 DestroyWindow(hwnd
);
2549 hwnd
= create_listview_control(LVS_OWNERDATA
);
2550 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2552 item
.mask
= LVIF_STATE
;
2553 item
.stateMask
= LVIS_SELECTED
;
2554 item
.state
= LVIS_SELECTED
;
2556 res
= SendMessageA(hwnd
, LVM_INSERTITEM
, 0, (LPARAM
)&item
);
2559 item
.mask
= LVIF_TEXT
| LVIF_NORECOMPUTE
;
2561 item
.pszText
= buff
;
2562 item
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
2563 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2564 res
= SendMessageA(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
2566 ok(item
.pszText
== LPSTR_TEXTCALLBACK
, "Expected (%p), got (%p)\n",
2567 LPSTR_TEXTCALLBACK
, (VOID
*)item
.pszText
);
2568 ok_sequence(sequences
, PARENT_SEQ_INDEX
, empty_seq
, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE
);
2570 DestroyWindow(hwnd
);
2573 static void test_nosortheader(void)
2578 hwnd
= create_listview_control(0);
2579 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2581 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
2582 ok(IsWindow(header
), "header expected\n");
2584 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2585 ok(style
& HDS_BUTTONS
, "expected header to have HDS_BUTTONS\n");
2587 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2588 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
| LVS_NOSORTHEADER
);
2589 /* HDS_BUTTONS retained */
2590 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2591 ok(style
& HDS_BUTTONS
, "expected header to retain HDS_BUTTONS\n");
2593 DestroyWindow(hwnd
);
2595 /* create with LVS_NOSORTHEADER */
2596 hwnd
= create_listview_control(LVS_NOSORTHEADER
);
2597 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2599 header
= (HWND
)SendMessageA(hwnd
, LVM_GETHEADER
, 0, 0);
2600 ok(IsWindow(header
), "header expected\n");
2602 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2603 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
2605 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2606 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
& ~LVS_NOSORTHEADER
);
2607 /* not changed here */
2608 style
= GetWindowLongPtr(header
, GWL_STYLE
);
2609 ok(!(style
& HDS_BUTTONS
), "expected header to have no HDS_BUTTONS\n");
2611 DestroyWindow(hwnd
);
2614 static void test_setredraw(void)
2620 hwnd
= create_listview_control(0);
2621 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2623 /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2624 ListView seems to handle it internally without DefWinProc */
2626 /* default value first */
2627 ret
= SendMessage(hwnd
, WM_SETREDRAW
, TRUE
, 0);
2630 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2631 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
2632 ret
= SendMessage(hwnd
, WM_SETREDRAW
, FALSE
, 0);
2634 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
2635 ok(style
& WS_VISIBLE
, "Expected WS_VISIBLE to be set\n");
2637 DestroyWindow(hwnd
);
2640 static void test_hittest(void)
2646 static CHAR text
[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2649 HIMAGELIST himl
, himl2
;
2652 hwnd
= create_listview_control(0);
2653 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2655 /* LVS_REPORT with a single subitem (2 columns) */
2656 insert_column(hwnd
, 0);
2657 insert_column(hwnd
, 1);
2658 insert_item(hwnd
, 0);
2661 /* the only purpose of that line is to be as long as a half item rect */
2662 item
.pszText
= text
;
2663 r
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0, (LPARAM
)&item
);
2666 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
2668 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(100, 0));
2671 memset(&bounds
, 0, sizeof(bounds
));
2672 bounds
.left
= LVIR_BOUNDS
;
2673 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&bounds
);
2674 ok(bounds
.bottom
- bounds
.top
> 0, "Expected non zero item height\n");
2675 ok(bounds
.right
- bounds
.left
> 0, "Expected non zero item width\n");
2676 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pos
);
2679 /* LVS_EX_FULLROWSELECT not set, no icons attached */
2680 x
= pos
.x
+ 50; /* column half width */
2681 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2682 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, __LINE__
);
2683 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2684 x
= pos
.x
+ 150; /* outside column */
2685 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2686 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2687 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, TRUE
, TRUE
, TRUE
, __LINE__
);
2688 /* parent client area is 100x100 by default */
2689 MoveWindow(hwnd
, 0, 0, 300, 100, FALSE
);
2690 x
= pos
.x
+ 150; /* outside column */
2691 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2692 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_NOWHERE
, FALSE
, FALSE
, __LINE__
);
2693 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2694 /* the same with LVS_EX_FULLROWSELECT */
2695 SendMessage(hwnd
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
2696 x
= pos
.x
+ 150; /* outside column */
2697 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2698 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEM
, FALSE
, FALSE
, __LINE__
);
2699 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, FALSE
, FALSE
, FALSE
, __LINE__
);
2700 MoveWindow(hwnd
, 0, 0, 100, 100, FALSE
);
2701 x
= pos
.x
+ 150; /* outside column */
2702 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2703 test_lvm_hittest(hwnd
, x
, y
, -1, LVHT_TORIGHT
, FALSE
, FALSE
, __LINE__
);
2704 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 1, LVHT_ONITEMLABEL
, TRUE
, TRUE
, TRUE
, __LINE__
);
2705 /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
2706 himl
= ImageList_Create(16, 16, 0, 4, 4);
2707 ok(himl
!= NULL
, "failed to create imagelist\n");
2708 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
2709 ok(hbmp
!= NULL
, "failed to create bitmap\n");
2710 r
= ImageList_Add(himl
, hbmp
, 0);
2711 ok(r
== 0, "should be zero\n");
2712 hbmp
= CreateBitmap(16, 16, 1, 1, NULL
);
2713 ok(hbmp
!= NULL
, "failed to create bitmap\n");
2714 r
= ImageList_Add(himl
, hbmp
, 0);
2715 ok(r
== 1, "should be one\n");
2717 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
2718 ok(r
== 0, "should return zero\n");
2720 item
.mask
= LVIF_IMAGE
;
2724 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2728 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2729 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, __LINE__
);
2730 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2732 /* state icons indices are 1 based, check with valid index */
2733 item
.mask
= LVIF_STATE
;
2734 item
.state
= INDEXTOSTATEIMAGEMASK(1);
2735 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2738 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
2742 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2743 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, __LINE__
);
2744 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMSTATEICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2746 himl2
= (HIMAGELIST
)SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)NULL
);
2747 ok(himl2
== himl
, "should return handle\n");
2749 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
2750 ok(r
== 0, "should return zero\n");
2753 y
= pos
.y
+ (bounds
.bottom
- bounds
.top
) / 2;
2754 test_lvm_hittest(hwnd
, x
, y
, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, __LINE__
);
2755 test_lvm_subitemhittest(hwnd
, x
, y
, 0, 0, LVHT_ONITEMICON
, FALSE
, FALSE
, FALSE
, __LINE__
);
2757 DestroyWindow(hwnd
);
2760 static void test_getviewrect(void)
2767 hwnd
= create_listview_control(0);
2768 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2771 r
= SendMessage(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
2774 insert_column(hwnd
, 0);
2775 insert_column(hwnd
, 1);
2777 memset(&item
, 0, sizeof(item
));
2780 SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
2782 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 0, MAKELPARAM(100, 0));
2784 r
= SendMessage(hwnd
, LVM_SETCOLUMNWIDTH
, 1, MAKELPARAM(120, 0));
2787 rect
.left
= rect
.right
= rect
.top
= rect
.bottom
= -1;
2788 r
= SendMessage(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
2790 /* left is set to (2e31-1) - XP SP2 */
2791 expect(0, rect
.right
);
2792 expect(0, rect
.top
);
2793 expect(0, rect
.bottom
);
2795 /* switch to LVS_ICON */
2796 SetWindowLong(hwnd
, GWL_STYLE
, GetWindowLong(hwnd
, GWL_STYLE
) & ~LVS_REPORT
);
2798 rect
.left
= rect
.right
= rect
.top
= rect
.bottom
= -1;
2799 r
= SendMessage(hwnd
, LVM_GETVIEWRECT
, 0, (LPARAM
)&rect
);
2801 expect(0, rect
.left
);
2802 expect(0, rect
.top
);
2803 /* precise value differs for 2k, XP and Vista */
2804 ok(rect
.bottom
> 0, "Expected positive bottom value, got %d\n", rect
.bottom
);
2805 ok(rect
.right
> 0, "Expected positive right value, got %d\n", rect
.right
);
2807 DestroyWindow(hwnd
);
2810 static void test_getitemposition(void)
2817 hwnd
= create_listview_control(0);
2818 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2819 header
= subclass_header(hwnd
);
2821 /* LVS_REPORT, single item, no columns added */
2822 insert_item(hwnd
, 0);
2824 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2827 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
2829 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq1
, "get item position 1", FALSE
);
2831 /* LVS_REPORT, single item, single column */
2832 insert_column(hwnd
, 0);
2834 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
2837 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
2839 ok_sequence(sequences
, LISTVIEW_SEQ_INDEX
, getitemposition_seq2
, "get item position 2", TRUE
);
2841 memset(&rect
, 0, sizeof(rect
));
2842 SendMessage(header
, HDM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2845 /* offset by header height */
2846 expect(rect
.bottom
- rect
.top
, pt
.y
);
2848 DestroyWindow(hwnd
);
2851 static void test_columnscreation(void)
2856 hwnd
= create_listview_control(0);
2857 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2859 insert_item(hwnd
, 0);
2861 /* headers columns aren't created automatically */
2862 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
2863 ok(IsWindow(header
), "Expected header handle\n");
2864 r
= SendMessage(header
, HDM_GETITEMCOUNT
, 0, 0);
2867 DestroyWindow(hwnd
);
2870 static void test_getitemrect(void)
2882 hwnd
= create_listview_control(0);
2883 ok(hwnd
!= NULL
, "failed to create a listview window\n");
2886 memset(&item
, 0, sizeof(item
));
2889 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
2892 rect
.left
= LVIR_BOUNDS
;
2893 rect
.right
= rect
.top
= rect
.bottom
= -1;
2894 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2897 /* zero width rectangle with no padding */
2898 expect(0, rect
.left
);
2899 expect(0, rect
.right
);
2901 insert_column(hwnd
, 0);
2902 insert_column(hwnd
, 1);
2904 col
.mask
= LVCF_WIDTH
;
2906 r
= SendMessage(hwnd
, LVM_SETCOLUMN
, 0, (LPARAM
)&col
);
2909 col
.mask
= LVCF_WIDTH
;
2911 r
= SendMessage(hwnd
, LVM_SETCOLUMN
, 1, (LPARAM
)&col
);
2914 rect
.left
= LVIR_BOUNDS
;
2915 rect
.right
= rect
.top
= rect
.bottom
= -1;
2916 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2919 /* still no left padding */
2920 expect(0, rect
.left
);
2921 expect(150, rect
.right
);
2923 rect
.left
= LVIR_SELECTBOUNDS
;
2924 rect
.right
= rect
.top
= rect
.bottom
= -1;
2925 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2928 expect(2, rect
.left
);
2930 rect
.left
= LVIR_LABEL
;
2931 rect
.right
= rect
.top
= rect
.bottom
= -1;
2932 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2934 /* padding, column width */
2935 expect(2, rect
.left
);
2936 expect(50, rect
.right
);
2938 /* no icons attached */
2939 rect
.left
= LVIR_ICON
;
2940 rect
.right
= rect
.top
= rect
.bottom
= -1;
2941 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2944 expect(2, rect
.left
);
2945 expect(2, rect
.right
);
2948 order
[0] = 1; order
[1] = 0;
2949 r
= SendMessage(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
2952 r
= SendMessage(hwnd
, LVM_GETITEMPOSITION
, 0, (LPARAM
)&pt
);
2954 /* 1 indexed column width + padding */
2955 todo_wine
expect(102, pt
.x
);
2956 /* rect is at zero too */
2957 rect
.left
= LVIR_BOUNDS
;
2958 rect
.right
= rect
.top
= rect
.bottom
= -1;
2959 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2961 expect(0, rect
.left
);
2962 /* just width sum */
2963 expect(150, rect
.right
);
2965 rect
.left
= LVIR_SELECTBOUNDS
;
2966 rect
.right
= rect
.top
= rect
.bottom
= -1;
2967 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
2969 /* column width + padding */
2970 todo_wine
expect(102, rect
.left
);
2972 /* back to initial order */
2973 order
[0] = 0; order
[1] = 1;
2974 r
= SendMessage(hwnd
, LVM_SETCOLUMNORDERARRAY
, 2, (LPARAM
)&order
);
2978 himl
= ImageList_Create(16, 16, 0, 2, 2);
2979 ok(himl
!= NULL
, "failed to create imagelist\n");
2980 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
2981 ok(hbm
!= NULL
, "failed to create bitmap\n");
2982 r
= ImageList_Add(himl
, hbm
, 0);
2983 ok(r
== 0, "should be zero\n");
2984 hbm
= CreateBitmap(16, 16, 1, 1, NULL
);
2985 ok(hbm
!= NULL
, "failed to create bitmap\n");
2986 r
= ImageList_Add(himl
, hbm
, 0);
2987 ok(r
== 1, "should be one\n");
2989 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)himl
);
2990 ok(r
== 0, "should return zero\n");
2992 item
.mask
= LVIF_STATE
;
2993 item
.state
= INDEXTOSTATEIMAGEMASK(1);
2994 item
.stateMask
= LVIS_STATEIMAGEMASK
;
2997 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
3001 rect
.left
= LVIR_ICON
;
3002 rect
.right
= rect
.top
= rect
.bottom
= -1;
3003 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3005 /* padding + stateicon width */
3006 expect(18, rect
.left
);
3007 expect(18, rect
.right
);
3009 rect
.left
= LVIR_LABEL
;
3010 rect
.right
= rect
.top
= rect
.bottom
= -1;
3011 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3013 /* padding + stateicon width -> column width */
3014 expect(18, rect
.left
);
3015 expect(50, rect
.right
);
3017 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)NULL
);
3018 ok(r
!= 0, "should return current list handle\n");
3020 r
= SendMessage(hwnd
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)himl
);
3021 ok(r
== 0, "should return zero\n");
3023 item
.mask
= LVIF_STATE
| LVIF_IMAGE
;
3026 item
.stateMask
= ~0;
3029 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
3033 rect
.left
= LVIR_ICON
;
3034 rect
.right
= rect
.top
= rect
.bottom
= -1;
3035 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3037 /* padding, icon width */
3038 expect(2, rect
.left
);
3039 expect(18, rect
.right
);
3041 rect
.left
= LVIR_LABEL
;
3042 rect
.right
= rect
.top
= rect
.bottom
= -1;
3043 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3045 /* padding + icon width -> column width */
3046 expect(18, rect
.left
);
3047 expect(50, rect
.right
);
3050 rect
.left
= LVIR_SELECTBOUNDS
;
3051 rect
.right
= rect
.top
= rect
.bottom
= -1;
3052 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3054 /* padding, column width */
3055 expect(2, rect
.left
);
3056 todo_wine
expect(50, rect
.right
);
3058 /* try with indentation */
3059 item
.mask
= LVIF_INDENT
;
3063 r
= SendMessage(hwnd
, LVM_SETITEM
, 0, (LPARAM
)&item
);
3067 rect
.left
= LVIR_BOUNDS
;
3068 rect
.right
= rect
.top
= rect
.bottom
= -1;
3069 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3071 /* padding + 1 icon width, column width */
3072 expect(0, rect
.left
);
3073 expect(150, rect
.right
);
3076 rect
.left
= LVIR_SELECTBOUNDS
;
3077 rect
.right
= rect
.top
= rect
.bottom
= -1;
3078 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3080 /* padding + 1 icon width, column width */
3081 expect(2 + 16, rect
.left
);
3082 todo_wine
expect(50, rect
.right
);
3085 rect
.left
= LVIR_LABEL
;
3086 rect
.right
= rect
.top
= rect
.bottom
= -1;
3087 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3089 /* padding + 2 icon widths, column width */
3090 expect(2 + 16*2, rect
.left
);
3091 expect(50, rect
.right
);
3094 rect
.left
= LVIR_ICON
;
3095 rect
.right
= rect
.top
= rect
.bottom
= -1;
3096 r
= SendMessage(hwnd
, LVM_GETITEMRECT
, 0, (LPARAM
)&rect
);
3098 /* padding + 1 icon width indentation, icon width */
3099 expect(2 + 16, rect
.left
);
3100 expect(34, rect
.right
);
3103 DestroyWindow(hwnd
);
3106 static void test_editbox(void)
3108 HWND hwnd
, hwndedit
, hwndedit2
;
3111 static CHAR testitemA
[] = "testitem";
3112 static CHAR testitem1A
[] = "testitem1";
3113 static CHAR buffer
[10];
3115 hwnd
= create_listview_control(LVS_EDITLABELS
);
3116 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3118 insert_column(hwnd
, 0);
3120 memset(&item
, 0, sizeof(item
));
3121 item
.mask
= LVIF_TEXT
;
3122 item
.pszText
= testitemA
;
3125 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3128 /* setting focus is necessary */
3130 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3131 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3133 /* modify initial string */
3134 r
= SendMessage(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
3136 /* return focus to listview */
3139 memset(&item
, 0, sizeof(item
));
3140 item
.mask
= LVIF_TEXT
;
3141 item
.pszText
= buffer
;
3142 item
.cchTextMax
= 10;
3145 r
= SendMessage(hwnd
, LVM_GETITEMA
, 0, (LPARAM
)&item
);
3148 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
3150 /* send LVM_EDITLABEL on already created edit */
3152 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3153 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3154 /* focus will be set to edit */
3155 ok(GetFocus() == hwndedit
, "Expected Edit window to be focused\n");
3156 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3157 ok(IsWindow(hwndedit2
), "Expected Edit window to be created\n");
3159 /* creating label disabled when control isn't focused */
3161 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3162 todo_wine
ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
3164 /* check EN_KILLFOCUS handling */
3165 memset(&item
, 0, sizeof(item
));
3166 item
.pszText
= testitemA
;
3169 r
= SendMessage(hwnd
, LVM_SETITEMTEXTA
, 0, (LPARAM
)&item
);
3173 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3174 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3175 /* modify edit and notify control that it lost focus */
3176 r
= SendMessage(hwndedit
, WM_SETTEXT
, 0, (LPARAM
)testitem1A
);
3178 r
= SendMessage(hwnd
, WM_COMMAND
, MAKEWPARAM(0, EN_KILLFOCUS
), (LPARAM
)hwndedit
);
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");
3188 /* end edit without saving */
3189 r
= SendMessage(hwndedit
, WM_KEYDOWN
, VK_ESCAPE
, 0);
3191 memset(&item
, 0, sizeof(item
));
3192 item
.pszText
= buffer
;
3193 item
.cchTextMax
= 10;
3196 r
= SendMessage(hwnd
, LVM_GETITEMTEXTA
, 0, (LPARAM
)&item
);
3197 expect(lstrlen(item
.pszText
), r
);
3198 ok(strcmp(buffer
, testitem1A
) == 0, "Expected item text to change\n");
3200 /* LVM_EDITLABEL with -1 destroys current edit */
3201 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_GETEDITCONTROL
, 0, 0);
3202 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
3203 /* no edit present */
3204 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, -1, 0);
3205 ok(hwndedit
== NULL
, "Expected Edit window not to be created\n");
3206 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3207 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3209 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
3210 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, -1, 0);
3211 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
3212 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
3213 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
3214 /* check another negative value */
3215 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3216 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3217 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
3218 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, -2, 0);
3219 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
3220 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
3221 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
3222 /* and value greater than max item index */
3223 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3224 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3225 ok(GetFocus() == hwndedit
, "Expected Edit to be focused\n");
3226 r
= SendMessage(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
3227 hwndedit2
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, r
, 0);
3228 ok(hwndedit2
== NULL
, "Expected Edit window not to be created\n");
3229 ok(!IsWindow(hwndedit
), "Expected Edit window to be destroyed\n");
3230 ok(GetFocus() == hwnd
, "Expected List to be focused\n");
3232 /* messaging tests */
3234 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3236 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3237 ok(IsWindow(hwndedit
), "Expected Edit window to be created\n");
3238 /* testing only sizing messages */
3239 ok_sequence(sequences
, EDITBOX_SEQ_INDEX
, editbox_create_pos
,
3240 "edit box create - sizing", TRUE
);
3242 DestroyWindow(hwnd
);
3245 static void test_notifyformat(void)
3250 hwnd
= create_listview_control(0);
3251 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3253 /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
3254 CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
3255 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3257 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
3259 r
= SendMessage(hwnd
, LVM_SETUNICODEFORMAT
, 1, 0);
3261 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3264 r
= SendMessage(hwnd
, LVM_SETUNICODEFORMAT
, 0, 0);
3266 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3271 win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
3272 DestroyWindow(hwnd
);
3276 DestroyWindow(hwnd
);
3278 /* test failure in parent WM_NOTIFYFORMAT */
3280 hwnd
= create_listview_control(0);
3281 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3282 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3283 ok(IsWindow(header
), "expected header to be created\n");
3284 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3286 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3288 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_QUERY
);
3289 ok(r
!= 0, "Expected valid format\n");
3291 notifyFormat
= NFR_UNICODE
;
3292 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
3293 expect(NFR_UNICODE
, r
);
3294 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3296 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3299 notifyFormat
= NFR_ANSI
;
3300 r
= SendMessage(hwnd
, WM_NOTIFYFORMAT
, 0, NF_REQUERY
);
3301 expect(NFR_ANSI
, r
);
3302 r
= SendMessage(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3304 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3307 DestroyWindow(hwnd
);
3309 /* try different unicode window combination and defaults */
3310 if (!GetModuleHandleW(NULL
))
3312 win_skip("Additional notify format tests are incompatible with Win9x\n");
3316 hwndparentW
= create_parent_window(TRUE
);
3317 ok(IsWindow(hwndparentW
), "Unicode parent creation failed\n");
3318 if (!IsWindow(hwndparentW
)) return;
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 error code defaulting to 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 /* receiving ansi code from unicode window, use it */
3342 notifyFormat
= NFR_ANSI
;
3343 hwnd
= create_listview_controlW(0, hwndparentW
);
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 */
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
);
3363 /* unicode listview with ansi parent window, return error code */
3365 hwnd
= create_listview_controlW(0, hwndparent
);
3366 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3367 header
= (HWND
)SendMessage(hwnd
, LVM_GETHEADER
, 0, 0);
3368 ok(IsWindow(header
), "expected header to be created\n");
3369 r
= SendMessageW(hwnd
, LVM_GETUNICODEFORMAT
, 0, 0);
3371 r
= SendMessage(header
, HDM_GETUNICODEFORMAT
, 0, 0);
3373 DestroyWindow(hwnd
);
3375 DestroyWindow(hwndparentW
);
3378 static void test_indentation(void)
3384 hwnd
= create_listview_control(0);
3385 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3387 memset(&item
, 0, sizeof(item
));
3388 item
.mask
= LVIF_INDENT
;
3390 item
.iIndent
= I_INDENTCALLBACK
;
3391 r
= SendMessage(hwnd
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3394 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3397 item
.mask
= LVIF_INDENT
;
3398 r
= SendMessage(hwnd
, LVM_GETITEM
, 0, (LPARAM
)&item
);
3401 ok_sequence(sequences
, PARENT_SEQ_INDEX
, single_getdispinfo_parent_seq
,
3402 "get indent dispinfo", FALSE
);
3404 DestroyWindow(hwnd
);
3407 static INT CALLBACK
DummyCompareEx(LPARAM first
, LPARAM second
, LPARAM param
)
3412 static BOOL
is_below_comctl_5(void)
3417 hwnd
= create_listview_control(0);
3418 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3419 insert_item(hwnd
, 0);
3421 ret
= SendMessage(hwnd
, LVM_SORTITEMSEX
, 0, (LPARAM
)&DummyCompareEx
);
3423 DestroyWindow(hwnd
);
3428 static void unload_v6_module(ULONG_PTR cookie
)
3431 BOOL (WINAPI
*pDeactivateActCtx
)(DWORD
, ULONG_PTR
);
3433 hKernel32
= GetModuleHandleA("kernel32.dll");
3434 pDeactivateActCtx
= (void*)GetProcAddress(hKernel32
, "DeactivateActCtx");
3435 if (!pDeactivateActCtx
)
3437 win_skip("Activation contexts unsupported\n");
3441 pDeactivateActCtx(0, cookie
);
3443 DeleteFileA(manifest_name
);
3446 static BOOL
load_v6_module(ULONG_PTR
*pcookie
)
3449 HANDLE (WINAPI
*pCreateActCtxA
)(ACTCTXA
*);
3450 BOOL (WINAPI
*pActivateActCtx
)(HANDLE
, ULONG_PTR
*);
3459 hKernel32
= GetModuleHandleA("kernel32.dll");
3460 pCreateActCtxA
= (void*)GetProcAddress(hKernel32
, "CreateActCtxA");
3461 pActivateActCtx
= (void*)GetProcAddress(hKernel32
, "ActivateActCtx");
3462 if (!(pCreateActCtxA
&& pActivateActCtx
))
3464 win_skip("Activation contexts unsupported. No version 6 tests possible.\n");
3468 /* create manifest */
3469 file
= CreateFileA( manifest_name
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
3470 if (file
!= INVALID_HANDLE_VALUE
)
3472 ret
= (WriteFile( file
, manifest
, sizeof(manifest
)-1, &written
, NULL
) &&
3473 written
== sizeof(manifest
)-1);
3474 CloseHandle( file
);
3477 DeleteFileA( manifest_name
);
3478 skip("Failed to fill manifest file. Skipping comctl32 V6 tests.\n");
3482 trace("created %s\n", manifest_name
);
3486 skip("Failed to create manifest file. Skipping comctl32 V6 tests.\n");
3490 memset(&ctx
, 0, sizeof(ctx
));
3491 ctx
.cbSize
= sizeof(ctx
);
3492 ctx
.lpSource
= manifest_name
;
3494 hCtx
= pCreateActCtxA(&ctx
);
3495 ok(hCtx
!= 0, "Expected context handle\n");
3497 ret
= pActivateActCtx(hCtx
, pcookie
);
3502 win_skip("A problem during context activation occurred.\n");
3503 DeleteFileA(manifest_name
);
3508 /* this is a XP SP3 failure workaround */
3509 hwnd
= CreateWindowExA(0, WC_LISTVIEW
, "foo",
3510 WS_CHILD
| WS_BORDER
| WS_VISIBLE
| LVS_REPORT
,
3512 hwndparent
, NULL
, GetModuleHandleA(NULL
), NULL
);
3513 if (!IsWindow(hwnd
))
3515 win_skip("FIXME: failed to create ListView window.\n");
3516 unload_v6_module(*pcookie
);
3520 DestroyWindow(hwnd
);
3526 static void test_get_set_view(void)
3532 /* test style->view mapping */
3533 hwnd
= create_listview_control(0);
3534 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3536 ret
= SendMessage(hwnd
, LVM_GETVIEW
, 0, 0);
3537 expect(LV_VIEW_DETAILS
, ret
);
3539 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3541 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
& ~LVS_REPORT
);
3542 ret
= SendMessage(hwnd
, LVM_GETVIEW
, 0, 0);
3543 expect(LV_VIEW_ICON
, ret
);
3545 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3546 SetWindowLongPtr(hwnd
, GWL_STYLE
, style
| LVS_SMALLICON
);
3547 ret
= SendMessage(hwnd
, LVM_GETVIEW
, 0, 0);
3548 expect(LV_VIEW_SMALLICON
, ret
);
3550 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3551 SetWindowLongPtr(hwnd
, GWL_STYLE
, (style
& ~LVS_SMALLICON
) | LVS_LIST
);
3552 ret
= SendMessage(hwnd
, LVM_GETVIEW
, 0, 0);
3553 expect(LV_VIEW_LIST
, ret
);
3555 /* switching view doesn't touch window style */
3556 ret
= SendMessage(hwnd
, LVM_SETVIEW
, LV_VIEW_DETAILS
, 0);
3558 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3559 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
3560 ret
= SendMessage(hwnd
, LVM_SETVIEW
, LV_VIEW_ICON
, 0);
3562 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3563 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
3564 ret
= SendMessage(hwnd
, LVM_SETVIEW
, LV_VIEW_SMALLICON
, 0);
3566 style
= GetWindowLongPtr(hwnd
, GWL_STYLE
);
3567 ok(style
& LVS_LIST
, "Expected style to be preserved\n");
3569 DestroyWindow(hwnd
);
3572 static void test_canceleditlabel(void)
3574 HWND hwnd
, hwndedit
;
3578 static CHAR test
[] = "test";
3579 static const CHAR test1
[] = "test1";
3581 hwnd
= create_listview_control(LVS_EDITLABELS
);
3582 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3584 insert_item(hwnd
, 0);
3586 /* try without edit created */
3587 ret
= SendMessage(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
3590 /* cancel without data change */
3592 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3593 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
3594 ret
= SendMessage(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
3596 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
3598 /* cancel after data change */
3599 memset(&itema
, 0, sizeof(itema
));
3600 itema
.pszText
= test
;
3601 ret
= SendMessage(hwnd
, LVM_SETITEMTEXT
, 0, (LPARAM
)&itema
);
3604 hwndedit
= (HWND
)SendMessage(hwnd
, LVM_EDITLABEL
, 0, 0);
3605 ok(IsWindow(hwndedit
), "Expected edit control to be created\n");
3606 ret
= SetWindowText(hwndedit
, test1
);
3607 ok(ret
!= 0, "Expected edit text to change\n");
3608 ret
= SendMessage(hwnd
, LVM_CANCELEDITLABEL
, 0, 0);
3610 ok(!IsWindow(hwndedit
), "Expected edit control to be destroyed\n");
3611 memset(&itema
, 0, sizeof(itema
));
3612 itema
.pszText
= buff
;
3613 itema
.cchTextMax
= sizeof(buff
)/sizeof(CHAR
);
3614 ret
= SendMessage(hwnd
, LVM_GETITEMTEXT
, 0, (LPARAM
)&itema
);
3616 ok(strcmp(buff
, test1
) == 0, "Expected label text not to change\n");
3618 DestroyWindow(hwnd
);
3621 static void test_mapidindex(void)
3626 /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
3627 hwnd
= create_listview_control(LVS_OWNERDATA
);
3628 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3629 insert_item(hwnd
, 0);
3630 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
3632 DestroyWindow(hwnd
);
3634 hwnd
= create_listview_control(0);
3635 ok(hwnd
!= NULL
, "failed to create a listview window\n");
3637 /* LVM_MAPINDEXTOID with invalid index */
3638 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
3641 insert_item(hwnd
, 0);
3642 insert_item(hwnd
, 1);
3644 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, -1, 0);
3646 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 2, 0);
3649 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
3651 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
3653 /* remove 0 indexed item, id retained */
3654 SendMessage(hwnd
, LVM_DELETEITEM
, 0, 0);
3655 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 0, 0);
3657 /* new id starts from previous value */
3658 insert_item(hwnd
, 1);
3659 ret
= SendMessage(hwnd
, LVM_MAPINDEXTOID
, 1, 0);
3662 /* get index by id */
3663 ret
= SendMessage(hwnd
, LVM_MAPIDTOINDEX
, -1, 0);
3665 ret
= SendMessage(hwnd
, LVM_MAPIDTOINDEX
, 0, 0);
3667 ret
= SendMessage(hwnd
, LVM_MAPIDTOINDEX
, 1, 0);
3669 ret
= SendMessage(hwnd
, LVM_MAPIDTOINDEX
, 2, 0);
3672 DestroyWindow(hwnd
);
3675 START_TEST(listview
)
3678 BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
3680 ULONG_PTR ctx_cookie
;
3682 hComctl32
= GetModuleHandleA("comctl32.dll");
3683 pInitCommonControlsEx
= (void*)GetProcAddress(hComctl32
, "InitCommonControlsEx");
3684 if (pInitCommonControlsEx
)
3686 INITCOMMONCONTROLSEX iccex
;
3687 iccex
.dwSize
= sizeof(iccex
);
3688 iccex
.dwICC
= ICC_LISTVIEW_CLASSES
;
3689 pInitCommonControlsEx(&iccex
);
3692 InitCommonControls();
3694 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
3696 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3697 hwndparent
= create_parent_window(FALSE
);
3698 ok_sequence(sequences
, PARENT_SEQ_INDEX
, create_parent_wnd_seq
, "create parent window", TRUE
);
3699 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
3701 g_is_below_5
= is_below_comctl_5();
3709 test_icon_spacing();
3712 test_item_position();
3717 test_subitem_rect();
3721 test_nosortheader();
3725 test_getitemposition();
3726 test_columnscreation();
3728 test_notifyformat();
3731 if (!load_v6_module(&ctx_cookie
))
3733 DestroyWindow(hwndparent
);
3737 /* comctl32 version 6 tests start here */
3738 test_get_set_view();
3739 test_canceleditlabel();
3742 unload_v6_module(ctx_cookie
);
3744 DestroyWindow(hwndparent
);